Add toolchain and mbtk source

Change-Id: Ie12546301367ea59240bf23d5e184ad7e36e40b3
diff --git a/mbtk/mbtk_ril/Makefile b/mbtk/mbtk_ril/Makefile
new file mode 100755
index 0000000..813d94b
--- /dev/null
+++ b/mbtk/mbtk_ril/Makefile
@@ -0,0 +1,44 @@
+ROOT = $(shell pwd)/../..
+include ../Make.defines
+
+LOCAL_PATH=$(BUILD_ROOT)/mbtk_ril
+
+INC_DIR += \
+		-I$(LOCAL_PATH)/inc \
+		-I$(BUILD_ROOT)/mbtk_lib/inc
+	
+LIB_DIR +=
+
+LIBS += -lmbtk_lib -lrilutil -lprop2uci -lmtel -laudio-apu -lcutils -ltinyalsa -lacm
+
+CFLAGS += 
+
+DEFINE +=
+
+MY_FILES_PATH:=$(LOCAL_PATH)/src
+#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))
+
+dtarget := $(OUT_DIR)/bin/mbtk_ril
+
+all: $(dtarget)
+
+$(dtarget):
+	@echo "  BIN     $@"
+	$(CC) $(CFLAGS) $(LOCAL_SRC_FILES) -o $@ $(DEFINE) $(INC_DIR) $(LIB_DIR) $(LIBS)
+
+clean:
+	
+
diff --git a/mbtk/mbtk_ril/inc/at_tok.h b/mbtk/mbtk_ril/inc/at_tok.h
new file mode 100755
index 0000000..a9725c0
--- /dev/null
+++ b/mbtk/mbtk_ril/inc/at_tok.h
@@ -0,0 +1,31 @@
+/* //device/system/reference-ril/at_tok.h
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef AT_TOK_H
+#define AT_TOK_H 1
+
+int at_tok_start(char **p_cur);
+int at_tok_nextint(char **p_cur, int *p_out);
+int at_tok_nexthexint(char **p_cur, int *p_out);
+
+int at_tok_nextbool(char **p_cur, char *p_out);
+int at_tok_nextstr(char **p_cur, char **out);
+
+int at_tok_hasmore(char **p_cur);
+
+#endif /*AT_TOK_H */
+
diff --git a/mbtk/mbtk_ril/inc/atchannel.h b/mbtk/mbtk_ril/inc/atchannel.h
new file mode 100755
index 0000000..b97cb27
--- /dev/null
+++ b/mbtk/mbtk_ril/inc/atchannel.h
@@ -0,0 +1,148 @@
+/* //device/system/reference-ril/atchannel.h
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ATCHANNEL_H
+#define ATCHANNEL_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "mbtk_type.h"
+
+/* define AT_DEBUG to send AT traffic to /tmp/radio-at.log" */
+#define AT_DEBUG  0
+
+#if AT_DEBUG
+extern void  AT_DUMP(const char* prefix, const char*  buff, int  len);
+#else
+#define  AT_DUMP(prefix,buff,len)  do{}while(0)
+#endif
+
+#define AT_ERROR_GENERIC          (-1)
+#define AT_ERROR_COMMAND_PENDING  (-2)
+#define AT_ERROR_CHANNEL_CLOSED   (-3)
+#define AT_ERROR_TIMEOUT          (-4)
+#define AT_ERROR_INVALID_THREAD   (-5) /* AT commands may not be issued from
+                                          reader thread (or unsolicited response
+                                          callback */
+#define AT_ERROR_INVALID_RESPONSE (-6) /* eg an at_send_command_singleline that
+                                          did not get back an intermediate
+                                          response */
+#define AT_ERROR_TIMEOUT_CLOSE    (-7)
+
+
+typedef enum
+{
+    NO_RESULT,   /* no intermediate response expected */
+    NUMERIC,     /* a single intermediate response starting with a 0-9 */
+    SINGLELINE,  /* a single intermediate response starting with a prefix */
+    MULTILINE    /* multiple line intermediate response
+                    starting with a prefix */
+} ATCommandType;
+
+/** a singly-lined list of intermediate responses */
+typedef struct ATLine
+{
+    struct ATLine *p_next;
+    char *line;
+} ATLine;
+
+/** Free this with at_response_free() */
+typedef struct
+{
+    int success;              /* true if final response indicates
+                                    success (eg "OK") */
+    char *finalResponse;      /* eg OK, ERROR */
+    ATLine  *p_intermediates; /* any intermediate responses */
+} ATResponse;
+
+typedef enum
+{
+    RIL_AT_STATE_CLOSED = 0,
+    RIL_AT_STATE_OPENED,
+    RIL_AT_STATE_CONNECTED,
+    RIL_AT_STATE_READY,
+    RIL_AT_STATE_BUSY
+} mbtk_ril_at_state_enum;
+
+/**
+ * a user-provided unsolicited response handler function
+ * this will be called from the reader thread, so do not block
+ * "s" is the line, and "sms_pdu" is either NULL or the PDU response
+ * for multi-line TS 27.005 SMS PDU responses (eg +CMT:)
+ */
+typedef void (*ATUnsolHandler)(const char *s, const char *sms_pdu);
+
+int at_open(int at_fd, int uart_fd, ATUnsolHandler h);
+void at_close();
+
+/* This callback is invoked on the command thread.
+   You should reset or handshake here to avoid getting out of sync */
+void at_set_on_timeout(void (*onTimeout)(void));
+/* This callback is invoked on the reader thread (like ATUnsolHandler)
+   when the input stream closes before you call at_close
+   (not when you call at_close())
+   You should still call at_close()
+   It may also be invoked immediately from the current thread if the read
+   channel is already closed */
+void at_set_on_reader_closed(void (*onClose)(void));
+
+int at_send_command_singleline (const char *command,
+                                const char *responsePrefix,
+                                ATResponse **pp_outResponse);
+int at_send_command_singleline_with_timeout (const char *command,
+        const char *responsePrefix,
+        ATResponse **pp_outResponse,long long timeoutMsec);
+
+int at_send_command_numeric (const char *command,
+                             ATResponse **pp_outResponse);
+
+int at_send_command_multiline (const char *command,
+                               const char *responsePrefix,
+                               ATResponse **pp_outResponse);
+
+
+int at_handshake();
+
+int at_send_command (const char *command, ATResponse **pp_outResponse);
+
+int at_send_command_sms (const char *command, const char *pdu,
+                         const char *responsePrefix,
+                         ATResponse **pp_outResponse);
+
+void at_response_free(ATResponse *p_response);
+
+typedef enum
+{
+    CME_ERROR_NON_CME = -1,
+    CME_SUCCESS = 0,
+    CME_SIM_NOT_INSERTED = 10,
+    CME_ERROR_UNKNOWN
+} AT_CME_Error;
+
+AT_CME_Error at_get_cme_error(const ATResponse *p_response);
+
+mbtk_ril_at_state_enum at_state_get();
+void at_state_set(mbtk_ril_at_state_enum state);
+bool at_rsp_check(ATResponse *p_response);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*ATCHANNEL_H*/
+
diff --git a/mbtk/mbtk_ril/inc/info_data.h b/mbtk/mbtk_ril/inc/info_data.h
new file mode 100755
index 0000000..c17cd80
--- /dev/null
+++ b/mbtk/mbtk_ril/inc/info_data.h
@@ -0,0 +1,65 @@
+/*
+*
+* Data : 2022/11/1 18:27:39
+* Author : LiuBin
+*/
+#ifndef _info_data_H
+#define _info_data_H
+#include "mbtk_type.h"
+#include "mbtk_list.h"
+#include "mbtk_log.h"
+#include "mbtk_utils.h"
+
+#define SOCK_CLIENT_MAX 100
+#define EPOLL_LISTEN_MAX 100
+#define IND_REGISTER_MAX 10
+#define PACK_PROCESS_QUEUE_MAX 20
+
+#define MBTK_APN_PROP "persist.mbtk.apn"
+#define MBTK_LTE_B28_SUPPORT 1
+
+typedef struct
+{
+    int fd;
+
+    uint32 ind_num;
+    uint16 ind_register[IND_REGISTER_MAX];
+} sock_client_info_t;
+
+typedef struct
+{
+    sock_client_info_t *cli_info;
+    void* pack;
+} info_queue_item_t;
+
+typedef struct
+{
+    int cid;
+
+    bool ipv4_valid;
+    uint8 ipv4[20];
+    bool ipv6_valid;
+    uint8 ipv6[50];
+} info_apn_ip_t;
+
+typedef enum {
+    INFO_URC_MSG_RADIO_STATE,
+    INFO_URC_MSG_CGEV,
+    INFO_URC_MSG_NET_CS_REG_STATE,
+    INFO_URC_MSG_NET_PS_REG_STATE,
+    INFO_URC_MSG_CALL_STATE,
+    INFO_URC_MSG_SIM_STATE,
+    INFO_URC_MSG_PDP_STATE,
+    INFO_URC_MSG_SMS_STATE,
+    INFO_URC_MSG_NET_STATE_LOG      // Save Network state into file.
+} info_urc_msg_id_enum;
+
+typedef struct {
+    info_urc_msg_id_enum msg;
+
+    void *data;
+    int data_len;
+} info_urc_msg_t;
+
+
+#endif /* _info_data_H */
diff --git a/mbtk/mbtk_ril/src/at_tok.c b/mbtk/mbtk_ril/src/at_tok.c
new file mode 100755
index 0000000..531afff
--- /dev/null
+++ b/mbtk/mbtk_ril/src/at_tok.c
@@ -0,0 +1,194 @@
+/* //device/system/reference-ril/at_tok.c
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "at_tok.h"
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "mbtk_log.h"
+/**
+ * Starts tokenizing an AT response string
+ * returns -1 if this is not a valid response string, 0 on success.
+ * updates *p_cur with current position
+ */
+int at_tok_start(char **p_cur)
+{
+    if (*p_cur == NULL) {
+        return -1;
+    }
+
+    // skip prefix
+    // consume "^[^:]:"
+
+    *p_cur = strchr(*p_cur, ':');
+
+    if (*p_cur == NULL) {
+        return -1;
+    }
+
+    (*p_cur)++;
+/*
+    while(**p_cur == ' ') {
+        (*p_cur)++;
+    }
+*/
+    return 0;
+}
+
+static void skipWhiteSpace(char **p_cur)
+{
+    if (*p_cur == NULL) return;
+
+    while (**p_cur != '\0' && isspace(**p_cur)) {
+        (*p_cur)++;
+    }
+}
+
+static void skipNextComma(char **p_cur)
+{
+    if (*p_cur == NULL) return;
+
+    while (**p_cur != '\0' && **p_cur != ',') {
+        (*p_cur)++;
+    }
+
+    if (**p_cur == ',') {
+        (*p_cur)++;
+    }
+}
+
+static char * nextTok(char **p_cur)
+{
+    char *ret = NULL;
+
+    skipWhiteSpace(p_cur);
+
+    if (*p_cur == NULL) {
+        ret = NULL;
+    } else if (**p_cur == '"') {
+        (*p_cur)++;
+        ret = strsep(p_cur, "\"");
+        skipNextComma(p_cur);
+    } else {
+        ret = strsep(p_cur, ",");
+    }
+
+    return ret;
+}
+
+
+/**
+ * Parses the next integer in the AT response line and places it in *p_out
+ * returns 0 on success and -1 on fail
+ * updates *p_cur
+ * "base" is the same as the base param in strtol
+ */
+
+static int at_tok_nextint_base(char **p_cur, int *p_out, int base, int  uns)
+{
+    char *ret;
+
+    if (*p_cur == NULL) {
+        return -1;
+    }
+
+    ret = nextTok(p_cur);
+
+    if (ret == NULL) {
+        return -1;
+    } else {
+        long l;
+        char *end;
+
+        if (uns)
+            l = strtoul(ret, &end, base);
+        else
+            l = strtol(ret, &end, base);
+
+        *p_out = (int)l;
+
+        if (end == ret) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * Parses the next base 10 integer in the AT response line
+ * and places it in *p_out
+ * returns 0 on success and -1 on fail
+ * updates *p_cur
+ */
+int at_tok_nextint(char **p_cur, int *p_out)
+{
+    return at_tok_nextint_base(p_cur, p_out, 10, 0);
+}
+
+/**
+ * Parses the next base 16 integer in the AT response line
+ * and places it in *p_out
+ * returns 0 on success and -1 on fail
+ * updates *p_cur
+ */
+int at_tok_nexthexint(char **p_cur, int *p_out)
+{
+    return at_tok_nextint_base(p_cur, p_out, 16, 1);
+}
+
+int at_tok_nextbool(char **p_cur, char *p_out)
+{
+    int ret;
+    int result;
+
+    ret = at_tok_nextint(p_cur, &result);
+
+    if (ret < 0) {
+        return -1;
+    }
+
+    // booleans should be 0 or 1
+    if (!(result == 0 || result == 1)) {
+        return -1;
+    }
+
+    if (p_out != NULL) {
+        *p_out = (char)result;
+    }
+
+    return ret;
+}
+
+int at_tok_nextstr(char **p_cur, char **p_out)
+{
+    if (*p_cur == NULL) {
+        return -1;
+    }
+
+    *p_out = nextTok(p_cur);
+
+    return 0;
+}
+
+/** returns 1 on "has more tokens" and 0 if no */
+int at_tok_hasmore(char **p_cur)
+{
+    return ! (*p_cur == NULL || **p_cur == '\0');
+}
+
diff --git a/mbtk/mbtk_ril/src/atchannel.c b/mbtk/mbtk_ril/src/atchannel.c
new file mode 100755
index 0000000..a1a9f21
--- /dev/null
+++ b/mbtk/mbtk_ril/src/atchannel.c
@@ -0,0 +1,1349 @@
+/* //device/system/reference-ril/atchannel.c
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "atchannel.h"
+#include "at_tok.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "mbtk_log.h"
+#include "mbtk_type.h"
+#include "mbtk_utils.h"
+
+#define MAX_AT_RESPONSE (8 * 1024)
+#define HANDSHAKE_RETRY_COUNT 20
+#define HANDSHAKE_TIMEOUT_MSEC 500
+#define AT_BUFF_MAX 100
+
+static pthread_t s_tid_reader;
+static int s_at_fd = -1;    /* fd of the AT channel */
+static int s_uart_fd = -1;    /* fd of the UART channel */
+
+static ATUnsolHandler s_unsolHandler;
+
+/* for input buffering */
+
+static char s_ATBuffer[MAX_AT_RESPONSE+1];
+static char *s_ATBufferCur = s_ATBuffer;
+static char s_UartBuffer[MAX_AT_RESPONSE+1];
+static char *s_UartBufferCur = s_UartBuffer;
+
+static mbtk_ril_at_state_enum at_state = RIL_AT_STATE_CLOSED;
+
+#if AT_DEBUG
+void  AT_DUMP(const char*  prefix, const char*  buff, int  len)
+{
+    if (len < 0)
+        len = strlen(buff);
+    LOGD("%.*s", len, buff);
+}
+#endif
+
+/*
+ * There is one reader thread |s_tid_reader| and potentially multiple writer
+ * threads. |s_commandmutex| and |s_commandcond| are used to maintain the
+ * condition that the writer thread will not read from |sp_response| until the
+ * reader thread has signaled itself is finished, etc. |s_writeMutex| is used to
+ * prevent multiple writer threads from calling at_send_command_full_nolock
+ * function at the same time.
+ */
+
+// "Wait" when AT process...
+static pthread_mutex_t s_commandmutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t s_commandcond = PTHREAD_COND_INITIALIZER;
+
+static ATCommandType s_type;
+static const char *s_responsePrefix = NULL;
+static const char *s_smsPDU = NULL;
+static ATResponse *sp_response = NULL;
+static char s_curr_at[AT_BUFF_MAX];
+
+static void (*s_onTimeout)(void) = NULL;
+static void (*s_onReaderClosed)(void) = NULL;
+static int s_readerClosed;
+
+static void onReaderClosed();
+static int writeCtrlZ (const char *s);
+static int writeline (const char *s);
+
+typedef struct
+{
+    char *at_command;
+    long long timeout;  // ms
+    bool timeout_close; // Close AT or not while AT response timeout.
+} at_timeout_t;
+
+static at_timeout_t at_timeout_list[] =
+{
+    {"AT+CRSM", 10000, false},
+//    {"AT+COPS", 60000, false}
+};
+
+#define NS_PER_S 1000000000
+static void setTimespecRelative(struct timespec *p_ts, long long msec)
+{
+    struct timeval tv;
+
+    gettimeofday(&tv, (struct timezone *) NULL);
+
+    p_ts->tv_sec = tv.tv_sec + (msec / 1000);
+    p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L;
+    /* assuming tv.tv_usec < 10^6 */
+    if (p_ts->tv_nsec >= NS_PER_S)
+    {
+        p_ts->tv_sec++;
+        p_ts->tv_nsec -= NS_PER_S;
+    }
+}
+
+static void sleepMsec(long long msec)
+{
+    struct timespec ts;
+    int err;
+
+    ts.tv_sec = (msec / 1000);
+    ts.tv_nsec = (msec % 1000) * 1000 * 1000;
+
+    do
+    {
+        err = nanosleep (&ts, &ts);
+    }
+    while (err < 0 && errno == EINTR);
+}
+
+
+
+/** add an intermediate response to sp_response*/
+static void addIntermediate(const char *line)
+{
+    ATLine *p_new;
+
+    p_new = (ATLine  *) malloc(sizeof(ATLine));
+
+    p_new->line = strdup(line);
+
+//    LOGD("line:%s", line);
+//    LOGD("line-1:%s", p_new->line);
+
+    /* note: this adds to the head of the list, so the list
+       will be in reverse order of lines received. the order is flipped
+       again before passing on to the command issuer */
+    p_new->p_next = sp_response->p_intermediates;
+    sp_response->p_intermediates = p_new;
+}
+
+
+/**
+ * returns 1 if line is a final response indicating error
+ * See 27.007 annex B
+ * WARNING: NO CARRIER and others are sometimes unsolicited
+ */
+static const char * s_finalResponsesError[] =
+{
+    "ERROR",
+    "+CMS ERROR:",
+    "+CME ERROR:",
+//    "NO CARRIER", /* sometimes! */ // Only for ATD ?
+    "NO ANSWER",
+    "NO DIALTONE",
+};
+static int isFinalResponseError(const char *line)
+{
+    size_t i;
+
+    for (i = 0 ; i < ARRAY_SIZE(s_finalResponsesError) ; i++)
+    {
+        if (strStartsWith(line, s_finalResponsesError[i]))
+        {
+            return 1;
+        }
+    }
+
+    if(!strncasecmp(s_curr_at, "ATD", 3) && strStartsWith(line, "NO CARRIER"))
+    {
+        return 1;
+    }
+
+    return 0;
+}
+
+/**
+ * returns 1 if line is a final response indicating success
+ * See 27.007 annex B
+ * WARNING: NO CARRIER and others are sometimes unsolicited
+ */
+static const char * s_finalResponsesSuccess[] =
+{
+    "OK",
+//    "CONNECT"       /* some stacks start up data on another channel */
+};
+static int isFinalResponseSuccess(const char *line)
+{
+    size_t i;
+
+    for (i = 0 ; i < ARRAY_SIZE(s_finalResponsesSuccess) ; i++)
+    {
+        if (strStartsWith(line, s_finalResponsesSuccess[i]))
+        {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * returns 1 if line is a final response, either  error or success
+ * See 27.007 annex B
+ * WARNING: NO CARRIER and others are sometimes unsolicited
+ */
+static int isFinalResponse(const char *line)
+{
+    return isFinalResponseSuccess(line) || isFinalResponseError(line);
+}
+
+/**
+ * returns 1 if line is the first line in (what will be) a two-line
+ * SMS unsolicited response
+ */
+static const char * s_smsUnsoliciteds[] =
+{
+    "+CMT:",
+    "+CDS:",
+    "+CBM:"
+};
+static int isSMSUnsolicited(const char *line)
+{
+    size_t i;
+
+    for (i = 0 ; i < ARRAY_SIZE(s_smsUnsoliciteds) ; i++)
+    {
+        if (strStartsWith(line, s_smsUnsoliciteds[i]))
+        {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+
+/** assumes s_commandmutex is held */
+static void handleFinalResponse(const char *line)
+{
+    sp_response->finalResponse = strdup(line);
+
+    //LOGD("AT complete (pthread_cond_signal): %s",line);
+    pthread_cond_signal(&s_commandcond);
+}
+
+static void handleUnsolicited(const char *line)
+{
+    if (s_unsolHandler != NULL)
+    {
+        s_unsolHandler(line, NULL);
+    }
+}
+
+static void processLine(const char *line)
+{
+    pthread_mutex_lock(&s_commandmutex);
+//    LOGD("LINE : %s", line);
+    if (sp_response == NULL)
+    {
+        /* no command pending */
+        handleUnsolicited(line);
+    }
+    else if (isFinalResponseSuccess(line))
+    {
+        sp_response->success = 1;
+        handleFinalResponse(line);
+    }
+    else if (isFinalResponseError(line))
+    {
+        sp_response->success = 0;
+        handleFinalResponse(line);
+    }
+    else if (s_smsPDU != NULL && 0 == strcmp(line, "> "))
+    {
+        // See eg. TS 27.005 4.3
+        // Commands like AT+CMGS have a "> " prompt
+        writeCtrlZ(s_smsPDU);
+        s_smsPDU = NULL;
+    }
+    else switch (s_type)
+        {
+            case NO_RESULT:
+                handleUnsolicited(line);
+                break;
+            case NUMERIC:
+                if (sp_response->p_intermediates == NULL
+                    && isdigit(line[0])
+                   )
+                {
+                    addIntermediate(line);
+                }
+                else
+                {
+                    /* either we already have an intermediate response or
+                       the line doesn't begin with a digit */
+                    handleUnsolicited(line);
+                }
+                break;
+            case SINGLELINE:
+                if (sp_response->p_intermediates == NULL
+                    && strStartsWith (line, s_responsePrefix)
+                   )
+                {
+                    if(*line == '"')
+                    {
+                        char *line_temp = strdup(line);
+                        line_temp++;
+                        if(strlen(line_temp) > 0)
+                        {
+                            char *ptr = line_temp + strlen(line_temp) - 1;
+                            while(ptr >= line_temp && *ptr == '"')
+                            {
+                                *ptr = '\0';
+                                ptr--;
+                            }
+                        }
+                        addIntermediate(line_temp);
+                        free(line_temp);
+                    }
+                    else
+                    {
+                        addIntermediate(line);
+                    }
+                }
+                else
+                {
+                    /* we already have an intermediate response */
+                    handleUnsolicited(line);
+                }
+                break;
+            case MULTILINE:
+                if (strStartsWith (line, s_responsePrefix))
+                {
+                    addIntermediate(line);
+                }
+                else
+                {
+                    handleUnsolicited(line);
+                }
+                break;
+
+            default: /* this should never be reached */
+                LOGE("Unsupported AT command type %d\n", s_type);
+                handleUnsolicited(line);
+                break;
+        }
+
+    pthread_mutex_unlock(&s_commandmutex);
+}
+
+
+/**
+ * Returns a pointer to the end of the next line
+ * special-cases the "> " SMS prompt
+ *
+ * returns NULL if there is no complete line
+ */
+static char * findNextEOL(char *cur)
+{
+    if (cur[0] == '>' && cur[1] == ' ' && cur[2] == '\0')
+    {
+        /* SMS prompt character...not \r terminated */
+        return cur+2;
+    }
+
+    // Find next newline
+    while (*cur != '\0' && *cur != '\r' && *cur != '\n') cur++;
+
+    return *cur == '\0' ? NULL : cur;
+}
+
+
+/**
+ * Reads a line from the AT channel, returns NULL on timeout.
+ * Assumes it has exclusive read access to the FD
+ *
+ * This line is valid only until the next call to readline
+ *
+ * This function exists because as of writing, android libc does not
+ * have buffered stdio.
+ */
+
+static const char *readline()
+{
+    ssize_t count;
+
+    char *p_read = NULL;
+    char *p_eol = NULL;
+    char *ret;
+
+    /* this is a little odd. I use *s_ATBufferCur == 0 to
+     * mean "buffer consumed completely". If it points to a character, than
+     * the buffer continues until a \0
+     */
+    if (*s_ATBufferCur == '\0')
+    {
+        /* empty buffer */
+        s_ATBufferCur = s_ATBuffer;
+        *s_ATBufferCur = '\0';
+        p_read = s_ATBuffer;
+    }
+    else       /* *s_ATBufferCur != '\0' */
+    {
+        /* there's data in the buffer from the last read */
+
+        // skip over leading newlines
+        while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
+            s_ATBufferCur++;
+
+        p_eol = findNextEOL(s_ATBufferCur);
+
+        if (p_eol == NULL)
+        {
+            /* a partial line. move it up and prepare to read more */
+            size_t len;
+
+            len = strlen(s_ATBufferCur);
+
+            memmove(s_ATBuffer, s_ATBufferCur, len + 1);
+            p_read = s_ATBuffer + len;
+            s_ATBufferCur = s_ATBuffer;
+        }
+        /* Otherwise, (p_eol !- NULL) there is a complete line  */
+        /* that will be returned the while () loop below        */
+    }
+
+    while (p_eol == NULL)
+    {
+        if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer))
+        {
+            LOGE("ERROR: Input line exceeded buffer\n");
+            /* ditch buffer and start over again */
+            s_ATBufferCur = s_ATBuffer;
+            *s_ATBufferCur = '\0';
+            p_read = s_ATBuffer;
+        }
+
+        do
+        {
+            count = read(s_at_fd, p_read,
+                         MAX_AT_RESPONSE - (p_read - s_ATBuffer));
+            usleep(10000);
+        }
+        while (count < 0 && errno == EINTR);
+
+        if (count > 0)
+        {
+            AT_DUMP( "<< ", p_read, count );
+
+            p_read[count] = '\0';
+
+            // skip over leading newlines
+            while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
+                s_ATBufferCur++;
+
+            p_eol = findNextEOL(s_ATBufferCur);
+            p_read += count;
+        }
+        else if (count <= 0)
+        {
+            /* read error encountered or EOF reached */
+            if(count == 0)
+            {
+                LOGD("atchannel: EOF reached");
+            }
+            else
+            {
+                LOGD("atchannel: read error %s", strerror(errno));
+            }
+            return NULL;
+        }
+    }
+
+    /* a full line in the buffer. Place a \0 over the \r and return */
+
+    ret = s_ATBufferCur;
+    *p_eol = '\0';
+    s_ATBufferCur = p_eol + 1; /* this will always be <= p_read,    */
+    /* and there will be a \0 at *p_read */
+
+    LOGD("AT< %s", ret);
+    return ret;
+}
+
+static const char *readlineUrc()
+{
+    ssize_t count;
+
+    char *p_read = NULL;
+    char *p_eol = NULL;
+    char *ret;
+
+    /* this is a little odd. I use *s_ATBufferCur == 0 to
+     * mean "buffer consumed completely". If it points to a character, than
+     * the buffer continues until a \0
+     */
+    if (*s_UartBufferCur == '\0')
+    {
+        /* empty buffer */
+        s_UartBufferCur = s_UartBuffer;
+        *s_UartBufferCur = '\0';
+        p_read = s_UartBuffer;
+    }
+    else       /* *s_ATBufferCur != '\0' */
+    {
+        /* there's data in the buffer from the last read */
+
+        // skip over leading newlines
+        while (*s_UartBufferCur == '\r' || *s_UartBufferCur == '\n')
+            s_UartBufferCur++;
+
+        p_eol = findNextEOL(s_UartBufferCur);
+
+        if (p_eol == NULL)
+        {
+            /* a partial line. move it up and prepare to read more */
+            size_t len;
+
+            len = strlen(s_UartBufferCur);
+
+            memmove(s_UartBuffer, s_UartBufferCur, len + 1);
+            p_read = s_UartBuffer + len;
+            s_UartBufferCur = s_UartBuffer;
+        }
+        /* Otherwise, (p_eol !- NULL) there is a complete line  */
+        /* that will be returned the while () loop below        */
+    }
+
+    while (p_eol == NULL)
+    {
+        if (0 == MAX_AT_RESPONSE - (p_read - s_UartBuffer))
+        {
+            LOGE("ERROR: Input line exceeded buffer\n");
+            /* ditch buffer and start over again */
+            s_UartBufferCur = s_UartBuffer;
+            *s_UartBufferCur = '\0';
+            p_read = s_UartBuffer;
+        }
+
+        do
+        {
+            count = read(s_uart_fd, p_read,
+                         MAX_AT_RESPONSE - (p_read - s_UartBuffer));
+            usleep(10000);
+        }
+        while (count < 0 && errno == EINTR);
+
+        if (count > 0)
+        {
+            AT_DUMP( "<< ", p_read, count );
+
+            p_read[count] = '\0';
+
+            // skip over leading newlines
+            while (*s_UartBufferCur == '\r' || *s_UartBufferCur == '\n')
+                s_UartBufferCur++;
+
+            p_eol = findNextEOL(s_UartBufferCur);
+            p_read += count;
+        }
+        else if (count <= 0)
+        {
+            /* read error encountered or EOF reached */
+            if(count == 0)
+            {
+                LOGD("atchannel: EOF reached");
+            }
+            else
+            {
+                LOGD("atchannel: read error %s", strerror(errno));
+            }
+            return NULL;
+        }
+    }
+
+    /* a full line in the buffer. Place a \0 over the \r and return */
+
+    ret = s_UartBufferCur;
+    *p_eol = '\0';
+    s_UartBufferCur = p_eol + 1; /* this will always be <= p_read,    */
+    /* and there will be a \0 at *p_read */
+
+    LOGD("URC< %s", ret);
+    return ret;
+}
+
+
+
+static void onReaderClosed()
+{
+    LOGD("onReaderClosed()");
+    if (s_onReaderClosed != NULL && s_readerClosed == 0)
+    {
+
+        pthread_mutex_lock(&s_commandmutex);
+
+        s_readerClosed = 1;
+
+        pthread_cond_signal(&s_commandcond);
+
+        pthread_mutex_unlock(&s_commandmutex);
+
+        s_onReaderClosed();
+    }
+}
+
+typedef struct
+{
+    int cid;
+    bool act;
+    bool waitting;
+} info_cgact_wait_t;
+extern info_cgact_wait_t cgact_wait;
+
+static void *readerLoop(void *arg)
+{
+    UNUSED(arg);
+    for (;;)
+    {
+        const char * line;
+
+        line = readline();
+
+        if (line == NULL)
+        {
+            break;
+        }
+
+        if(strStartsWith(line, "MBTK_AT_READY")) {
+            //handleUnsolicited(line);
+            continue;
+        } else if(strStartsWith(line, "CONNECT")) {
+            if(cgact_wait.waitting && cgact_wait.act) {
+                cgact_wait.waitting = false;
+            }
+        }
+
+        if(isSMSUnsolicited(line))
+        {
+            char *line1;
+            const char *line2;
+
+            // The scope of string returned by 'readline()' is valid only
+            // till next call to 'readline()' hence making a copy of line
+            // before calling readline again.
+            line1 = strdup(line);
+            line2 = readline();
+
+            if (line2 == NULL)
+            {
+                free(line1);
+                break;
+            }
+
+            if (s_unsolHandler != NULL)
+            {
+                s_unsolHandler (line1, line2);
+            }
+            free(line1);
+        }
+        else
+        {
+            processLine(line);
+        }
+    }
+
+    onReaderClosed();
+
+    return NULL;
+}
+
+static void *readerUrcLoop(void *arg)
+{
+    UNUSED(arg);
+    for (;;)
+    {
+        const char *line;
+
+        line = readlineUrc();
+
+        if (line == NULL)
+        {
+            break;
+        }
+
+        handleUnsolicited(line);
+    }
+
+    onReaderClosed();
+
+    return NULL;
+}
+
+
+/**
+ * Sends string s to the radio with a \r appended.
+ * Returns AT_ERROR_* on error, 0 on success
+ *
+ * This function exists because as of writing, android libc does not
+ * have buffered stdio.
+ */
+static int writeline (const char *s)
+{
+    size_t cur = 0;
+    size_t len = strlen(s);
+    ssize_t written;
+
+    if (s_at_fd < 0 || s_readerClosed > 0)
+    {
+        return AT_ERROR_CHANNEL_CLOSED;
+    }
+
+    LOGD("AT> %s", s);
+
+    AT_DUMP( ">> ", s, strlen(s) );
+
+    memset(s_curr_at, 0x0, AT_BUFF_MAX);
+    memcpy(s_curr_at, s, strlen(s));
+
+    /* the main string */
+    while (cur < len)
+    {
+        do
+        {
+            written = write (s_at_fd, s + cur, len - cur);
+        }
+        while (written < 0 && errno == EINTR);
+
+        if (written < 0)
+        {
+            return AT_ERROR_GENERIC;
+        }
+
+        cur += written;
+    }
+
+    /* the \r  */
+
+    do
+    {
+        written = write (s_at_fd, "\r", 1);
+    }
+    while ((written < 0 && errno == EINTR) || (written == 0));
+
+    if (written < 0)
+    {
+        return AT_ERROR_GENERIC;
+    }
+
+    return 0;
+}
+
+static int writeCtrlZ (const char *s)
+{
+    size_t cur = 0;
+    size_t len = strlen(s);
+    ssize_t written;
+
+    if (s_at_fd < 0 || s_readerClosed > 0)
+    {
+        return AT_ERROR_CHANNEL_CLOSED;
+    }
+
+    LOGD("AT> %s^Z\n", s);
+
+    AT_DUMP( ">* ", s, strlen(s) );
+
+    /* the main string */
+    while (cur < len)
+    {
+        do
+        {
+            written = write (s_at_fd, s + cur, len - cur);
+        }
+        while (written < 0 && errno == EINTR);
+
+        if (written < 0)
+        {
+            return AT_ERROR_GENERIC;
+        }
+
+        cur += written;
+    }
+
+    /* the ^Z  */
+
+    do
+    {
+        written = write (s_at_fd, "\032", 1);
+    }
+    while ((written < 0 && errno == EINTR) || (written == 0));
+
+    if (written < 0)
+    {
+        return AT_ERROR_GENERIC;
+    }
+
+    return 0;
+}
+
+static void clearPendingCommand()
+{
+    if (sp_response != NULL)
+    {
+        at_response_free(sp_response);
+    }
+
+    sp_response = NULL;
+    s_responsePrefix = NULL;
+    s_smsPDU = NULL;
+}
+
+
+/**
+ * Starts AT handler on stream "fd'
+ * returns 0 on success, -1 on error
+ */
+int at_open(int at_fd, int uart_fd, ATUnsolHandler h)
+{
+    int ret;
+    pthread_attr_t attr;
+
+    s_at_fd = at_fd;
+    s_uart_fd = uart_fd;
+    s_unsolHandler = h;
+    s_readerClosed = 0;
+    s_responsePrefix = NULL;
+    s_smsPDU = NULL;
+    sp_response = NULL;
+
+    pthread_attr_init (&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+    ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);
+    if (ret < 0)
+    {
+        LOGE("AT thread create fail.");
+        return -1;
+    }
+
+    pthread_t uart_tid_reader;
+    ret = pthread_create(&uart_tid_reader, &attr, readerUrcLoop, &attr);
+    if (ret < 0)
+    {
+        LOGE("Uart thread create fail.");
+        return -1;
+    }
+
+    return 0;
+}
+
+/* FIXME is it ok to call this from the reader and the command thread? */
+void at_close()
+{
+    LOGD("at_close()");
+    if (s_at_fd >= 0)
+    {
+        close(s_at_fd);
+    }
+    if (s_uart_fd >= 0)
+    {
+        close(s_uart_fd);
+    }
+    s_at_fd = -1;
+    s_uart_fd = -1;
+
+    pthread_mutex_lock(&s_commandmutex);
+    s_readerClosed = 1;
+    pthread_cond_signal(&s_commandcond);
+    pthread_mutex_unlock(&s_commandmutex);
+    /* the reader thread should eventually die */
+
+    at_state = RIL_AT_STATE_CLOSED;
+}
+
+static ATResponse * at_response_new()
+{
+    return (ATResponse *) calloc(1, sizeof(ATResponse));
+}
+
+void at_response_free(ATResponse *p_response)
+{
+    ATLine *p_line;
+
+    if (p_response == NULL) return;
+
+    p_line = p_response->p_intermediates;
+
+    while (p_line != NULL)
+    {
+        ATLine *p_toFree;
+
+        p_toFree = p_line;
+        p_line = p_line->p_next;
+
+        free(p_toFree->line);
+        free(p_toFree);
+    }
+
+    free (p_response->finalResponse);
+    free (p_response);
+}
+
+/**
+ * The line reader places the intermediate responses in reverse order
+ * here we flip them back
+ */
+static void reverseIntermediates(ATResponse *p_response)
+{
+    ATLine *pcur,*pnext;
+
+    pcur = p_response->p_intermediates;
+    p_response->p_intermediates = NULL;
+
+    while (pcur != NULL)
+    {
+        pnext = pcur->p_next;
+        pcur->p_next = p_response->p_intermediates;
+        p_response->p_intermediates = pcur;
+        pcur = pnext;
+    }
+}
+
+static long long at_timeout_get(const char *at_command, bool *timeout_close)
+{
+    long long timeout = 0;
+    int i;
+    for(i = 0; i <  ARRAY_SIZE(at_timeout_list); i++)
+    {
+        if(!strncasecmp(at_command, at_timeout_list[i].at_command, strlen(at_timeout_list[i].at_command)))
+        {
+            timeout = at_timeout_list[i].timeout;
+            *timeout_close = at_timeout_list[i].timeout_close;
+            break;
+        }
+    }
+
+    return timeout;
+}
+
+/**
+ * Internal send_command implementation
+ * Doesn't lock or call the timeout callback
+ *
+ * timeoutMsec == 0 means infinite timeout
+ */
+static int at_send_command_full_nolock (const char *command, ATCommandType type,
+                                        const char *responsePrefix, const char *smspdu,
+                                        long long timeoutMsec, ATResponse **pp_outResponse)
+{
+    int err = 0;
+    bool tiemout_close = true;
+    struct timespec ts;
+    if(at_state == RIL_AT_STATE_READY)
+        at_state = RIL_AT_STATE_BUSY;
+
+    if(sp_response != NULL)
+    {
+        err = AT_ERROR_COMMAND_PENDING;
+        goto error;
+    }
+
+    err = writeline (command);
+
+    if (err < 0)
+    {
+        goto error;
+    }
+
+    s_type = type;
+    s_responsePrefix = responsePrefix;
+    s_smsPDU = smspdu;
+    sp_response = at_response_new();
+
+    if(timeoutMsec == 0)
+    {
+        timeoutMsec = at_timeout_get(command, &tiemout_close);
+    }
+
+    if (timeoutMsec != 0)
+    {
+        setTimespecRelative(&ts, timeoutMsec);
+    }
+
+    while (sp_response->finalResponse == NULL && s_readerClosed == 0)
+    {
+        //LOGD("AT wait time:%lld",timeoutMsec);
+        if (timeoutMsec != 0)
+        {
+            err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
+        }
+        else
+        {
+            err = pthread_cond_wait(&s_commandcond, &s_commandmutex);
+        }
+
+        //LOGD("AT continue:err - %d",err);
+        if (err == ETIMEDOUT)
+        {
+            if(tiemout_close)
+            {
+                err = AT_ERROR_TIMEOUT_CLOSE;
+            }
+            else
+            {
+                err = AT_ERROR_TIMEOUT;
+            }
+            goto error;
+        }
+    }
+
+    if (pp_outResponse == NULL)
+    {
+        at_response_free(sp_response);
+    }
+    else
+    {
+        /* line reader stores intermediate responses in reverse order */
+        reverseIntermediates(sp_response);
+        *pp_outResponse = sp_response;
+    }
+
+    sp_response = NULL;
+
+    if(s_readerClosed > 0)
+    {
+        err = AT_ERROR_CHANNEL_CLOSED;
+        goto error;
+    }
+
+    err = 0;
+error:
+    if(at_state == RIL_AT_STATE_BUSY)
+        at_state = RIL_AT_STATE_READY;
+    clearPendingCommand();
+
+    return err;
+}
+
+/**
+ * Internal send_command implementation
+ *
+ * timeoutMsec == 0 means infinite timeout
+ */
+static int at_send_command_full (const char *command, ATCommandType type,
+                                 const char *responsePrefix, const char *smspdu,
+                                 long long timeoutMsec, ATResponse **pp_outResponse)
+{
+    int err;
+
+    if (0 != pthread_equal(s_tid_reader, pthread_self()))
+    {
+        /* cannot be called from reader thread */
+        LOGE("cannot be called from reader thread.");
+        return AT_ERROR_INVALID_THREAD;
+    }
+
+    // Waitting for previous AT complete.
+    while(at_state == RIL_AT_STATE_BUSY)
+    {
+        usleep(10000);
+    }
+
+    pthread_mutex_lock(&s_commandmutex);
+
+    err = at_send_command_full_nolock(command, type,
+                                      responsePrefix, smspdu,
+                                      timeoutMsec, pp_outResponse);
+
+    pthread_mutex_unlock(&s_commandmutex);
+
+    if (err == AT_ERROR_TIMEOUT_CLOSE && s_onTimeout != NULL)
+    {
+        s_onTimeout();
+    }
+
+    return err;
+}
+
+
+/**
+ * Issue a single normal AT command with no intermediate response expected
+ *
+ * "command" should not include \r
+ * pp_outResponse can be NULL
+ *
+ * if non-NULL, the resulting ATResponse * must be eventually freed with
+ * at_response_free
+ */
+int at_send_command (const char *command, ATResponse **pp_outResponse)
+{
+    return at_send_command_full (command, NO_RESULT, NULL,
+                                 NULL, 0, pp_outResponse);
+}
+
+
+int at_send_command_singleline (const char *command,
+                                const char *responsePrefix,
+                                ATResponse **pp_outResponse)
+{
+    int err;
+
+    err = at_send_command_full (command, SINGLELINE, responsePrefix,
+                                NULL, 0, pp_outResponse);
+
+    if (err == 0 && pp_outResponse != NULL
+        && (*pp_outResponse)->success > 0
+        && (*pp_outResponse)->p_intermediates == NULL
+       )
+    {
+        /* successful command must have an intermediate response */
+        at_response_free(*pp_outResponse);
+        *pp_outResponse = NULL;
+        return AT_ERROR_INVALID_RESPONSE;
+    }
+
+    return err;
+}
+
+int at_send_command_singleline_with_timeout (const char *command,
+        const char *responsePrefix,
+        ATResponse **pp_outResponse,long long timeoutMsec)
+{
+    int err;
+
+    err = at_send_command_full (command, SINGLELINE, responsePrefix,
+                                NULL, timeoutMsec, pp_outResponse);
+
+    if (err == 0 && pp_outResponse != NULL
+        && (*pp_outResponse)->success > 0
+        && (*pp_outResponse)->p_intermediates == NULL
+       )
+    {
+        /* successful command must have an intermediate response */
+        at_response_free(*pp_outResponse);
+        *pp_outResponse = NULL;
+        return AT_ERROR_INVALID_RESPONSE;
+    }
+
+    return err;
+}
+
+
+
+int at_send_command_numeric (const char *command,
+                             ATResponse **pp_outResponse)
+{
+    int err;
+
+    err = at_send_command_full (command, NUMERIC, NULL,
+                                NULL, 0, pp_outResponse);
+
+    if (err == 0 && pp_outResponse != NULL
+        && (*pp_outResponse)->success > 0
+        && (*pp_outResponse)->p_intermediates == NULL
+       )
+    {
+        /* successful command must have an intermediate response */
+        at_response_free(*pp_outResponse);
+        *pp_outResponse = NULL;
+        return AT_ERROR_INVALID_RESPONSE;
+    }
+
+    return err;
+}
+
+
+int at_send_command_sms (const char *command,
+                         const char *pdu,
+                         const char *responsePrefix,
+                         ATResponse **pp_outResponse)
+{
+    int err;
+
+    err = at_send_command_full (command, SINGLELINE, responsePrefix,
+                                pdu, 0, pp_outResponse);
+
+    if (err == 0 && pp_outResponse != NULL
+        && (*pp_outResponse)->success > 0
+        && (*pp_outResponse)->p_intermediates == NULL
+       )
+    {
+        /* successful command must have an intermediate response */
+        at_response_free(*pp_outResponse);
+        *pp_outResponse = NULL;
+        return AT_ERROR_INVALID_RESPONSE;
+    }
+
+    return err;
+}
+
+
+int at_send_command_multiline (const char *command,
+                               const char *responsePrefix,
+                               ATResponse **pp_outResponse)
+{
+    int err;
+
+    err = at_send_command_full (command, MULTILINE, responsePrefix,
+                                NULL, 0, pp_outResponse);
+
+    return err;
+}
+
+
+/** This callback is invoked on the command thread */
+void at_set_on_timeout(void (*onTimeout)(void))
+{
+    s_onTimeout = onTimeout;
+}
+
+/**
+ *  This callback is invoked on the reader thread (like ATUnsolHandler)
+ *  when the input stream closes before you call at_close
+ *  (not when you call at_close())
+ *  You should still call at_close()
+ */
+
+void at_set_on_reader_closed(void (*onClose)(void))
+{
+    s_onReaderClosed = onClose;
+}
+
+
+/**
+ * Periodically issue an AT command and wait for a response.
+ * Used to ensure channel has start up and is active
+ */
+int at_handshake()
+{
+    int i;
+    int err = 0;
+
+    if (0 != pthread_equal(s_tid_reader, pthread_self()))
+    {
+        /* cannot be called from reader thread */
+        return AT_ERROR_INVALID_THREAD;
+    }
+    pthread_mutex_lock(&s_commandmutex);
+
+#if 0
+    for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++)
+    {
+        /* some stacks start with verbose off */
+        err = at_send_command_full_nolock("ATE0Q0V1", NO_RESULT,
+                                          NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL);
+
+        if (err == 0)
+        {
+            break;
+        }
+    }
+#else
+    err = at_send_command_full_nolock("ATE0Q0V1", NO_RESULT,
+                                          NULL, NULL, 0, NULL);
+#endif
+
+    if (err == 0)
+    {
+        /* pause for a bit to let the input buffer drain any unmatched OK's
+           (they will appear as extraneous unsolicited responses) */
+        sleepMsec(HANDSHAKE_TIMEOUT_MSEC);
+    }
+
+    pthread_mutex_unlock(&s_commandmutex);
+
+
+    return err;
+}
+
+/**
+ * Returns error code from response
+ * Assumes AT+CMEE=1 (numeric) mode
+ */
+int at_get_cme_error(const ATResponse *p_response)
+{
+    int ret;
+    int err;
+    char *p_cur;
+
+    if (p_response->success > 0)
+    {
+        return CME_SUCCESS;
+    }
+
+    if (p_response->finalResponse == NULL
+        || !strStartsWith(p_response->finalResponse, "+CME ERROR:")
+       )
+    {
+        return CME_ERROR_NON_CME;
+    }
+
+    p_cur = p_response->finalResponse;
+    err = at_tok_start(&p_cur);
+
+    if (err < 0)
+    {
+        return CME_ERROR_NON_CME;
+    }
+
+    err = at_tok_nextint(&p_cur, &ret);
+
+    if (err < 0)
+    {
+        return CME_ERROR_NON_CME;
+    }
+
+    return ret;
+}
+
+mbtk_ril_at_state_enum at_state_get()
+{
+    return at_state;
+}
+
+void at_state_set(mbtk_ril_at_state_enum state)
+{
+    at_state = state;
+}
+
+bool at_rsp_check(ATResponse *p_response)
+{
+    if(!p_response || !p_response->success)
+        return false;
+
+    return true;
+}
+
+void unused_func()
+{
+    isFinalResponse(NULL);
+}
+
diff --git a/mbtk/mbtk_ril/src/main.c b/mbtk/mbtk_ril/src/main.c
new file mode 100755
index 0000000..2c5922d
--- /dev/null
+++ b/mbtk/mbtk_ril/src/main.c
@@ -0,0 +1,1877 @@
+#include <stdio.h>

+#include <stdlib.h>

+#include <unistd.h>

+#include <sys/socket.h>

+#include <errno.h>

+#include <fcntl.h>

+#include <string.h>

+#include <netinet/in.h>

+#include <arpa/inet.h>

+#include <linux/un.h>

+#include <linux/netlink.h>

+#include <cutils/properties.h>

+#include <time.h>

+#include <sys/time.h>

+

+//#include "cploader.h"

+#include "mbtk_log.h"

+#include "mbtk_ifc.h"

+#include "mbtk_type.h"

+#include "atchannel.h"

+#include "at_tok.h"

+#include "mbtk_utils.h"

+#include "mbtk_task.h"

+#include "mbtk_info.h"

+#include "mbtk_ntp.h"

+#include "mbtk_net_control.h"

+#include "info_data.h"

+

+#define TEMP_FAILURE_RETRY(exp) ({         \

+    typeof (exp) _rc;                      \

+    do {                                   \

+        _rc = (exp);                       \

+    } while (_rc == -1 && errno == EINTR); \

+    _rc; })

+

+#define BUFFER_SIZE 2048

+#define UEVENT_USIM_DEV "/devices/virtual/usim_event/usim0"

+#define MBTK_BOOT_SERVER_READY "/etc/init.d/mbtk_boot_server_ready"

+

+struct cooling_device

+{

+    const char *name;

+    const char *action;

+    const char *path;

+    const char *event;

+    const char *subsystem;

+};

+static pthread_t uevnet_task_id;

+extern net_info_t net_info;

+extern mbtK_cell_pack_info_t cell_info;

+extern info_cgact_wait_t cgact_wait;

+extern bool at_process;

+

+void setRadioPower(int isOn);

+int urc_msg_distribute(bool async_process, info_urc_msg_id_enum msg, void *data, int data_len);

+int mbtk_signal_log(char *data);

+

+/* Called on command thread */

+static void onATTimeout()

+{

+    LOGI("AT channel timeout; closing\n");

+    at_close();

+}

+

+/* Called on command or reader thread */

+static void onATReaderClosed()

+{

+    LOGI("AT channel closed\n");

+    at_close();

+}

+

+//int req_time_set(int type, char *time, int *cme_err);

+static int metis_strptime(char *str_time)

+{

+    struct tm stm;

+    char dateTime[30];

+    struct timeval tv;

+    if(strptime(str_time, "%Y-%m-%d %H:%M:%S",&stm) != NULL)

+    {

+        time_t _t = mktime(&stm);

+        tv.tv_sec = _t;

+        if(settimeofday(&tv, NULL)) {

+            LOG("Set time fail:%d", errno);

+            return -1;

+        } else {

+            LOG("Set time to %s.", str_time);

+            return 0;

+        }

+    } else {

+        LOG("Set time fail.");

+        return -1;

+    }

+}

+

+static void* ntp_pthread_run(void* arg)

+{

+    // Waitting for network connected.

+    while(mbtk_net_state_get() == MBTK_NET_STATE_OFF) {

+        sleep(1);

+    }

+    LOG("Network is connected.");

+

+    char time_type[10];

+    while(1){

+        memset(time_type, 0, 10);

+        property_get("persist.mbtk.time_type", time_type, "0");

+    	if(atoi(time_type) == MBTK_TIME_TYPE_NTP) // NTP time

+    	{

+            char time_str[100] = {0};

+            time_t time = 0;

+            while((time = (time_t)mbtk_at_systime()) == 0) {

+                usleep(100000);

+            }

+            struct tm *tm_t;

+            tm_t = localtime(&time);

+            strftime(time_str,128,"%F %T",tm_t);

+

+            // NTP time

+            metis_strptime(time_str);

+    	} else {

+            break;

+    	}

+

+        sleep(64); // Sleep 64s.

+    }

+    return NULL;

+}

+

+static void ntp_thread_start()

+{

+    pthread_t ntp_pid;

+    pthread_attr_t thread_attr;

+    pthread_attr_init(&thread_attr);

+    if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))

+    {

+        LOG("pthread_attr_setdetachstate() fail.");

+        return;

+    }

+

+    if(pthread_create(&ntp_pid, &thread_attr, ntp_pthread_run, NULL))

+    {

+        LOG("pthread_create() fail.");

+    }

+}

+

+bool sms_cmt = false;

+mbtk_sim_card_info sim_info_reg={0};

+static void onUnsolicited(const char *s, const char *sms_pdu)

+{

+    LOGV("URC : %s", s);

+    // MBTK_AT_READY

+    if (strStartsWith(s, "MBTK_AT_READY")) // AT ready.

+    {

+

+    }

+#if 0

+    else if(strStartsWith(s, "*SIMDETEC:")) // *SIMDETEC:1,SIM

+    {

+        const char* ptr = strstr(s, ",");

+        if(ptr)

+        {

+            ptr++; // Jump ','

+            if(memcmp(ptr, "SIM", 3) == 0)

+                net_info.sim_state = MBTK_SIM_STATE_READY;

+            else

+                net_info.sim_state = MBTK_SIM_STATE_ABSENT;

+        }

+    }

+#endif

+    else if(strStartsWith(s, "*RADIOPOWER:")) // "*RADIOPOWER: 1"

+    {

+        const char* ptr = s + strlen("*RADIOPOWER:");

+        while(*ptr != '\0' && *ptr == ' ' )

+        {

+            ptr++;

+        }

+

+        uint8 state;

+        if(*ptr == '1') {

+            //net_info.radio_state = MBTK_RADIO_STATE_ON;

+            // mbtk_radio_ready_cb();

+            state = (uint8)1;

+        } else {

+            //net_info.radio_state = MBTK_RADIO_STATE_OFF;

+            state = (uint8)0;

+        }

+        urc_msg_distribute(true, INFO_URC_MSG_RADIO_STATE, &state, sizeof(uint8));

+    }

+    // "CONNECT"

+    else if(strStartsWith(s, "CONNECT"))

+    {

+        if(cgact_wait.waitting && cgact_wait.act) {

+            cgact_wait.waitting = false;

+        }

+

+        uint8 data_pdp;

+        data_pdp = 1;       //

+        urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+    }

+    // +CGEV:

+    // +CGEV: NW DEACT <cid>,<cid>

+    // +CGEV: ME DEACT <cid>,<cid>

+    // +CGEV: NW PDN DEACT <cid>

+    // +CGEV: ME PDN DEACT <cid>

+    // +CGEV: NW DETACH

+    // +CGEV: ME DETACH

+    //

+    // +CGEV: NW ACT <cid>,<cid>

+    // +CGEV: ME ACT <cid>,<cid>

+    // +CGEV: EPS PDN ACT <cid>

+    // +CGEV: ME PDN ACT <cid>,<reason>,<cid>

+    // +CGEV: ME PDN ACT <cid>,<reason>

+    // +CGEV: NW PDN ACT <cid>

+    // +CGEV: EPS ACT <cid>

+    // +CGEV: NW MODIFY <cid>,<reason>

+    // +CGEV: NW REATTACH

+    else if(strStartsWith(s, "+CGEV:"))

+    {

+        if(at_process) {

+            if(cgact_wait.act) {

+                if(strStartsWith(s, "+CGEV: ME PDN ACT ")) { // +CGEV: ME PDN ACT 15,4

+                    if(cgact_wait.cid == atoi(s + 18)) {

+                        cgact_wait.waitting = false;

+                    }

+

+                    uint8 data_pdp;

+                    char* tmp_s = memdup(s + 18,strlen(s + 18));

+                    char* free_ptr = tmp_s;

+                    char *line = tmp_s;

+                    int tmp_int;

+                    if (at_tok_start(&line) < 0)

+                    {

+                        goto at_PDP_CREG_EXIT;

+                    }

+                    if (at_tok_nextint(&line, &tmp_int) < 0)

+                    {

+                        goto at_PDP_CREG_EXIT;

+                    }

+                    if (at_tok_nextint(&line, &tmp_int) < 0)

+                    {

+                        goto at_PDP_CREG_EXIT;

+                    }

+                    data_pdp = tmp_int;

+at_PDP_CREG_EXIT:

+                    free(free_ptr);

+

+                    //data_pdp = (uint8)atoi(s + 20);  //reason

+                    if(cgact_wait.cid >= 1 && cgact_wait.cid < 8)

+                    {

+                        if(data_pdp == 0)

+                        {

+                            data_pdp = 25;

+                            urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                            //data_pdp = cgact_wait.cid + 200;

+                        }

+                        else if(data_pdp == 1)

+                        {

+                            data_pdp = 26;

+                            urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                        }

+                        else if(data_pdp == 2)

+                        {

+                            data_pdp = 27;

+                            urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                        }

+                        else if(data_pdp == 3)

+                        {

+                            data_pdp = 27;

+                            urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                        }

+                        else

+                        {

+

+                        }

+                        if(cgact_wait.cid != 0)

+                        {

+                            data_pdp = cgact_wait.cid + 200;

+                            urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                        }

+                    }

+                } else if(strStartsWith(s, "+CGEV: NW MODIFY ")) { // +CGEV: NW MODIFY 1,4

+                    if(cgact_wait.cid == atoi(s + 17)) {

+                        cgact_wait.waitting = false;

+                    }

+                }

+            } else {

+                if(strStartsWith(s, "+CGEV: ME PDN DEACT ")) { // +CGEV: ME PDN DEACT 1

+                    if(cgact_wait.cid == atoi(s + 20)) {

+                        cgact_wait.waitting = false;

+                    }

+                    uint8 data_pdp;

+                    data_pdp = 0;       //

+                    urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                    if(cgact_wait.cid != 0)

+                    {

+                        data_pdp = cgact_wait.cid + 100;

+                        urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                    }

+                }

+            }

+        } else {

+            // apn_state_set

+

+            // +CGEV: NW PDN DEACT <cid>

+

+            // +CGEV: EPS PDN ACT 1

+            // +CGEV: ME PDN ACT 8,1

+

+            // +CGEV: ME PDN ACT 2,4

+            uint8 data[2] = {0xFF};

+            if(strStartsWith(s, "+CGEV: NW PDN DEACT ")) { // +CGEV: NW PDN DEACT <cid>

+                //apn_state_set(atoi(s + 20), false);

+                data[0] = (uint8)0;

+                data[1] = (uint8)atoi(s + 20);

+

+                uint8 data_pdp;

+                data_pdp = 0;       //

+                urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                data_pdp = cgact_wait.cid + 100;

+                urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+            } else if(strStartsWith(s, "+CGEV: EPS PDN ACT ")) { // +CGEV: EPS PDN ACT <cid>

+                //apn_state_set(atoi(s + 19), true);

+                data[0] = (uint8)1;

+                data[1] = (uint8)atoi(s + 19);

+            } else if(strStartsWith(s, "+CGEV: ME PDN ACT ")) { // +CGEV: ME PDN ACT <cid>,1

+                //apn_state_set(atoi(s + 18), true);

+                data[0] = (uint8)1;

+                data[1] = (uint8)atoi(s + 18);

+

+                uint8 data_pdp;

+                char* tmp_s = memdup(s + 18,strlen(s + 18));

+                char* free_ptr = tmp_s;

+                char *line = tmp_s;

+                int tmp_int;

+                if (at_tok_start(&line) < 0)

+                {

+                    goto PDP_CREG_EXIT;

+                }

+                if (at_tok_nextint(&line, &tmp_int) < 0)

+                {

+                    goto PDP_CREG_EXIT;

+                }

+                if (at_tok_nextint(&line, &tmp_int) < 0)

+                {

+                    goto PDP_CREG_EXIT;

+                }

+                data_pdp = tmp_int;

+PDP_CREG_EXIT:

+                free(free_ptr);

+                //data_pdp = (uint8)atoi(s + 20);  //reason

+                if(data[1] >= 1 && data[1] < 8)

+                {

+                    if(data_pdp == 0)

+                    {

+                        data_pdp = 25;

+                        urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                    }

+                    else if(data_pdp == 1)

+                    {

+                        data_pdp = 26;

+                        urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                    }

+                    else if(data_pdp == 2)

+                    {

+                        data_pdp = 27;

+                        urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                    }

+                    else if(data_pdp == 3)

+                    {

+                        data_pdp = 27;

+                        urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                    }

+                    else

+                    {

+

+                    }

+                    if(cgact_wait.cid != 0)

+                    {

+                        data_pdp = cgact_wait.cid + 200;

+                        urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+                    }

+                }

+            } else {

+                LOGI("No process : %s", s);

+            }

+

+            urc_msg_distribute(true, INFO_URC_MSG_CGEV, data, sizeof(uint8) * 2);

+        }

+    }

+    // +CREG: 1, "8010", "000060a5", 0, 2, 0

+    // +CREG: 1, "8330", "06447347", 7, 2, 0

+    // +CEREG: 1, "8330", "06447347", 7

+    // $CREG: 1, "8330", "06447347", 7,"0d4", 2, 0

+    // $CREG: 1, "8010", "000060a7", 0,, 2, 0

+    // +CGREG: 1

+    else if(strStartsWith(s, "+CGREG:")     // GMS/WCDMA data registed.

+         || strStartsWith(s, "+CEREG:"))    // LTE data registed.

+    {

+        char* tmp_s = s + 7;

+        while(*tmp_s && *tmp_s == ' ')

+            tmp_s++;

+        uint8 data = (uint8)atoi(tmp_s); // Reg State.

+

+        urc_msg_distribute(true, INFO_URC_MSG_NET_PS_REG_STATE, &data, sizeof(uint8));

+    }

+    // +CREG: 1, "8010", "000060a5", 0, 2, 0

+    // +CREG: 1, "8330", "06447347", 7, 2, 0

+    // +CREG: 0

+    else if(strStartsWith(s, "+CREG:"))     // GMS/WCDMA/LTE CS registed.

+    {

+        uint8 data[3];

+        data[0] = (uint8)MBTK_NET_CS_STATE;

+        char* tmp_s = memdup(s,strlen(s));

+        char* free_ptr = tmp_s;

+        char *line = tmp_s;

+        int tmp_int;

+        char *tmp_str;

+        if (at_tok_start(&line) < 0)

+        {

+            goto CREG_EXIT;

+        }

+        if (at_tok_nextint(&line, &tmp_int) < 0)

+        {

+            goto CREG_EXIT;

+        }

+        data[1] = (uint8)tmp_int; // Reg State.

+        if (data[1])

+        {

+            if (at_tok_nextstr(&line, &tmp_str) < 0)

+            {

+                goto CREG_EXIT;

+            }

+            if (at_tok_nextstr(&line, &tmp_str) < 0)

+            {

+                goto CREG_EXIT;

+            }

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto CREG_EXIT;

+            }

+            data[2] = (uint8)tmp_int; // AcT

+        } else {

+            data[2] = (uint8)0xFF; // AcT

+        }

+        if(data[1] == 5)

+        {

+            uint8 data_pdp;

+            data_pdp = 5;       //

+            urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+        }

+        urc_msg_distribute(false, INFO_URC_MSG_NET_CS_REG_STATE, data, sizeof(data));

+CREG_EXIT:

+        free(free_ptr);

+    }

+    // +CLCC: 1, 1, 6, 0, 0, "18981911691", 129, "",, 0

+    else if(strStartsWith(s, "+CLCC:"))

+    {

+        mbtk_call_info_t reg;

+        reg.call_wait = MBTK_CLCC;

+        char* tmp_s = memdup(s,strlen(s));

+        char* free_ptr = tmp_s;

+        char *line = tmp_s;

+        int tmp_int;

+        char *tmp_str;

+        int err;

+

+        err = at_tok_start(&line);

+        if (err < 0)

+        {

+            goto CLCC_EXIT;

+        }

+        err = at_tok_nextint(&line, &tmp_int); // dir1

+        if (err < 0)

+        {

+            goto CLCC_EXIT;

+        }

+        reg.dir1 = (uint8)tmp_int;

+        err = at_tok_nextint(&line, &tmp_int);// dir

+        if (err < 0)

+        {

+            goto CLCC_EXIT;

+        }

+        reg.dir = (uint8)tmp_int;

+        err = at_tok_nextint(&line, &tmp_int);// state

+        if (err < 0)

+        {

+            goto CLCC_EXIT;

+        }

+        reg.state = (uint8)tmp_int;

+        err = at_tok_nextint(&line, &tmp_int);// mode

+        if (err < 0)

+        {

+            goto CLCC_EXIT;

+        }

+        reg.mode = (uint8)tmp_int;

+        err = at_tok_nextint(&line, &tmp_int);// mpty

+        if (err < 0)

+        {

+            goto CLCC_EXIT;

+        }

+        reg.mpty = (uint8)tmp_int;

+        err = at_tok_nextstr(&line, &tmp_str); // phone_number

+        if (err < 0)

+        {

+            goto CLCC_EXIT;

+        }

+

+        memset(reg.phone_number,0,sizeof(reg.phone_number));

+        memcpy(reg.phone_number, tmp_str, strlen(tmp_str));

+        err = at_tok_nextint(&line, &tmp_int);// tpye

+        if (err < 0)

+        {

+            goto CLCC_EXIT;

+        }

+        reg.type = (uint8)tmp_int;

+

+        urc_msg_distribute(false, INFO_URC_MSG_CALL_STATE, &reg, sizeof(mbtk_call_info_t));

+CLCC_EXIT:

+        free(free_ptr);

+    }

+    // +CPAS: 4

+    else if(strStartsWith(s, "+CPAS:"))

+    {

+        mbtk_call_info_t reg;

+        reg.call_wait = 0;

+        char* tmp_s = memdup(s,strlen(s));

+        char* free_ptr = tmp_s;

+        char *line = tmp_s;

+        int tmp_int;

+        int err;

+

+        memset(&reg,0,sizeof(reg));

+

+        err = at_tok_start(&line);

+        if (err < 0)

+        {

+            goto CPAS_EXIT;

+        }

+        err = at_tok_nextint(&line, &tmp_int);

+        if (err < 0)

+        {

+            goto CPAS_EXIT;

+        }

+        reg.pas = (uint8)tmp_int;

+        reg.call_wait = MBTK_CPAS;

+        urc_msg_distribute(false, INFO_URC_MSG_CALL_STATE, &reg, sizeof(mbtk_call_info_t));

+CPAS_EXIT:

+        free(free_ptr);

+    }

+    // +CALLDISCONNECT: 1

+    else if(strStartsWith(s, "+CALLDISCONNECT:"))

+    {

+        mbtk_call_info_t reg;

+        reg.call_wait = 0;

+        char* tmp_s = memdup(s,strlen(s));

+        char* free_ptr = tmp_s;

+        char *line = tmp_s;

+        int tmp_int;

+        int err;

+

+        memset(&reg,0,sizeof(reg));

+

+        err = at_tok_start(&line);

+        if (err < 0)

+        {

+            goto CALLDISCONNECTED_EXIT;

+        }

+        err = at_tok_nextint(&line, &tmp_int);

+        if (err < 0)

+        {

+            goto CALLDISCONNECTED_EXIT;

+        }

+        reg.disconnected_id = tmp_int;

+        reg.call_wait = MBTK_DISCONNECTED;

+        urc_msg_distribute(false, INFO_URC_MSG_CALL_STATE, &reg, sizeof(mbtk_call_info_t));

+

+CALLDISCONNECTED_EXIT:

+        free(free_ptr);

+    }

+    // *SIMDETEC:1,SIM

+    else if(strStartsWith(s, "*SIMDETEC:"))

+    {

+        sim_info_reg.sim = -1;

+        if(strStartsWith(s, "*SIMDETEC:1,NOS"))

+            sim_info_reg.sim = 0;

+        else if(strStartsWith(s, "*SIMDETEC:1,SIM"))

+            sim_info_reg.sim = 1;

+        if(sim_info_reg.sim == 0)

+        {

+            uint8 data_pdp;

+            data_pdp = 11;       //

+            urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+        }

+        urc_msg_distribute(false, INFO_URC_MSG_SIM_STATE, &sim_info_reg, sizeof(mbtk_sim_card_info));

+    }

+    // *EUICC:1

+/*0: SIM

+1: USIM

+2: TEST SIM

+3: TEST USIM

+4: UNKNOWN

+Note: *EUICC:

+*/

+    else if(strStartsWith(s, "*EUICC:"))

+    {

+        sim_info_reg.sim_card_type = -1;

+        if(strStartsWith(s, "*EUICC: 0"))

+            sim_info_reg.sim_card_type = 1;

+        else if(strStartsWith(s, "*EUICC: 1"))

+            sim_info_reg.sim_card_type = 2;

+        else if(strStartsWith(s, "*EUICC: 2"))

+            sim_info_reg.sim_card_type = 1;

+        else if(strStartsWith(s, "*EUICC: 3"))

+            sim_info_reg.sim_card_type = 2;

+        else if(strStartsWith(s, "*EUICC: 4"))

+            sim_info_reg.sim_card_type = 0;

+        urc_msg_distribute(false, INFO_URC_MSG_SIM_STATE, &sim_info_reg, sizeof(mbtk_sim_card_info));

+    }

+    // +CPIN: SIM PIN

+    else if(strStartsWith(s, "+CPIN:"))

+    {

+        sim_info_reg.sim = -1;

+        if(strStartsWith(s, "+CPIN: READY"))

+            sim_info_reg.sim = 1;

+        else if(strStartsWith(s, "+CPIN: SIM PIN"))

+            sim_info_reg.sim = 2;

+        else if(strStartsWith(s, "+CPIN: SIM PUK"))

+            sim_info_reg.sim = 3;

+        else if(strStartsWith(s, "+CPIN: PH-SIMLOCK PIN"))

+            sim_info_reg.sim = 4;

+        else if(strStartsWith(s, "+CPIN: PH-SIMLOCK PUK"))

+            sim_info_reg.sim = 5;

+        else if(strStartsWith(s, "+CPIN: PH-FSIM PIN"))

+            sim_info_reg.sim = 6;

+        else if(strStartsWith(s, "+CPIN: PH-FSIM PUK"))

+            sim_info_reg.sim = 7;

+        else if(strStartsWith(s, "+CPIN: SIM PIN2"))

+            sim_info_reg.sim = 8;

+        else if(strStartsWith(s, "+CPIN: SIM PUK2"))

+            sim_info_reg.sim = 9;

+        else if(strStartsWith(s, "+CPIN: PH-NET PIN"))

+            sim_info_reg.sim = 10;

+        else if(strStartsWith(s, "+CPIN: PH-NET PUK"))

+            sim_info_reg.sim = 11;

+        else if(strStartsWith(s, "+CPIN: PH-NETSUB PINMT"))

+            sim_info_reg.sim = 12;

+        else if(strStartsWith(s, "+CPIN: PH-NETSUB PUK"))

+            sim_info_reg.sim = 13;

+        else if(strStartsWith(s, "+CPIN: PH-SP PIN"))

+            sim_info_reg.sim = 14;

+        else if(strStartsWith(s, "+CPIN: PH-SP PUK"))

+            sim_info_reg.sim = 15;

+        else if(strStartsWith(s, "+CPIN: PH-CORP PIN"))

+            sim_info_reg.sim = 16;

+        else if(strStartsWith(s, "+CPIN: PH-CORP PUK"))

+            sim_info_reg.sim = 17;

+        else if(strStartsWith(s, "+CPIN: SIM REMOVED"))

+            sim_info_reg.sim = 18;

+        else

+            sim_info_reg.sim = 20;

+

+        if(sim_info_reg.sim == 18)

+        {

+            uint8 data_pdp;

+            data_pdp = 11;       //

+            urc_msg_distribute(false, INFO_URC_MSG_PDP_STATE, &data_pdp, sizeof(uint8));

+        }

+

+        urc_msg_distribute(false, INFO_URC_MSG_SIM_STATE, &sim_info_reg, sizeof(mbtk_sim_card_info));

+    }

+    // +CMT: ,23

+    // 0891683108200855F6240D91688189911196F10000221130717445230331D90C

+    else if(strStartsWith(s, "+CMT:") || sms_cmt)

+    {

+        if(!sms_cmt){

+            sms_cmt = true;

+        }else{

+            sms_cmt = false;

+        }

+        printf("+CMT() sms_cmt:%d, s:%s, len:%d\n",sms_cmt,  s, strlen(s));

+        urc_msg_distribute(false, INFO_URC_MSG_SMS_STATE, s, strlen(s));

+    }

+#if 0

+    // LTE data registed.

+    // +CEREG: 1, "8330", "06447347", 7

+    else if(strStartsWith(s, "+CEREG:"))

+    {

+        char* tmp_s = memdup(s,strlen(s));

+        char* free_ptr = tmp_s;

+        char *line = tmp_s;

+        int tmp_int;

+        char *tmp_str;

+        if (at_tok_start(&line) < 0)

+        {

+            goto CREG_EXIT;

+        }

+        if (at_tok_nextint(&line, &tmp_int) < 0)

+        {

+            goto CREG_EXIT;

+        }

+        uint8 data = (uint8)tmp_int; // Reg State.

+

+        urc_msg_distribute(INFO_URC_MSG_NET_REG_STATE, &data, sizeof(uint8));

+CREG_EXIT:

+        free(free_ptr);

+    }

+#endif

+    /*

+    // <mcc>, <length of mnc>, <mnc>, <tac>, <PCI>, <dlEuarfcn>, < ulEuarfcn >, <band>, <dlBandwidth>,

+    // <rsrp>,<rsrq>, <sinr>,

+    // errcModeState,emmState,serviceState,IsSingleEmmRejectCause,EMMRejectCause,mmeGroupId,mmeCode,mTmsi,

+    // cellId,subFrameAssignType,specialSubframePatterns,transMode

+    // mainRsrp,diversityRsrp,mainRsrq,diversityRsrq,rssi,cqi,pathLoss,tb0DlTpt,tb1DlTpt,tb0DlPeakTpt,tb1DlPeakTpt,tb0UlPeakTpt,

+    // tb1UlPeakTpt,dlThroughPut,dlPeakThroughPut,averDlPRB,averCQITb0,averCQITb1,rankIndex,grantTotal,ulThroughPut,ulPeakThroughPut,currPuschTxPower,averUlPRB,

+    // dlBer, ulBer,

+    // diversitySinr, diversityRssi

+    +EEMLTESVC: 1120, 2, 0, 33584, 430, 40936, 40936, 41, 20,

+    0, 0, 0,

+    1, 10, 0, 1, 0, 1059, 78, 3959566565,

+    105149248, 2, 7, 7,

+    0, 0, 0, 0, 0, 0, 0, 1190919, 0, 0, 0, 16779777,

+    0, 5112867, 3959566565, 2, 0, 0, 0, 0, 0, 0, 0, 0,

+    0, 0,

+    7, 44

+    */

+    else if(strStartsWith(s, "+EEMLTESVC:"))   // LTE Server Cell

+    {

+        // tac, PCI, dlEuarfcn, ulEuarfcn, band

+        if(cell_info.running) {

+            int tmp_int;

+            int i = 0;

+            char* tmp_s = memdup(s,strlen(s));

+            char* free_ptr = tmp_s;

+            char *line = tmp_s;

+            if (at_tok_start(&line) < 0)

+            {

+                goto EEMLTESVC_EXIT;

+            }

+

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTESVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value6 = (uint32)tmp_int;    //mcc

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTESVC_EXIT;

+            }

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTESVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value7 = (uint32)tmp_int;    //mnc

+            /*

+            // Jump 2 integer.

+            i = 0;

+            while(i < 2) {

+                if (at_tok_nextint(&line, &tmp_int) < 0)

+                {

+                    goto EEMLTESVC_EXIT;

+                }

+                i++;

+            }

+            */

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTESVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value1 = (uint32)tmp_int;    //tac

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTESVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value2 = (uint32)tmp_int;    //pci

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTESVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value3 = (uint32)tmp_int;    //dl arfcn

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTESVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value4 = (uint32)tmp_int;    //ul arfcn

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTESVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value5 = (uint32)tmp_int;    //band

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTESVC_EXIT;

+            }

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTESVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value8 = (uint32)tmp_int;    //cid

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTESVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value9 = (uint32)tmp_int;    //rsrp

+

+            for(i =0; i < 10; i++)

+            {

+                if (at_tok_nextint(&line, &tmp_int) < 0)

+                {

+                    goto EEMLTESVC_EXIT;

+                }

+            }

+			cell_info.cell[cell_info.cell_num].value10 = (uint32)tmp_int;   //cell identiy

+

+            cell_info.cell_num++;

+

+EEMLTESVC_EXIT:

+            free(free_ptr);

+        }

+    }

+    /*

+    // index,phyCellId,euArfcn,rsrp,rsrq

+    +EEMLTEINTER: 0, 65535, 38950, 0, 0

+    */

+    else if(strStartsWith(s, "+EEMLTEINTER:") || strStartsWith(s, "+EEMLTEINTRA:")) // LTE ÒìÆµ/Í¬ÆµÐ¡Çø

+    {

+        // phyCellId,euArfcn,rsrp,rsrq

+        if(cell_info.running) {

+            int tmp_int;

+            char* tmp_s = memdup(s,strlen(s));

+            char* free_ptr = tmp_s;

+            char *line = tmp_s;

+            if (at_tok_start(&line) < 0)

+            {

+                goto EEMLTEINTER_EXIT;

+            }

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTEINTER_EXIT;

+            }

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int <= 0 || tmp_int > 503)

+            {

+                goto EEMLTEINTER_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value1 = (uint32)tmp_int;

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTEINTER_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value2 = (uint32)tmp_int;

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTEINTER_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value3 = (uint32)tmp_int;

+            LOG("cell line : %s", line);

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMLTEINTER_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value4 = (uint32)tmp_int;

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                LOG("cell tmp_int : %d", tmp_int);

+                goto EEMLTEINTER_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value5 = (uint32)tmp_int;

+            LOG("cell value5 : %d", cell_info.cell[cell_info.cell_num].value5);

+            cell_info.cell_num++;

+EEMLTEINTER_EXIT:

+            free(free_ptr);

+        }

+    }

+    // Do nothing

+    else if(strStartsWith(s, "+EEMLTEINTERRAT:")) // LTE RATÐ¡ÇøÐÅÏ¢

+    {

+        if(cell_info.running) {

+

+        }

+    }

+    // WCDMA

+    /*

+    // Mode, sCMeasPresent, sCParamPresent, ueOpStatusPresent,

+

+    // if sCMeasPresent == 1

+    // cpichRSCP, utraRssi, cpichEcN0, sQual, sRxLev, txPower,

+    // endif

+

+    // if sCParamPresent == 1

+    // rac, nom, mcc, mnc_len, mnc, lac, ci,

+    // uraId, psc, arfcn, t3212, t3312, hcsUsed, attDetAllowed,

+    // csDrxCycleLen, psDrxCycleLen, utranDrxCycleLen, HSDPASupport, HSUPASupport,

+    // endif

+

+    // if ueOpStatusPresent == 1

+    // rrcState, numLinks, srncId, sRnti,

+    // algPresent, cipherAlg, cipherOn, algPresent, cipherAlg, cipherOn,

+    // HSDPAActive, HSUPAActive, MccLastRegisteredNetwork, MncLastRegisteredNetwork, TMSI, PTMSI, IsSingleMmRejectCause, IsSingleGmmRejectCause,

+    // MMRejectCause, GMMRejectCause, mmState, gmmState, gprsReadyState, readyTimerValueInSecs, NumActivePDPContext, ULThroughput, DLThroughput,

+    // serviceStatus, pmmState, LAU_status, LAU_count, RAU_status, RAU_count

+    // endif

+    //

+    +EEMUMTSSVC: 3, 1, 1, 1,

+    -80, 27, -6, -18, -115, -32768,

+    1, 1, 1120, 2, 1, 61697, 168432821,

+    15, 24, 10763, 0, 0, 0, 0,

+    128, 128, 65535, 0, 0,

+    2, 255, 65535, 4294967295,

+    0, 0, 0, 0, 0, 0,

+    0, 0, 0, 0, 0, 0, 1, 1,

+    28672, 28672, 0, 0, 0, 0, 0, 0, 0,

+    0, 0, 0, 0, 0, 0

+    */

+    else if(strStartsWith(s, "+EEMUMTSSVC:")) // WCDMA Server Cell

+    {

+        // lac, ci, arfcn

+        if(cell_info.running) {

+            int tmp_int;

+            int i = 0;

+            char* tmp_s = memdup(s,strlen(s));

+            char* free_ptr = tmp_s;

+            char *line = tmp_s;

+            if (at_tok_start(&line) < 0)

+            {

+                goto EEMUMTSSVC_EXIT;

+            }

+            // Jump 12 integer.

+            i = 0;

+            while(i < 12) {

+                if (at_tok_nextint(&line, &tmp_int) < 0)

+                {

+                    goto EEMUMTSSVC_EXIT;

+                }

+                i++;

+            }

+            // mcc

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMUMTSSVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value4= (uint32)tmp_int;

+            // mnc

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMUMTSSVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value5= (uint32)tmp_int;

+            // lac

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMUMTSSVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value1 = (uint32)tmp_int;

+            // ci

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMUMTSSVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value2 = (uint32)tmp_int;

+

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMUMTSSVC_EXIT;

+            }

+            // cpi

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMUMTSSVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value6= (uint32)tmp_int;

+            /*

+            // Jump 2 integer.

+            i = 0;

+            while(i < 2) {

+                if (at_tok_nextint(&line, &tmp_int) < 0)

+                {

+                    goto EEMUMTSSVC_EXIT;

+                }

+                i++;

+            }

+            */

+            // arfcn

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                goto EEMUMTSSVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value3 = (uint32)tmp_int;

+

+            cell_info.cell_num++;

+EEMUMTSSVC_EXIT:

+            free(free_ptr);

+        }

+    }

+    /*

+    // index, cpichRSCP, utraRssi, cpichEcN0, sQual, sRxLev ,mcc, mnc, lac, ci, arfcn, psc

+    +EEMUMTSINTRA: 0, -32768, -1, -32768, -18, -115, 0, 0, 65534, 1, 10763, 32

+    */

+    else if(strStartsWith(s, "+EEMUMTSINTRA:")) // WCDMAÁÙ½üÐ¡Çø

+    {

+        // lac, ci, arfcn

+        if(cell_info.running) {

+            int tmp_int;

+            int i = 0;

+            char* tmp_s = memdup(s,strlen(s));

+            char* free_ptr = tmp_s;

+            char *line = tmp_s;

+            if (at_tok_start(&line) < 0)

+            {

+                goto EEMUMTSINTRA_EXIT;

+            }

+            // Jump 8 integer.

+            i = 0;

+            while(i < 8) {

+                if (at_tok_nextint(&line, &tmp_int) < 0)

+                {

+                    goto EEMUMTSINTRA_EXIT;

+                }

+                i++;

+            }

+

+            // lac

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int <= 0 || tmp_int >= 65536)

+            {

+                goto EEMUMTSINTRA_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value1 = (uint32)tmp_int;

+

+            // ci

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int <= 0 || tmp_int >= 65536)

+            {

+                goto EEMUMTSINTRA_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value2 = (uint32)tmp_int;

+

+            // arfcn

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int <= 0 || tmp_int >= 65536)

+            {

+                goto EEMUMTSINTRA_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value3 = (uint32)tmp_int;

+

+            cell_info.cell_num++;

+EEMUMTSINTRA_EXIT:

+            free(free_ptr);

+        }

+    }

+    /*

+    // index,gsmRssi,rxLev,C1,C2,mcc,mnc,lac,ci,arfcn,bsic

+    +EEMUMTSINTERRAT: 0, -32768, -107, -1, -1, 0, 0, 65534, 0, 117, 36

+    */

+    else if(strStartsWith(s, "+EEMUMTSINTERRAT:")) // WCDMA RATÐ¡ÇøÐÅÏ¢

+    {

+        // lac, ci, arfcn

+        if(cell_info.running) {

+            int tmp_int;

+            int i = 0;

+            char* tmp_s = memdup(s,strlen(s));

+            char* free_ptr = tmp_s;

+            char *line = tmp_s;

+            if (at_tok_start(&line) < 0)

+            {

+                goto EEMUMTSINTERRAT_EXIT;

+            }

+            // Jump 7 integer.

+            i = 0;

+            while(i < 7) {

+                if (at_tok_nextint(&line, &tmp_int) < 0)

+                {

+                    goto EEMUMTSINTERRAT_EXIT;

+                }

+                i++;

+            }

+

+            // lac

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int <= 0 || tmp_int >= 65536)

+            {

+                goto EEMUMTSINTERRAT_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value1 = (uint32)tmp_int;

+

+            // ci

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int <= 0 || tmp_int >= 65536)

+            {

+                goto EEMUMTSINTERRAT_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value2 = (uint32)tmp_int;

+

+            // arfcn

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int <= 0 || tmp_int >= 65536)

+            {

+                goto EEMUMTSINTERRAT_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value3 = (uint32)tmp_int;

+

+            cell_info.cell_num++;

+EEMUMTSINTERRAT_EXIT:

+            free(free_ptr);

+        }

+    }

+    // GSM

+    // +EEMGINFOBASIC: 2

+    // Do nothing.

+    else if(strStartsWith(s, "+EEMGINFOBASIC:")) // Basic information in GSM

+        // 0: ME in Idle mode   1: ME in Dedicated mode   2: ME in PS PTM mode

+    {

+        if(cell_info.running) {

+

+        }

+    }

+    /*

+    // mcc, mnc_len, mnc, lac, ci, nom, nco,

+    // bsic, C1, C2, TA, TxPwr,

+    // RxSig, RxSigFull, RxSigSub, RxQualFull, RxQualSub,

+    // ARFCB_tch, hopping_chnl, chnl_type, TS, PacketIdle, rac, arfcn,

+    // bs_pa_mfrms, C31, C32, t3212, t3312, pbcch_support, EDGE_support,

+    // ncc_permitted, rl_timeout, ho_count, ho_succ, chnl_access_count, chnl_access_succ_count,

+    // gsmBand,channelMode

+    +EEMGINFOSVC: 1120, 2, 0, 32784, 24741, 2, 0,

+    63, 36, 146, 1, 7,

+    46, 42, 42, 7, 0,

+    53, 0, 8, 0, 1, 6, 53,

+    2, 0, 146, 42, 54, 0, 1,

+    1, 32, 0, 0, 0, 0,

+    0, 0

+    */

+    else if(strStartsWith(s, "+EEMGINFOSVC:")) // GSM Server Cell

+    {

+        // lac, ci, arfcn, bsic

+        LOG("+EEMGINFOSVC: 1= %d\n.",cell_info.running);

+        if(cell_info.running) {

+            int tmp_int;

+            int i = 0;

+            char* tmp_s = memdup(s,strlen(s));

+            char* free_ptr = tmp_s;

+            char *line = tmp_s;

+            if (at_tok_start(&line) < 0)

+            {

+                goto EEMGINFOSVC_EXIT;

+            }

+

+            // mcc

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int <= 0 || tmp_int >= 65536)

+            {

+                goto EEMGINFOSVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value5 = (uint32)tmp_int;

+

+            //mnc_len

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int <= 0 || tmp_int >= 65536)

+            {

+                goto EEMGINFOSVC_EXIT;

+            }

+            // mnc

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int <= 0 || tmp_int >= 65536)

+            {

+                goto EEMGINFOSVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value6 = (uint32)tmp_int;

+

+            /*

+            // Jump 3 integer.

+            i = 0;

+            while(i < 3) {

+                if (at_tok_nextint(&line, &tmp_int) < 0)

+                {

+                    goto EEMGINFOSVC_EXIT;

+                }

+                i++;

+            }

+            */

+            // lac

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int < 0 || tmp_int >= 65536)

+            {

+                goto EEMGINFOSVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value1 = (uint32)tmp_int;

+

+            // ci

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int < 0 || tmp_int >= 65536)

+            {

+                goto EEMGINFOSVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value2 = (uint32)tmp_int;

+

+            // Jump 2 integer.

+            i = 0;

+            while(i < 2) {

+                if (at_tok_nextint(&line, &tmp_int) < 0)

+                {

+                    goto EEMGINFOSVC_EXIT;

+                }

+                i++;

+            }

+

+            // bsic

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int < 0 || tmp_int >= 65536)

+            {

+                goto EEMGINFOSVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value4 = (uint32)tmp_int;

+

+            // Jump 15 integer.

+            i = 0;

+            while(i < 15) {

+                if (at_tok_nextint(&line, &tmp_int) < 0)

+                {

+                    goto EEMGINFOSVC_EXIT;

+                }

+                i++;

+            }

+

+            // arfcn

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int < 0 || tmp_int >= 65536)

+            {

+                goto EEMGINFOSVC_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value3 = (uint32)tmp_int;

+

+            cell_info.cell_num++;

+EEMGINFOSVC_EXIT:

+            free(free_ptr);

+        }

+    }

+    /*

+    // PS_attached, attach_type, service_type, tx_power, c_value,

+    // ul_ts, dl_ts, ul_cs, dl_cs, ul_modulation, dl_modulation,

+    // gmsk_cv_bep, 8psk_cv_bep, gmsk_mean_bep, 8psk_mean_bep, EDGE_bep_period, single_gmm_rej_cause

+    // pdp_active_num, mac_mode, network_control, network_mode, EDGE_slq_measurement_mode, edge_status

+    +EEMGINFOPS: 1, 255, 0, 0, 0,

+    0, 0, 268435501, 1, 0, 0,

+    4, 0, 96, 0, 0, 0,

+    0, 0, 0, 65535, 0, 13350

+    */

+    // Do nothing.

+    else if(strStartsWith(s, "+EEMGINFOPS:")) // PSÐÅÏ¢

+    {

+        if(cell_info.running) {

+

+        }

+    }

+    else if(strStartsWith(s, "+EEMGINFONC:")) // cell

+    {

+        if(cell_info.running) {

+            int tmp_int;

+            int i = 0;

+            char* tmp_s = memdup(s,strlen(s));

+            char* free_ptr = tmp_s;

+            char *line = tmp_s;

+            if (at_tok_start(&line) < 0)

+            {

+                goto EEMGINFOPS_EXIT;

+            }

+

+            // nc_num

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int < 0 || tmp_int >= 65536)

+            {

+                LOG("cell_info.running 1= %d\n.",cell_info.running);

+                goto EEMGINFOPS_EXIT;

+            }

+            // mcc

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int < 0 || tmp_int >= 65536)

+            {

+                LOG("cell_info.running 2= %d\n.",cell_info.running);

+                goto EEMGINFOPS_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value5 = (uint32)tmp_int;

+

+            // mnc

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int < 0 || tmp_int >= 65536)

+            {

+                LOG("cell_info.running 3= %d\n.",cell_info.running);

+                goto EEMGINFOPS_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value6 = (uint32)tmp_int;

+

+            // lac

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int < 0 || tmp_int >= 65536)

+            {

+                LOG("cell_info.running 4= %d\n.",cell_info.running);

+                goto EEMGINFOPS_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value1 = (uint32)tmp_int;

+

+            // rac

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int < 0 || tmp_int >= 65536)

+            {

+                LOG("cell_info.running 5= %d\n.",cell_info.running);

+                goto EEMGINFOPS_EXIT;

+            }

+

+            // ci

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int < 0 || tmp_int >= 65536)

+            {

+                LOG("cell_info.running 6= %d\n.",cell_info.running);

+                goto EEMGINFOPS_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value2 = (uint32)tmp_int;

+

+            // rx_lv

+            if (at_tok_nextint(&line, &tmp_int) < 0)

+            {

+                LOG("cell_info.running 7= %d\n.",cell_info.running);

+                goto EEMGINFOPS_EXIT;

+            }

+

+            // bsic

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int < 0 || tmp_int >= 65536)

+            {

+                LOG("cell_info.running 8= %d\n.",cell_info.running);

+                goto EEMGINFOPS_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value4 = (uint32)tmp_int;

+

+            // Jump 2 integer.

+            i = 0;

+            while(i < 2) {

+                if (at_tok_nextint(&line, &tmp_int) < 0)

+                {

+                    LOG("cell_info.running 9= %d\n.",cell_info.running);

+                    goto EEMGINFOPS_EXIT;

+                }

+                i++;

+            }

+

+            // arfcn

+            if (at_tok_nextint(&line, &tmp_int) < 0 || tmp_int < 0 || tmp_int >= 65536)

+            {

+                LOG("cell_info.running 10 = %d\n.",cell_info.running);

+                goto EEMGINFOPS_EXIT;

+            }

+            cell_info.cell[cell_info.cell_num].value3 = (uint32)tmp_int;

+

+            cell_info.cell_num++;

+EEMGINFOPS_EXIT:

+            free(free_ptr);

+        }

+    }

+    else if(strStartsWith(s, "+ZGIPDNS:")) // +ZGIPDNS: 1,"IPV4V6","10.156.239.245","10.156.239.246","223.87.253.100","223.87.253.253","fe80:0000:0000:0000:0001:0001:9b8c:7c0c","fe80::1:1:9b8c:7c0d","2409:8062:2000:2::1","2409:8062:2000:2::2"

+    {

+

+    }

+    else

+    {

+        LOGV("Unknown URC : %s", s);

+    }

+}

+

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

+}

+

+static void ril_get_cgpaddr_ip_process()

+{

+    int err, skip;

+    ATResponse *p_response = NULL;

+    char *line;

+    char *ipv4 = NULL, *ipv6 = NULL;

+    err = at_send_command_singleline("AT+CGPADDR", "+CGPADDR:", &p_response);

+    if ((err < 0) || (p_response == NULL) || (p_response->success == 0))

+    {

+        LOGE("+CGPADDR exec error.");

+        goto error;

+    }

+

+    // +CGPADDR: 1, "10.51.59.229", "254.128.0.0.0.0.0.0.0.1.0.0.111.176.63.99"

+    // +CGPADDR: 1, "10.124.139.131"

+    line = p_response->p_intermediates->line;

+    err = at_tok_start(&line);

+    if (err < 0)

+    {

+        goto error;

+    }

+

+    err = at_tok_nextint(&line, &skip);

+    if (err < 0)

+    {

+        goto error;

+    }

+

+    if (!at_tok_hasmore(&line))

+    {

+        goto error;

+    }

+

+    err = at_tok_nextstr(&line, &ipv4);

+    if (err < 0)

+    {

+        LOGE("Get IPv4 fail.");

+        goto error;

+    }

+

+    if (at_tok_hasmore(&line))

+    {

+        err = at_tok_nextstr(&line, &ipv6);

+        if (err < 0)

+        {

+            LOGE("Get IPv6 fail.");

+            goto error;

+        }

+    }

+    else

+    {

+        LOGD("No IPv6 Found.");

+    }

+

+    if(ipv6)

+    {

+        LOGD("IPv6 : %s", ipv6);

+    }

+

+    if(ipv4)

+    {

+        LOGD("IPv4 : %s", ipv4);

+

+//        ril_net_dev_config("ccinet0", ipv4, NULL);

+    }

+error:

+    at_response_free(p_response);

+}

+

+static void sim_state_change(bool plug_in) {

+    if(plug_in) {

+        // If radio on,must off in the first.

+        if(net_info.radio_state == MBTK_RADIO_STATE_ON) {

+            setRadioPower(0);

+        }

+        setRadioPower(1);

+    } else {

+        setRadioPower(0);

+    }

+}

+

+static int open_uevent_socket()

+{

+    struct sockaddr_nl addr;

+    int sz = 64*1024;

+    int s = 0;

+

+    memset(&addr, 0, sizeof(addr));

+    addr.nl_family = AF_NETLINK;

+    addr.nl_pid = getpid();

+    addr.nl_groups = 0xffffffff;

+

+    s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);

+    if (s < 0)

+    {

+        LOGE("socket() fail.[%d]", errno);

+        return -1;

+    }

+

+    setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));

+

+    if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0)

+    {

+        close(s);

+        return -1;

+    }

+

+    return s;

+}

+

+static void parse_uevent(const char *msg, int msg_len, struct cooling_device *cdev)

+{

+    // change@/devices/virtual/usim_event/usim0\0

+    // ACTION=change\0

+    // DEVPATH=/devices/virtual/usim_event/usim0\0

+    // SUBSYSTEM=usim_event\0

+    // USIM_NAME=usim0\0

+    // USIM_EVENT=plugout\0

+    // SEQNUM=704

+    int i = 0;

+    while (i < msg_len)

+    {

+        if(*(msg + i) == '\0')

+        {

+            i++;

+            continue;

+        }

+        if (!strncmp(msg + i, "USIM_NAME=", 10))

+        {

+            i += 10;

+            cdev->name = msg + i;

+            i += strlen(msg + i);

+        }

+        else if (!strncmp(msg + i, "ACTION=", 7))

+        {

+            i += 7;

+            cdev->action = msg + i;

+            i += strlen(msg + i);

+        }

+        else if (!strncmp(msg + i, "DEVPATH=", 8))

+        {

+            i += 8;

+            cdev->path = msg + i;

+            i += strlen(msg + i);

+        }

+        else if (!strncmp(msg + i, "USIM_EVENT=", 11))

+        {

+            i += 11;

+            cdev->event = msg + i;

+            i += strlen(msg + i);

+        }

+        else if (!strncmp(msg + i, "SUBSYSTEM=", 10))

+        {

+            i += 10;

+            cdev->subsystem = msg + i;

+            i += strlen(msg + i);

+        }

+        else

+        {

+            i++;

+        }

+    }

+

+    if(!strncmp(cdev->path, UEVENT_USIM_DEV, sizeof(UEVENT_USIM_DEV))

+       && !strncmp(cdev->action, "change", 5))

+    {

+        LOGD("event { name=%s, action=%s, path=%s, subsystem=%s, event=%s}",

+             cdev->name,    cdev->action, cdev->path, cdev->subsystem, cdev->event);

+        if(!strcmp(cdev->event, "plugout"))

+        {

+            sim_state_change(FALSE);

+        }

+        else if(!strcmp(cdev->event, "plugin"))

+        {

+            sim_state_change(TRUE);

+        }

+        else

+        {

+            LOGE("usim evnet error!");

+        }

+    }

+}

+

+static void* uevnet_run(void *payload)

+{

+    int socket_fd = -1;

+    char msg[BUFFER_SIZE+2];

+    int n;

+

+    socket_fd = open_uevent_socket();

+    if(socket_fd > 0)

+    {

+        while(1)

+        {

+            if((n = recv(socket_fd, msg, BUFFER_SIZE, 0)) > 0)

+            {

+                struct cooling_device cdev;

+                memset(&cdev, 0x0, sizeof(cdev));

+

+                if(n == BUFFER_SIZE)

+                    continue;

+                msg[n] = '\0';

+                // change@/devices/virtual/usim_event/usim0\0ACTION=change\0DEVPATH=/devices/virtual/usim_event/usim0\0SUBSYSTEM=usim_event\0USIM_NAME=usim0\0USIM_EVENT=plugout\0SEQNUM=704

+                log_hex("UEVENT", msg, n);

+                parse_uevent(msg, n, &cdev);

+            }

+            else

+            {

+                LOGE("recv msg error.");

+            }

+        }

+    }

+

+    LOGD("UEVENT Thread exit!!!");

+    return NULL;

+}

+

+int uevent_main()

+{

+    mbtk_task_info task;

+    task.task_id = &uevnet_task_id;

+    task.thread_run = uevnet_run;

+    task.args = NULL;

+    return mbtk_task_start(&task);

+}

+

+/*

+int ril_main()

+{

+    return mbtk_task_queue_start(&ril_task, ril_main_run);

+}

+*/

+

+int mbtk_info_server_start();

+int InProduction_Mode(void);

+void server_ready_set(void);

+

+
+/*
+ *Get mtdblock which name is ASR_FLAG
+ *return path if found, else return NULL
+ */
+static int asrFlagPathGet(char *asr_flag_path)

+{
+	char buf[128];
+	unsigned char find = 0;
+	FILE *fd = fopen("/proc/mtd", "r");

+	if (fd == NULL) {
+		LOGE("Open MTD failed!");

+		return -1;

+	}
+
+	memset(buf, '\0', 128);
+	while (fgets(buf, 128, fd) != NULL) {
+		if(strstr(buf, "asr_flag")) {
+			char *p = strstr(buf, "mtd");
+			if(p)
+			{
+				int bln;
+				sscanf(p, "mtd%d", &bln);
+				sprintf(asr_flag_path, "/dev/mtdblock%d", bln);
+				find = 1;
+				break;
+			}
+		}
+		memset(buf, '\0', 128);
+	}
+
+	fclose(fd);
+	return ((find == 1) ? 0 : -1);

+}
+
+static int readFromMTD(const char *path, unsigned int offset, void *buf, int size)

+{
+	int ret, fd;
+	if (!path)
+		return -1;
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0) {
+		LOGE("readFromMTD open error,%d", errno);

+		return -1;
+	}
+
+	ret = lseek(fd, offset, SEEK_SET);
+	if (ret < 0) {
+		close(fd);
+		LOGE("readFromMTD lseek error,%d", errno);

+		return -1;
+	}
+	ret = read(fd, buf, size);
+	if (ret < 0) {
+		close(fd);
+		LOGE("readFromMTD read error,%d", errno);

+		return -1;
+	}
+	close(fd);
+	return 0;
+}
+
+static int writeToMTD(const char *path, unsigned int offset, void *buf, int size)

+{
+	int ret, fd;
+
+	if (!path)
+		return -1;
+
+	fd = open(path, O_RDWR | O_SYNC);
+	if (fd < 0)
+		return -1;
+
+	ret = lseek(fd, offset, SEEK_SET);
+	if (ret < 0) {
+		close(fd);
+		return -1;
+	}
+	ret = write(fd, buf, size);
+	if (ret < 0) {
+		LOGE("writetomtd:write error:%d", errno);

+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+	return 0;
+}

+

+static void fota_result_check()

+{

+#if 0

+    ASR_flag tag;

+    char asr_flag_path[30] = {0};

+    if(asrFlagPathGet(asr_flag_path)) {

+        LOGE("getAsrFlagPath() fail.");

+        return;

+    }

+

+    if(readFromMTD(asr_flag_path, ASR_FLAG_OFFSET, &tag, sizeof(tag)) < 0)

+    {

+        LOGE("Get FOTA result fail.");

+    }

+    else

+    {

+        LOGD("FOTA result : %d, %d", tag.fota_result[0], tag.fota_result[1]);

+        tag.fota_result[0] = 0;

+        tag.fota_result[1] = 0;

+        if(writeToMTD(asr_flag_path, ASR_FLAG_OFFSET, &tag, sizeof(tag)) < 0)

+        {

+            LOGE("FOTA result update fail.");

+        } else {

+            LOGD("FOTA result update success.");

+        }

+    }

+#endif

+}

+

+static void mbtk_server_ready()

+{

+    // /etc/init.d/mbtk_boot_server_ready

+    if(access(MBTK_BOOT_SERVER_READY , X_OK) == 0) {

+        system(MBTK_BOOT_SERVER_READY);

+    } else {

+        LOGE("%s can not exec.", MBTK_BOOT_SERVER_READY);

+    }

+}

+

+#if 1

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

+{

+    mbtk_log_init("radio", "MBTK_RIL");

+    LOGI("mbtk_ril start.");

+

+    if(InProduction_Mode()) {

+        LOGI("Is Production Mode, will exit...");

+        exit(0);

+    }

+

+    int at_sock = openSocket("/tmp/atcmd_at");

+    if(at_sock < 0)

+    {

+        LOGE("Open AT Socket Fail[%d].", errno);

+        return -1;

+    }

+    int uart_sock = openSocket("/tmp/atcmd_urc");

+    if(uart_sock < 0)

+    {

+        LOGE("Open Uart Socket Fail[%d].", errno);

+        return -1;

+    }

+

+    at_set_on_reader_closed(onATReaderClosed);

+    at_set_on_timeout(onATTimeout);

+

+    if(at_open(at_sock, uart_sock, onUnsolicited))

+    {

+        LOGE("Start AT thread fail.");

+        return -1;

+    }

+

+#if 1

+    if(at_handshake())

+    {

+        LOGE("AT handshake fail.");

+        return -1;

+    }

+#endif

+

+    LOGD("AT OK.");

+

+    if(mbtk_info_server_start())

+    {

+        LOGE("mbtk_info_server_start() fail.");

+        return -1;

+    }

+

+#if 0

+    if(uevent_main())

+    {

+        LOGE("Start uevent thread fail.");

+        return -1;

+    }

+#endif

+

+    char time_type[10];

+    memset(time_type, 0, 10);

+    property_get("persist.mbtk.time_type", time_type, "0");

+    if(atoi(time_type) == MBTK_TIME_TYPE_NTP) { // NTP time

+        LOG("Start NTP thread.");

+        ntp_thread_start();

+    }

+

+    fota_result_check();

+

+    mbtk_server_ready();

+

+    server_ready_set();//Set the server readiness state

+    while(1)

+    {

+        sleep(24 * 60 * 60);

+    }

+

+    LOGD("!!!mbtk_ril exit!!!");

+    return 0;

+}

+

+#else

+int main()

+{

+    char buff[BUFFER_SIZE + 1] = {0};

+    if(!mbtk_at("AT+CFUN=1", buff, BUFFER_SIZE))

+    {

+        LOGD("+CFUN RSP:%s", buff);

+        while(1)

+        {

+            sleep(1);

+            memset(buff, 0x0, BUFFER_SIZE + 1);

+            if(!mbtk_at("AT+CGPADDR", buff, BUFFER_SIZE))

+            {

+                LOGD("+CGPADDR RSP:%s", buff);

+                if(strstr(buff, "+CGPADDR:"))

+                {

+                    // +CGPADDR: 1, "10.99.223.168", "254.128.0.0.0.0.0.0.0.1.0.0.117.9.250.59"

+                    //

+                    // OK

+                    char *ip_start = NULL;

+                    char *ip_end = NULL;

+                    char ipv4[50] = {0};

+                    ip_start = strstr(buff,"\"");

+                    if(ip_start)

+                        ip_end = strstr(ip_start + 1, "\"");

+                    if(ip_start && ip_end && ip_end - ip_start - 1 > 0)

+                    {

+                        memcpy(ipv4, ip_start + 1, ip_end - ip_start - 1);

+                        LOGD("IP : %s", ipv4);

+                        if(!mbtk_ifc_open())

+                        {

+                            in_addr_t addr;

+                            inet_aton(ipv4,(struct in_addr *)&addr);

+                            LOGD("IP : %s -> %x", ipv4, addr);

+                            if(!mbtk_ifc_set_addr("ccinet0", addr, 0))

+                            {

+                                mbtk_ifc_up("ccinet0");

+                            }

+

+                            mbtk_ifc_close();

+                        }

+

+                        system("route add default dev ccinet0");

+

+                        LOGD("Set IP success.");

+                    }

+                    else

+                    {

+                        LOGD("Get IP fail.");

+                    }

+

+                    break;

+                }

+            }

+        }

+    }

+

+    return 0;

+}

+#endif

diff --git a/mbtk/mbtk_ril/src/mbtk_call.c b/mbtk/mbtk_ril/src/mbtk_call.c
new file mode 100755
index 0000000..94c835f
--- /dev/null
+++ b/mbtk/mbtk_ril/src/mbtk_call.c
@@ -0,0 +1,570 @@
+#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 <fcntl.h>
+#include <signal.h>
+
+#include "mbtk_type.h"
+#include "mbtk_info.h"
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_utils.h"
+#include "info_data.h"
+
+void pack_rsp_send(int fd, int info_id, const void* data, int data_len);
+
+
+/*
+ATDXXXXXXX;
+OK
+
+*/
+static int req_call_start(char *phont_number, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int tmp_int;
+    char *tmp_str = NULL;
+    char cmd[100] = {0};
+    sprintf(cmd, "ATD%s;", phont_number);
+    int err = at_send_command(cmd, &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+
+AT+CHLD=2
+OK
+
+*/
+static int req_answer_call(int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command("AT+CHLD=2", &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+ATH
+OK
+
+*/
+static int req_hangup_call(int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command("ATH", &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CHLD=1x
+OK
+
+*/
+static int req_hangup_a_call(int phone_id, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[100] = {0};
+    sprintf(cmd, "AT+CHLD=1%d", phone_id);
+    int err = at_send_command(cmd, &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CHLD=0
+OK
+
+*/
+static int req_hangup_waiting_or_background_call(int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command("AT+CHLD=0", &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CHLD=1
+OK
+
+*/
+static int req_hangup_foreground_resume_background_call(int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command("AT+CHLD=1", &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CLCC
+OK
+
+*/
+static int req_waitin_call(mbtk_call_info_t *reg, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int tmp_int;
+    char *tmp_str = NULL;
+    
+    int err = at_send_command_multiline("AT+CLCC", "+CLCC:", &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    if(response->success == 1 && !response->p_intermediates)
+    {
+        reg->call_wait = 0;
+        goto exit;
+    }
+
+    reg->call_wait = 1;
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int); // dir1
+    if (err < 0)
+    {
+        goto exit;
+    }
+    reg->dir1 = (uint8)tmp_int;
+    err = at_tok_nextint(&line, &tmp_int);// dir
+    if (err < 0)
+    {
+        goto exit;
+    }
+    reg->dir = (uint8)tmp_int;
+    err = at_tok_nextint(&line, &tmp_int);// state
+    if (err < 0)
+    {
+        goto exit;
+    }
+    reg->state = (uint8)tmp_int;
+    err = at_tok_nextint(&line, &tmp_int);// mode
+    if (err < 0)
+    {
+        goto exit;
+    }
+    reg->mode = (uint8)tmp_int;
+    err = at_tok_nextint(&line, &tmp_int);// mpty
+    if (err < 0)
+    {
+        goto exit;
+    }
+    reg->mpty = (uint8)tmp_int;
+    err = at_tok_nextstr(&line, &tmp_str); // phone_number
+    if (err < 0)
+    {
+        goto exit;
+    }
+    memcpy(reg->phone_number, tmp_str, strlen(tmp_str));
+    err = at_tok_nextint(&line, &tmp_int);// tpye
+    if (err < 0)
+    {
+        goto exit;
+    }
+    reg->type = (uint8)tmp_int;
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CMUT?
++CMUT: 0
+
+OK
+*/
+static int req_mute_get(int *state, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int tmp_int;
+    int err = at_send_command_singleline("AT+CMUT?", "+CMUT:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    *state = tmp_int;
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CMUT=0;
+OK
+
+*/
+static int req_mute_set(int state, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[100] = {0};
+    sprintf(cmd, "AT+CMUT=%d", state);
+    LOG("Set the mute command is = %s.\n", cmd);
+    int err = at_send_command(cmd, &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+VTS=0; //0, 1, ..., 9, A, B, C, D, *, #
+OK
+
+*/
+static int req_dtmf_set(mbtk_call_dtmf_info_t *state, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[100] = {0};
+    sprintf(cmd, "AT+VTS=%c,%d", state->character, state->duration);
+    LOG("Set the DTMF command is = %s.\n", cmd);
+    int err = at_send_command(cmd, &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+//void net_list_free(void *data);
+// Return MBTK_INFO_ERR_SUCCESS,will call pack_error_send() to send RSP.
+// Otherwise, do not call pack_error_send().
+mbtk_info_err_enum call_pack_req_process(sock_client_info_t* cli_info, mbtk_info_pack_t* pack)
+{
+    mbtk_info_err_enum err = MBTK_INFO_ERR_SUCCESS;
+    int cme_err = MBTK_INFO_ERR_CME_NON;
+    switch(pack->info_id)
+    {
+        case MBTK_INFO_ID_CALL_START_REQ: // <string> phone number
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+            }
+            else     // Set
+            {
+                char *pn = (char*)(pack->data);
+                if(req_call_start(pn, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("ATD fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_CALL_START_RSP, NULL, 0);
+                }
+            }
+            break;
+        }
+        case MBTK_INFO_ID_CALL_ANSWER_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+               if(req_answer_call(&cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Answer call fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_CALL_ANSWER_RSP, NULL, 0);
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+                LOG("Answer call fail. NO DATA\n");
+            }
+            break;
+        }
+        case MBTK_INFO_ID_CALL_HANGUP_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                if(req_hangup_call(&cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Hang up call fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_CALL_HANGUP_RSP, NULL, 0);
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+                LOG("Hang up call fail.");
+            }
+            break;
+        }
+        case MBTK_INFO_ID_CALL_HANGUP_A_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+                LOG("Hang up a call fail.");
+            }
+            else
+            {
+                uint8 phone_id = *(pack->data);
+                if(req_hangup_a_call(phone_id, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Hang up a call fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_CALL_HANGUP_A_RSP, NULL, 0);
+                }
+            }
+            break;
+        }
+        case MBTK_INFO_ID_CALL_HANGUP_B_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                if(req_hangup_waiting_or_background_call(&cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Hang up waiting_or_background call fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_CALL_HANGUP_B_RSP, NULL, 0);
+                }
+            }
+            else
+            {
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+                LOG("Hang up waiting_or_background call fail.");
+            }
+            break;
+        }
+        case MBTK_INFO_ID_CALL_HANGUP_C_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                if(req_hangup_foreground_resume_background_call(&cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Hang up waiting_or_background call fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_CALL_HANGUP_C_RSP, NULL, 0);
+                }
+            }
+            else
+            {
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+                LOG("Hang up waiting_or_background call fail.");
+            }
+            break;
+        }
+        case MBTK_INFO_ID_CALL_WAITIN_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_call_info_t reg;
+                memset(&reg, 0, sizeof(mbtk_call_info_t));
+                if(req_waitin_call(&reg, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Wait incoing call fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_CALL_WAITIN_RSP, &reg, sizeof(mbtk_call_info_t));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+                LOG("Wait incoing call fail.");
+            }
+            break;
+        }
+        case MBTK_INFO_ID_CALL_MUTE_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                int state;
+                if(req_mute_get(&state, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Get mute state fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_CALL_MUTE_RSP, &state, sizeof(uint8));
+                }
+            }
+            else     // Set mute state.
+            {
+                uint8 on = *(pack->data);
+                if(pack->data_len != sizeof(uint8) || (on != 0 && on != 1))
+                {
+                    err = MBTK_INFO_ERR_REQ_PARAMETER;
+                    LOG("Set mute parameter error.");
+                    break;
+                }
+
+                if(req_mute_set(on, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Set mute state fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_CALL_MUTE_RSP, NULL, 0);
+                }
+            }
+            break;
+        }
+        case MBTK_INFO_ID_CALL_DTMF_REQ:
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+                LOG("Wait incoing call fail.");
+            }
+            else     // Set
+            {
+                mbtk_call_dtmf_info_t *reg = (mbtk_call_dtmf_info_t *)pack->data;
+                if(req_dtmf_set(reg, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Wait incoing call fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_CALL_DTMF_RSP, NULL, 0);
+                }
+            }
+            break;
+
+
+        default:
+        {
+            err = MBTK_INFO_ERR_REQ_UNKNOWN;
+            LOG("Unknown request : %s", id2str(pack->info_id));
+            break;
+        }
+    }
+
+    return err;
+}
+
diff --git a/mbtk/mbtk_ril/src/mbtk_info_server.c b/mbtk/mbtk_ril/src/mbtk_info_server.c
new file mode 100755
index 0000000..7c92094
--- /dev/null
+++ b/mbtk/mbtk_ril/src/mbtk_info_server.c
@@ -0,0 +1,6251 @@
+#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 <fcntl.h>
+#include <signal.h>
+#include <cutils/properties.h>
+
+#include "mbtk_type.h"
+#include "mbtk_info.h"
+#include "mbtk_queue.h"
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_utils.h"
+#include "mbtk_ifc.h"
+#include "info_data.h"
+
+static int sock_listen_fd = -1;
+static int epoll_fd = -1;
+static list_node_t *sock_client_list = NULL;
+static mbtk_queue_node_t info_queue;
+static pthread_cond_t info_cond;
+static pthread_mutex_t info_mutex;
+static mbtk_queue_node_t urc_queue;
+static pthread_cond_t urc_cond;
+static pthread_mutex_t urc_mutex;
+
+static mbtk_band_info_t band_support;
+net_info_t net_info;
+mbtK_cell_pack_info_t cell_info;
+info_cgact_wait_t cgact_wait;
+static int cid_active[MBTK_APN_CID_MAX + 1] = {0};
+bool at_process = false;
+//mbtk wyq for data_call_ex add start
+//  |2----7|
+//"00000000"+'\0'
+static char cid_bootconn[MBTK_APN_CID_MAX + 2] = {0};
+#define DATA_CALL_BOOTCONN_FD 0x5f6f7f8f
+//mbtk wyq for data_call_ex add end
+
+//mbtk wyq for server_ready_status add start
+static char server_ready_status = 0;
+//mbtk wyq for server_ready_status add end
+
+static void sock_cli_free_func(void *data)
+{
+    if (data)
+    {
+        sock_client_info_t *info = (sock_client_info_t*) data;
+        LOG("Free Socket client[fd = %d].", info->fd);
+        free(info);
+    }
+}
+
+static void cli_close(sock_client_info_t* client)
+{
+    struct epoll_event ev;
+    memset(&ev,0,sizeof(struct epoll_event));
+    ev.data.fd = client->fd;
+    ev.events = EPOLLIN | EPOLLERR | EPOLLET;
+    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client->fd, &ev);
+
+    close(client->fd);
+
+    if(list_remove(sock_client_list, client))
+    {
+        sock_cli_free_func(client);
+    }
+}
+
+static void pack_error_send(int fd, int info_id, int err)
+{
+    mbtk_info_pack_t* pack = mbtk_info_pack_creat(info_id);
+    if(pack)
+    {
+        pack->info_err = (uint16)err;
+        mbtk_info_pack_send(fd, pack);
+        mbtk_info_pack_free(&pack);
+    }
+    else
+    {
+        LOG("mbtk_info_pack_creat() fail.");
+    }
+}
+
+void pack_rsp_send(int fd, int info_id, const void* data, int data_len)
+{
+    mbtk_info_pack_t* pack = mbtk_info_pack_creat(info_id);
+    if(pack)
+    {
+        pack->info_err = (uint16)MBTK_INFO_ERR_SUCCESS;
+        if(data != NULL && data_len > 0)
+        {
+            //mbtk_info_pack_data_set(pack, data, data_len);
+            pack->data_len = (uint16)data_len;
+            pack->data = (const uint8*)data;
+        }
+        mbtk_info_pack_send(fd, pack);
+        mbtk_info_pack_free(&pack);
+    }
+    else
+    {
+        LOG("mbtk_info_pack_creat() fail.");
+    }
+}
+
+static int apn_prop_set(mbtk_apn_info_t *apn)
+{
+    char prop_name[20] = {0};
+    char prop_data[300] = {0};
+    sprintf(prop_name, "%s_%d",MBTK_APN_PROP,apn->cid);
+    snprintf(prop_data, 300, "%d,%s,%s,%s,%s", apn->ip_type, apn->apn,
+        str_empty(apn->user) ? "NULL" : apn->user,
+        str_empty(apn->pass) ? "NULL" : apn->pass,
+        str_empty(apn->auth) ? "NULL" : apn->auth);
+
+    return property_set(prop_name, prop_data);
+}
+
+/*
+AT*BAND=?
+*BAND:(0-18),79,147,482,524503
+
+
+OK
+
+AT*BAND=15,78,147,482,134742231
+
+
+*/
+static void band_support_get()
+{
+    // Support band has get.
+    if(band_support.net_pref != 0xFF) {
+        return;
+    }
+
+#if 1
+    // 79,147,482,524503
+    band_support.gsm_band = (uint16)79;
+    band_support.umts_band = (uint16)147;
+    band_support.tdlte_band = (uint32)482;
+#if MBTK_LTE_B28_SUPPORT
+    band_support.fddlte_band = (uint32)134742231;
+#else
+    band_support.fddlte_band = (uint32)524503;
+#endif
+    band_support.net_pref = (uint8)0;
+#else
+    ATResponse *response = NULL;
+    int tmp_int;
+    char *tmp_str;
+    int err = at_send_command_singleline("AT*BAND=?", "*BAND:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates)
+        goto exit;
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    err = at_tok_nextstr(&line, &tmp_str);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    band_support.gsm_band = (uint16)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    band_support.umts_band = (uint16)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    band_support.tdlte_band = (uint32)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    band_support.fddlte_band = (uint32)tmp_int;
+    band_support.net_pref = (uint8)0;
+exit:
+    at_response_free(response);
+#endif
+}
+
+static int parseRegistrationState(char *str, int *items, int **response)
+{
+    int err;
+    char *line = str, *p;
+    int *resp = NULL;
+    int skip;
+    int commas;
+
+    LOGD("parseRegistrationState. Parsing: %s",str);
+    err = at_tok_start(&line);
+    if (err < 0) goto error;
+
+    /* Ok you have to be careful here
+     * The solicited version of the CREG response is
+     * +CREG: n, stat, [lac, cid]
+     * and the unsolicited version is
+     * +CREG: stat, [lac, cid]
+     * The <n> parameter is basically "is unsolicited creg on?"
+     * which it should always be
+     *
+     * Now we should normally get the solicited version here,
+     * but the unsolicited version could have snuck in
+     * so we have to handle both
+     *
+     * Also since the LAC and CID are only reported when registered,
+     * we can have 1, 2, 3, or 4 arguments here
+     *
+     * finally, a +CGREG: answer may have a fifth value that corresponds
+     * to the network type, as in;
+     *
+     *   +CGREG: n, stat [,lac, cid [,networkType]]
+     */
+
+    /* count number of commas */
+    commas = 0;
+    for (p = line ; *p != '\0' ; p++)
+    {
+        if (*p == ',') commas++;
+    }
+
+    resp = (int *)calloc(commas + 1, sizeof(int));
+    if (!resp) goto error;
+    switch (commas)
+    {
+        case 0: /* +CREG: <stat> */
+            err = at_tok_nextint(&line, &resp[0]);
+            if (err < 0) goto error;
+            //resp[1] = -1;
+            //resp[2] = -1;
+            break;
+
+        case 1: /* +CREG: <n>, <stat> */
+            err = at_tok_nextint(&line, &skip);
+            if (err < 0) goto error;
+            err = at_tok_nextint(&line, &resp[0]);
+            if (err < 0) goto error;
+            resp[1] = -1;
+            //resp[2] = -1;
+            if (err < 0) goto error;
+            break;
+
+        case 2: /* +CREG: <stat>, <lac>, <cid> */
+            err = at_tok_nextint(&line, &resp[0]);
+            if (err < 0) goto error;
+            err = at_tok_nexthexint(&line, &resp[1]);
+            if (err < 0) goto error;
+            err = at_tok_nexthexint(&line, &resp[2]);
+            if (err < 0) goto error;
+            break;
+        case 3: /* +CREG: <n>, <stat>, <lac>, <cid> */
+            /* +CEREG: 1,"8330","06447340",7 */
+#if 0
+            err = at_tok_nextint(&line, &skip);
+            if (err < 0) goto error;
+            err = at_tok_nextint(&line, &resp[0]);
+            if (err < 0) goto error;
+            err = at_tok_nexthexint(&line, &resp[1]);
+            if (err < 0) goto error;
+            err = at_tok_nexthexint(&line, &resp[2]);
+            if (err < 0) goto error;
+#else
+            err = at_tok_nextint(&line, &resp[0]);
+            if (err < 0) goto error;
+            err = at_tok_nextint(&line, &resp[1]);
+            if (err < 0) goto error;
+            err = at_tok_nexthexint(&line, &resp[2]);
+            if (err < 0) goto error;
+            err = at_tok_nextint(&line, &resp[3]);
+            if (err < 0) goto error;
+#endif
+            break;
+        /* special case for CGREG, there is a fourth parameter
+         * that is the network type (unknown/gprs/edge/umts)
+         */
+        case 4: /* +CGREG: <n>, <stat>, <lac>, <cid>, <networkType> */
+            /* +CEREG: 2,1,"8330","06447340",7 */
+            err = at_tok_nextint(&line, &skip);
+            if (err < 0) goto error;
+            err = at_tok_nextint(&line, &resp[0]);
+            if (err < 0) goto error;
+            err = at_tok_nexthexint(&line, &resp[1]);
+            if (err < 0) goto error;
+            err = at_tok_nexthexint(&line, &resp[2]);
+            if (err < 0) goto error;
+            err = at_tok_nexthexint(&line, &resp[3]);
+            if (err < 0) goto error;
+            break;
+        default:
+            goto error;
+    }
+    /*
+        if(commas > 1) {
+            s_lac = resp[1];
+            s_cid = resp[2];
+        }*/
+    if (response)
+        *response = resp;
+    if (items)
+        *items = commas + 1;
+    return 0;
+error:
+    free(resp);
+    return -1;
+}
+
+/*
+0: minimum functionality
+1: full functionality
+3: disable phone receive RF circuits.
+4: disable phone both transmit and receive RF circuits
+5: disable SIM
+6: turn off full secondary receive.
+-1: fail
+*/
+static int isRadioOn()
+{
+    ATResponse *p_response = NULL;
+    int err;
+    char *line;
+    int ret;
+
+    err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response);
+
+    if (err < 0 || p_response->success == 0 || !p_response->p_intermediates)
+    {
+        // assume radio is off
+        goto error;
+    }
+
+    line = p_response->p_intermediates->line;
+
+    err = at_tok_start(&line);
+    if (err < 0) goto error;
+
+    err = at_tok_nextint(&line, &ret);
+    if (err < 0) goto error;
+
+    at_response_free(p_response);
+
+    if(ret == 1) {
+        net_info.radio_state = MBTK_RADIO_STATE_ON;
+    } else {
+        net_info.radio_state = MBTK_RADIO_STATE_OFF;
+    }
+
+    return ret;
+
+error:
+
+    at_response_free(p_response);
+    return -1;
+}
+
+/** Returns SIM_NOT_READY on error */
+static mbtk_sim_state_enum getSIMStatus()
+{
+    ATResponse *p_response = NULL;
+    int err;
+    mbtk_sim_state_enum ret;
+    char *cpinLine;
+    char *cpinResult;
+
+    err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
+
+    if (err < 0 || p_response->success == 0 || !p_response->p_intermediates)
+    {
+        ret = MBTK_SIM_NOT_READY;
+        goto done;
+    }
+
+    switch (at_get_cme_error(p_response))
+    {
+        case CME_SUCCESS:
+            break;
+
+        case CME_SIM_NOT_INSERTED:
+            ret = MBTK_SIM_ABSENT;
+            goto done;
+
+        default:
+            ret = MBTK_SIM_NOT_READY;
+            goto done;
+    }
+
+    /* CPIN? has succeeded, now look at the result */
+
+    cpinLine = p_response->p_intermediates->line;
+    err = at_tok_start (&cpinLine);
+
+    if (err < 0)
+    {
+        ret = MBTK_SIM_NOT_READY;
+        goto done;
+    }
+
+    err = at_tok_nextstr(&cpinLine, &cpinResult);
+
+    if (err < 0)
+    {
+        ret = MBTK_SIM_NOT_READY;
+        goto done;
+    }
+
+    if (0 == strcmp (cpinResult, "SIM PIN"))
+    {
+        ret = MBTK_SIM_PIN;
+        goto done;
+    }
+    else if (0 == strcmp (cpinResult, "SIM PUK"))
+    {
+        ret = MBTK_SIM_PUK;
+        goto done;
+    }
+    else if (0 == strcmp (cpinResult, "PH-NET PIN"))
+    {
+        return MBTK_SIM_NETWORK_PERSONALIZATION;
+    }
+    else if (0 != strcmp (cpinResult, "READY"))
+    {
+        /* we're treating unsupported lock types as "sim absent" */
+        ret = MBTK_SIM_ABSENT;
+        goto done;
+    }
+
+    at_response_free(p_response);
+    p_response = NULL;
+    cpinResult = NULL;
+
+    // ret = net_info.radio_state == MBTK_RADIO_STATE_ON ? MBTK_SIM_READY : MBTK_SIM_NOT_READY;
+    net_info.sim_state = MBTK_SIM_READY;
+    return MBTK_SIM_READY;
+done:
+    at_response_free(p_response);
+    net_info.sim_state = ret;
+    return ret;
+}
+
+void setRadioPower(int isOn)
+{
+    int err;
+    ATResponse *p_response = NULL;
+
+    LOGI("RadioPower - %s", isOn == 0 ? "OFF" : "ON");
+
+    if(isOn == 0 && net_info.radio_state == MBTK_RADIO_STATE_ON)
+    {
+        err = at_send_command("AT+CFUN=0", &p_response);
+        if (err || !p_response->success)
+            goto error;
+
+        net_info.radio_state = MBTK_RADIO_STATE_OFF;
+    }
+    else if(isOn && net_info.radio_state != MBTK_RADIO_STATE_ON)
+    {
+        err = at_send_command("AT+CFUN=1", &p_response);
+        if (err || !p_response->success)
+        {
+            if(isRadioOn() == 1)
+            {
+                net_info.radio_state = MBTK_RADIO_STATE_ON;
+            }
+            goto error;
+        }
+
+        net_info.radio_state = MBTK_RADIO_STATE_ON;
+    }
+
+    at_response_free(p_response);
+    return;
+error:
+    at_response_free(p_response);
+}
+
+static int apn_user_pass_set_by_cid(int cid, mbtk_apn_info_t *apn)
+{
+    char prop_name[20] = {0};
+    char prop_data[300] = {0};
+    sprintf(prop_name, "%s_%d",MBTK_APN_PROP,cid);
+    if(property_get(prop_name, prop_data, "") > 0 && !str_empty(prop_data)) {
+        char apn_name[128] = {0};
+        char *ptr_1 = prop_data;
+        mbtk_ip_type_enum ip_type = (mbtk_ip_type_enum)atoi(ptr_1);
+        ptr_1 = strstr(ptr_1, ",");
+        if(!ptr_1) {
+            return -1;
+        }
+        ptr_1++; // Jump ',' to apn
+
+        char *ptr_2 = strstr(ptr_1, ",");
+        if(!ptr_2) {
+            return -1;
+        }
+        memcpy(apn_name, ptr_1, ptr_2 - ptr_1); // apn
+
+        // Check ip_type and apn_name
+        if(ip_type != apn->ip_type || strcmp(apn_name, apn->apn)) {
+            LOGD("APN Changed, not get user/pass/auth.");
+            return -1;
+        }
+
+        ptr_2++; // Jump ',' to user
+        ptr_1 = strstr(ptr_2, ",");
+        if(!ptr_1) {
+            return -1;
+        }
+        if(memcmp(ptr_2, "NULL", 4)) { // Not "NULL"
+            memcpy(apn->user, ptr_2, ptr_1 - ptr_2); // user
+        }
+
+        ptr_1++; // Jump ',' to pass
+        ptr_2 = strstr(ptr_1, ",");
+        if(!ptr_2) {
+            return -1;
+        }
+        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+            memcpy(apn->pass, ptr_1, ptr_2 - ptr_1); // pass
+        }
+
+        ptr_2++; // Jump ',' to auth (Is last item)
+        if(memcmp(ptr_2, "NULL", 4)) { // Not "NULL"
+            memcpy(apn->auth, ptr_2, strlen(ptr_2)); // auth
+        }
+
+        return 0;
+    }
+    return -1;
+}
+
+
+/*
+AT+CPOL?
+*EUICC: 1
+
+OK
+*/
+static int req_plmn_get(mbtk_plmn_info *type, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_multiline("AT+CPOL?", "+CPOL:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    int mccmnc_type = -1;
+    int count = -1;
+    char *mccmnc_name = NULL;
+    ATLine* lines_ptr = response->p_intermediates;
+    char *line = NULL;
+    while(lines_ptr)
+    {
+        line = lines_ptr->line;
+        //if(strStartsWith(line, "+CPOL:"))
+        {
+            err = at_tok_start(&line);
+            if (err < 0)
+            {
+                goto exit;
+            }
+            err = at_tok_nextint(&line, &count);
+            if (err < 0)
+            {
+                goto exit;
+            }
+            type->count = count;
+
+            err = at_tok_nextint(&line, &mccmnc_type);
+            if (err < 0)
+            {
+                goto exit;
+            }
+            type->mbtk_plmn_name[count-1].format = mccmnc_type;
+
+            err = at_tok_nextstr(&line, &mccmnc_name);
+            if (err < 0)
+            {
+                goto exit;
+            }
+            memcpy(type->mbtk_plmn_name[count-1].plmn_name, mccmnc_name, strlen(mccmnc_name));
+            mccmnc_name = NULL;
+        }
+        lines_ptr = lines_ptr->p_next;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+/*
+AT*EUICC?
+*EUICC: 1
+
+OK
+*/
+static int req_sim_card_type_get(uint8 *type, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT*EUICC?", "*EUICC:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    int sim_card_type = -1;
+    err = at_tok_nextint(&line, &sim_card_type);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    if(sim_card_type != -1)
+        *type = sim_card_type;
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+EPIN?
++EPIN: 3,0,10,0
+
+OK
+*/
+static int req_pin_puk_last_times_get(mbtk_pin_puk_last_times *times, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT+EPIN?", "+EPIN:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    mbtk_pin_puk_last_times last_times={0};
+    err = at_tok_nextint(&line, &(last_times.p1_retry));
+    if (err < 0)
+    {
+        goto exit;
+    }
+    times->p1_retry = last_times.p1_retry;
+    err = at_tok_nextint(&line, &(last_times.p2_retry));
+    if (err < 0)
+    {
+        goto exit;
+    }
+    times->p2_retry = last_times.p2_retry;
+    err = at_tok_nextint(&line, &(last_times.puk1_retry));
+    if (err < 0)
+    {
+        goto exit;
+    }
+    times->puk1_retry = last_times.puk1_retry;
+    err = at_tok_nextint(&line, &(last_times.puk2_retry));
+    if (err < 0)
+    {
+        goto exit;
+    }
+    times->puk2_retry = last_times.puk2_retry;
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+/*
+AT+CGSN
+864788050901201
+
+OK
+*/
+static int req_imei_get(void *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command_numeric("AT+CGSN", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates) {
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    memcpy(data, response->p_intermediates->line, strlen(response->p_intermediates->line));
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+MRD_SN=R
++MRD_SN:0101,Thu Nov 12 00:00:00 2020,G4M32301020006
+
+OK
+
+*/
+static int req_sn_get(void *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT+MRD_SN=R", "+MRD_SN:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    err = at_tok_nextstr(&line, &tmp_ptr);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    err = at_tok_nextstr(&line, &tmp_ptr);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    err = at_tok_nextstr(&line, &tmp_ptr);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    memcpy(data, tmp_ptr, strlen(tmp_ptr));
+
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+SYSTIME?
++SYSTIME: 1
+
+OK
+
+*/
+static int req_time_get(int *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int tmp_int;
+    int err = at_send_command_singleline("AT+SYSTIME?", "+SYSTIME:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    *data = tmp_int;
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CCLK?
++CCLK: "23/03/20,01:58:00+32"
+
+OK
+
+*/
+static int req_net_time_get(char *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT+CCLK?", "+CCLK:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextstr(&line, &tmp_ptr);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    memcpy(data, tmp_ptr, strlen(tmp_ptr));
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CFUN?
++CFUN: 1
+OK
+*/
+static int req_modem_get(int *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int modem;
+    int err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &modem);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    *data = modem;
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CFUN=<fun>[,<rst>]
+OK
+*/
+static int req_modem_set(mbtk_modem_info_t* modem, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+    int err = -1;
+
+    sprintf(cmd, "AT+CFUN=%d,%d", modem->fun, modem->rst);
+    err = at_send_command(cmd, &response);
+
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+/*
+    ATResponse *response = NULL;
+    int err = at_send_command_multiline(cmd, "", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    ATLine* lines_ptr = response->p_intermediates;
+    char *line = NULL;
+    while(lines_ptr)
+    {
+        line = lines_ptr->line;
+        if(strStartsWith(line, "Revision"))
+        {
+            err = at_tok_start(&line);
+            if (err < 0)
+            {
+                goto exit;
+            }
+            memcpy(data, line, strlen(line));
+            break;
+        }
+        lines_ptr = lines_ptr->p_next;
+    }
+
+    goto exit;
+*/
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+/*
+AT+SYSTIME=0,"2022-01-25-11:15:30"
+OK
+
+AT+SYSTIME=1
+OK
+*/
+static int req_time_set(int type, char *time, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int tmp_int;
+    char cmd[200] = {0};
+    if(str_empty(time)){
+        sprintf(cmd, "AT+SYSTIME=%d", type);
+    } else {
+        sprintf(cmd, "AT+SYSTIME=%d,\"%s\"", type, time);
+    }
+    int err = at_send_command(cmd, &response);
+
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+/*
+ATI
+Manufacturer:"LYNQ"
+Model:"LYNQ_L508TLC"
+Revision:L508TLCv02.01b01.00
+IMEI:864788050901201
+
+OK
+
+*/
+static int req_version_get(void *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command_multiline("ATI", "", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    ATLine* lines_ptr = response->p_intermediates;
+    char *line = NULL;
+    while(lines_ptr)
+    {
+        line = lines_ptr->line;
+        if(strStartsWith(line, "Revision"))
+        {
+            err = at_tok_start(&line);
+            if (err < 0)
+            {
+                goto exit;
+            }
+            memcpy(data, line, strlen(line));
+            break;
+        }
+        lines_ptr = lines_ptr->p_next;
+    }
+
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+ATI
+Manufacturer:"LYNQ"
+Model:"LYNQ_L508TLC"
+Revision:L508TLCv02.01b01.00
+IMEI:864788050901201
+
+OK
+
+*/
+static int req_model_get(void *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command_multiline("ATI", "", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    ATLine* lines_ptr = response->p_intermediates;
+    char *line = NULL;
+    while(lines_ptr)
+    {
+        line = lines_ptr->line;
+        if(strStartsWith(line, "Model"))
+        {
+            err = at_tok_start(&line);
+            if (err < 0)
+            {
+                goto exit;
+            }
+            memcpy(data, line, strlen(line));
+            break;
+        }
+        lines_ptr = lines_ptr->p_next;
+    }
+
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+ACONFIG="IMSD=1"
+or
+AT+ACONFIG="IMSD=0"
+
+OK
+*/
+static int req_volte_set(int state, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+    if(state)
+    {
+        strcpy(cmd, "AT+ACONFIG=\"IMSD=1\"");
+    }
+    else
+    {
+        strcpy(cmd, "AT+ACONFIG=\"IMSD=0\"");
+    }
+    int err = at_send_command(cmd, &response);
+
+    if (err < 0 || response->success == 0) {
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    err = 0;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+ACONFIG?
+PID=0,VID=0,IMSD=1,PIPE=0,FAST=0,RDUP=1,NOCP=0,GEFL=-1237040617
+
+OK
+*/
+static int req_volte_get(int *state, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT+ACONFIG?", "", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    char* ptr = strstr(line, "IMSD=");
+    if(ptr)
+    {
+        *state = atoi(ptr + strlen("IMSD="));
+    }
+    else
+    {
+        err = -1;
+    }
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+/*
+* Get system temperature.
+*
+* type[IN]:
+*   0: Soc temperature.
+*   1: RF temperature.
+* temp[OUT]:
+*   temperature in celsius.
+*
+
+AT*RFTEMP
+*RFTEMP:0,28
+OK
+
+AT*SOCTEMP
+*SOCTEMP:24000
+OK
+
+*/
+static int req_temp_get(int type, int *temp, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = -1;
+    int tmp_int;
+    if(type == 0) { // Soc
+        err = at_send_command_singleline("AT*SOCTEMP", "*SOCTEMP:", &response);
+    } else { // RF
+        err = at_send_command_singleline("AT*RFTEMP", "*RFTEMP:", &response);
+    }
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    if(type == 1) { // RF
+        err = at_tok_nextint(&line, &tmp_int);
+        if (err < 0)
+        {
+            goto exit;
+        }
+        *temp = tmp_int;
+    } else {
+        *temp = tmp_int / 1000;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT*BAND=15
+OK
+
+*/
+static int req_band_set(mbtk_band_info_t* band, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+    int err = -1;
+
+    if(band->gsm_band == 0 && band->umts_band == 0
+        && band->tdlte_band == 0 && band->fddlte_band == 0) {
+        sprintf(cmd, "AT*BAND=%d", band->net_pref);
+    } else {
+        band_support_get();
+
+        log_hex("BAND_SUPPORT", &band_support, sizeof(mbtk_band_info_t));
+        log_hex("BAND", band, sizeof(mbtk_band_info_t));
+
+        if(band->gsm_band == 0) {
+            band->gsm_band = band_support.gsm_band;
+        }
+        if(band->umts_band == 0) {
+            band->umts_band = band_support.umts_band;
+        }
+        if(band->tdlte_band == 0) {
+            band->tdlte_band = band_support.tdlte_band;
+        }
+        if(band->fddlte_band == 0) {
+            band->fddlte_band = band_support.fddlte_band;
+        }
+
+        if((band->gsm_band & band_support.gsm_band) != band->gsm_band) {
+            LOG("GSM band error.");
+            goto exit;
+        }
+
+        if((band->umts_band & band_support.umts_band) != band->umts_band) {
+            LOG("UMTS band error.");
+            goto exit;
+        }
+
+        if((band->tdlte_band & band_support.tdlte_band) != band->tdlte_band) {
+            LOG("TDLTE band error.");
+            goto exit;
+        }
+
+        if((band->fddlte_band & band_support.fddlte_band) != band->fddlte_band) {
+            LOG("FDDLTE band error.");
+            goto exit;
+        }
+
+        if(band->net_pref == 0xFF) { // No change net_pref.
+            int tmp_int;
+            err = at_send_command_singleline("AT*BAND?", "*BAND:", &response);
+            if (err < 0 || response->success == 0 || !response->p_intermediates){
+                *cme_err = at_get_cme_error(response);
+                goto exit;
+            }
+
+            char *line = response->p_intermediates->line;
+            err = at_tok_start(&line);
+            if (err < 0)
+            {
+                goto exit;
+            }
+
+            err = at_tok_nextint(&line, &tmp_int);
+            if (err < 0)
+            {
+                goto exit;
+            }
+            band->net_pref = (uint8)tmp_int; // Set to current net_pref.
+
+            at_response_free(response);
+        }
+
+        sprintf(cmd, "AT*BAND=%d,%d,%d,%d,%d", band->net_pref, band->gsm_band, band->umts_band, band->tdlte_band, band->fddlte_band);
+    }
+    err = at_send_command(cmd, &response);
+
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    err = 0;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+// ???????
+AT*BAND=?
+*BAND:(0-18),79,147,482,524503
+
+OK
+
+// ???????????
+AT*BAND?
+*BAND: 15, 78, 147, 482, 524503, 0, 2, 2, 0, 0
+
+OK
+
+// ?????????
+AT*BAND=5,79,147,128,1
+OK
+
+net_prefferred??
+    0 : GSM only
+    1 : UMTS only
+    2 : GSM/UMTS(auto)
+    3 : GSM/UMTS(GSM preferred)
+    4 : GSM/UMTS(UMTS preferred)
+    5 : LTE only
+    6 : GSM/LTE(auto)
+    7 : GSM/LTE(GSM preferred)
+    8 : GSM/LTE(LTE preferred)
+    9 : UMTS/LTE(auto)
+    10 : UMTS/LTE(UMTS preferred)
+    11 : UMTS/LTE(LTE preferred)
+    12 : GSM/UMTS/LTE(auto)
+    13 : GSM/UMTS/LTE(GSM preferred)
+    14 : GSM/UMTS/LTE(UMTS preferred)
+    15 : GSM/UMTS/LTE(LTE preferred)
+GSM band??
+    1 ?C PGSM 900 (standard or primary)
+    2 ?C DCS GSM 1800
+    4 ?C PCS GSM 1900
+    8 ?C EGSM 900 (extended)
+    16 ?C GSM 450
+    32 ?C GSM 480
+    64 ?C GSM 850
+    512 - BAND_LOCK_BIT // used for GSM band setting
+UMTS band??
+    1 ?C UMTS_BAND_1
+    2 ?C UMTS_BAND_2
+    4 ?C UMTS_BAND_3
+    8 ?C UMTS_BAND_4
+    16 ?C UMTS_BAND_5
+    32 ?C UMTS_BAND_6
+    64 ?C UMTS_BAND_7
+    128 ?C UMTS_BAND_8
+    256 ?C UMTS_BAND_9
+LTEbandH(TDD-LTE band)
+    32 ?C TDLTE_BAND_38
+    64 ?C TDLTE_BAND_39
+    128 ?C TDLTE_BAND_40
+    256 ?C TDLTE_BAND_41
+LTEbandL(FDD-LTE band)
+    1 ?C FDDLTE_BAND_1
+    4 ?C FDDLTE _BAND_3
+    8 ?C FDDLTE _BAND_4
+    64 ?C FDDLTE _BAND_7
+    65536 ?C FDDLTE _BAND_17
+    524288 ?C FDDLTE _BAND_20
+*/
+static int req_band_get(mbtk_band_info_t *band, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int tmp_int;
+
+    band_support_get();
+
+    log_hex("BAND_SUPPORT", &band_support, sizeof(mbtk_band_info_t));
+    int err = at_send_command_singleline("AT*BAND?", "*BAND:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    band->net_pref = (uint8)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    band->gsm_band = (uint16)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    band->umts_band = (uint16)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    band->tdlte_band = (uint32)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    band->fddlte_band = (uint32)tmp_int;
+
+    log_hex("BAND", band, sizeof(mbtk_band_info_t));
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+ICCID
++ICCID: 89860621330065648041
+
+OK
+*/
+static int req_iccid_get(void *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT+ICCID", "+ICCID:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    err = at_tok_nextstr(&line, &tmp_ptr);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    memcpy(data, tmp_ptr, strlen(tmp_ptr));
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CNUM?
++CNUM: "","13980414101",129
+
+OK
+
+*/
+static int req_phone_number_get(void *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT+CNUM?", "+CNUM:", &response);
+    if (err < 0 || response == NULL || response->success == 0 || !response->p_intermediates){
+        if(response) {
+            *cme_err = at_get_cme_error(response);
+        }
+        LOGD("AT+CNUM? fail.");
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    if(line == NULL) {
+        LOGD("line is NULL");
+        goto exit;
+    }
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    err = at_tok_nextstr(&line, &tmp_ptr);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    err = at_tok_nextstr(&line, &tmp_ptr);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    memcpy(data, tmp_ptr, strlen(tmp_ptr));
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+/*
+AT+CIMI
+460068103383304
+
+OK
+
+*/
+static int req_imsi_get(void *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command_numeric("AT+CIMI", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    memcpy(data, response->p_intermediates->line, strlen(response->p_intermediates->line));
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+/*
+AT+CLCK=SC,1/0,1234
++CLCK:1/0
+
+OK
+
+*/
+static int req_pin_enable(mbtk_enable_pin_info *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[64]={0};
+    sprintf(cmd, "AT+CLCK=SC,%d,%s", data->enable, data->pin_value);
+
+    int err = at_send_command_singleline(cmd, "+CLCK:", &response);
+    if (err < 0 || response == NULL || response->success == 0 || !response->p_intermediates){
+        if(response) {
+            *cme_err = at_get_cme_error(response);
+        }
+        LOGD("AT+CLCK? fail.");
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    if(line == NULL) {
+        LOGD("line is NULL");
+        goto exit;
+    }
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    int clck;
+    err = at_tok_nextint(&line, &clck);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CPIN=1234
+
+OK
+
+*/
+static int req_pin_verify(char *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[64]={0};
+    sprintf(cmd, "AT+CPIN=%s", data);
+    int err = at_send_command(cmd, &response);
+    if (err < 0 || response->success == 0){
+        if(cme_err) {
+            *cme_err = at_get_cme_error(response);
+        }
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CLCK=SC,2
++CLCK: 1
+
+OK
+
+AT+CLCK="SC",1,"1234"
++CLCK:1
+
+OK
+
+AT+CPWD="SC","1234","4321"
+
+OK
+
+*/
+static int req_pin_change(mbtk_change_pin_info *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[64]={0};
+
+    int err = at_send_command_singleline("AT+CLCK=SC,2", "+CLCK:", &response);
+    if (err < 0 || response == NULL || response->success == 0 || !response->p_intermediates){
+        if(response) {
+            *cme_err = at_get_cme_error(response);
+        }
+        LOGD("AT+CLCK fail.");
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    if(line == NULL) {
+        LOGD("line is NULL");
+        goto exit;
+    }
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    int clck;
+    err = at_tok_nextint(&line, &clck);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    at_response_free(response);
+
+    if(clck==0)
+    {
+        sprintf(cmd, "AT+CLCK=SC,1,%s", data->old_pin_value);
+        err = at_send_command_singleline(cmd, "+CLCK:", &response);
+        if (err < 0 || response == NULL || response->success == 0 || !response->p_intermediates){
+            if(response) {
+                *cme_err = at_get_cme_error(response);
+            }
+            LOGD("AT+CLCK fail.");
+            goto exit;
+        }
+        line = response->p_intermediates->line;
+        if(line == NULL) {
+            LOGD("line is NULL");
+            goto exit;
+        }
+        err = at_tok_start(&line);
+        if (err < 0)
+        {
+            goto exit;
+        }
+        clck = -1;
+        err = at_tok_nextint(&line, &clck);
+        if (err < 0)
+        {
+            goto exit;
+        }
+        at_response_free(response);
+        if(clck != 1)
+            return err;
+    }
+    memset(cmd, 0, 64);
+    sprintf(cmd, "AT+CPWD=SC,%s,%s", data->old_pin_value,data->new_pin_value);
+    err = at_send_command(cmd, &response);
+    if (err < 0 || response->success == 0){
+        if(cme_err) {
+            *cme_err = at_get_cme_error(response);
+        }
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CPIN?
++CPIN:SIM PUK
+
+OK
+
+AT+CPIN="PUK","PIN"
++CPIN: READY
+
+OK
+*/
+static int req_puk_unlock_pin(mbtk_unlock_pin_info *data, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[64]={0};
+#if 0
+    int err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &response);
+    if (err < 0 || response == NULL || response->success == 0 || !response->p_intermediates){
+        if(response) {
+            *cme_err = at_get_cme_error(response);
+        }
+        LOGD("AT+CNUM? fail.");
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    if(line == NULL) {
+        LOGD("line is NULL");
+        goto exit;
+    }
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    char *tmp_ptr = NULL;
+    err = at_tok_nextstr(&line, &tmp_ptr);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    at_response_free(response);
+
+    if(!strstr(tmp_ptr,"SIM PUK"))
+    {
+        sprintf(cmd, "AT+CPIN=%s,%s", data->puk_value, data->pin_value);
+        err = at_send_command_singleline(cmd, "+CPIN:", &response);
+        if (err < 0 || response == NULL || response->success == 0 || !response->p_intermediates){
+            if(response) {
+                *cme_err = at_get_cme_error(response);
+            }
+            LOGD("AT+CNUM? fail.");
+            goto exit;
+        }
+        line = response->p_intermediates->line;
+        if(line == NULL) {
+            LOGD("line is NULL");
+            goto exit;
+        }
+        err = at_tok_start(&line);
+        if (err < 0)
+        {
+            goto exit;
+        }
+        memset(tmp_ptr, 0, strlen(tmp_ptr));
+        err = at_tok_nextstr(&line, &tmp_ptr);
+        if (err < 0)
+        {
+            goto exit;
+        }
+        at_response_free(response);
+        if(strstr(tmp_ptr, "READY"))
+            return err;
+    }
+    else
+        return err;
+#else
+    sprintf(cmd, "AT+CPIN=%s,%s", data->puk_value, data->pin_value);
+    int err = at_send_command_singleline(cmd, "+CPIN: READY:", &response);
+    if (err < 0 || response == NULL || response->success == 0 || !response->p_intermediates){
+        if(response) {
+            *cme_err = at_get_cme_error(response);
+        }
+        LOGD("AT+CPIN fail.");
+        goto exit;
+    }
+#endif
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+COPS=?
+
++COPS: (2, "CHINA MOBILE", "CMCC", "46000", 7),(3, "CHN-CT", "CT", "46011", 7),(3, "CHN-UNICOM", "UNICOM", "46001", 7),(1, "460 15", "460 15", "46015", 7),,(0,1,2,3,4),(0,1,2)
+
+OK
+
+// Return [sel_mode(uint8)type(uint8)plmn(uint32)...sel_mode(uint8)type(uint8)plmn(uint32)]
+*/
+#if 0
+static int req_available_net_get(mbtk_net_array_info_t *data_ptr)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int tmp_int;
+    int err = at_send_command_singleline("AT+COPS=?", "+COPS:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates)
+        goto exit;
+#if 1
+    char *line_ptr = response->p_intermediates->line;
+    if(line_ptr == NULL) {
+        LOG("line is NULL");
+        goto exit;
+    }
+    //LOG("Line:%s",line_ptr);
+    line_ptr = strstr(line_ptr, "(");
+    while(line_ptr) {
+        line_ptr++;
+        // Only for available/current net.
+        if(*line_ptr == '1' || *line_ptr == '2') {
+            //LOG("Temp:%s",line_ptr);
+            //sleep(1);
+            line_ptr = strstr(line_ptr, ",");
+            if(line_ptr == NULL)
+                goto exit;
+            line_ptr++;
+
+            line_ptr = strstr(line_ptr, ",");
+            if(line_ptr == NULL)
+                goto exit;
+            line_ptr++;
+
+            line_ptr = strstr(line_ptr, ",");
+            if(line_ptr == NULL)
+                goto exit;
+
+            while(*line_ptr != '\0' && (*line_ptr == ',' || *line_ptr == ' ' || *line_ptr == '"'))
+                line_ptr++;
+
+            mbtk_net_info_t *net = (mbtk_net_info_t*)malloc(sizeof(mbtk_net_info_t));
+            if(net == NULL) {
+                LOG("malloc() fail.");
+                goto exit;
+            }
+            memset(net, 0, sizeof(mbtk_net_info_t));
+
+            // Point to "46000"
+            //LOG("PLMN:%s",line_ptr);
+            //sleep(1);
+            net->plmn = (uint32)atoi(line_ptr);
+
+            line_ptr = strstr(line_ptr, ",");
+            if(line_ptr == NULL)
+                goto exit;
+
+            while(*line_ptr != '\0' && (*line_ptr == ',' || *line_ptr == ' '))
+                line_ptr++;
+
+            // Point to "7"
+            if(*line_ptr == '\0') {
+                free(net);
+                goto exit;
+            }
+            //LOG("Type:%s",line_ptr);
+            //sleep(1);
+            net->net_type = (uint8)atoi(line_ptr);
+            list_add(data_ptr->net_list, net);
+            data_ptr->count++;
+        }
+
+        line_ptr = strstr(line_ptr, "(");
+    }
+#endif
+exit:
+    at_response_free(response);
+    return err;
+}
+#else
+static int req_available_net_get(void* buff, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int tmp_int;
+    int buff_size = 0;
+    int err = at_send_command_singleline("AT+COPS=?", "+COPS:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+    char *line_ptr = response->p_intermediates->line;
+    if(line_ptr == NULL) {
+        LOG("line is NULL");
+        goto exit;
+    }
+    uint8* buff_ptr = (uint8*)buff;
+    //LOG("Line:%s",line_ptr);
+    line_ptr = strstr(line_ptr, "(");
+    while(line_ptr) {
+        line_ptr++;
+        // Only for available/current net.
+        if(*line_ptr == '1' || *line_ptr == '2' || *line_ptr == '3') {
+            *(buff_ptr + 2) = (uint8)atoi(line_ptr); // net_state
+
+            line_ptr = strstr(line_ptr, ",");
+            if(line_ptr == NULL)
+                goto exit;
+            line_ptr++;
+
+            line_ptr = strstr(line_ptr, ",");
+            if(line_ptr == NULL)
+                goto exit;
+            line_ptr++;
+
+            line_ptr = strstr(line_ptr, ",");
+            if(line_ptr == NULL)
+                goto exit;
+
+            while(*line_ptr != '\0' && (*line_ptr == ',' || *line_ptr == ' ' || *line_ptr == '"'))
+                line_ptr++;
+
+            // set sel_mode to 0
+            *buff_ptr = (uint8)0;
+            // Point to "46000"
+            //LOG("PLMN:%s",line_ptr);
+            //sleep(1);
+            uint32_2_byte((uint32)atoi(line_ptr), buff_ptr + 3, false); // plmn
+
+            line_ptr = strstr(line_ptr, ",");
+            if(line_ptr == NULL)
+                goto exit;
+
+            while(*line_ptr != '\0' && (*line_ptr == ',' || *line_ptr == ' '))
+                line_ptr++;
+
+            // Point to "7"
+            if(*line_ptr == '\0') {
+                goto exit;
+            }
+            //LOG("Type:%s",line_ptr);
+            //sleep(1);
+            *(buff_ptr + 1) = (uint8)atoi(line_ptr); // net_type
+
+            buff_size += sizeof(mbtk_net_info_t);
+            buff_ptr += sizeof(mbtk_net_info_t);
+        }
+
+        line_ptr = strstr(line_ptr, "(");
+    }
+exit:
+    at_response_free(response);
+    return buff_size;
+}
+#endif
+
+/*
+AT+COPS?
++COPS: 1
+
+OK
+
+or
+
+AT+COPS?
++COPS: 0,2,"46001",7
+
+OK
+
+*/
+static int req_net_sel_mode_get(mbtk_net_info_t *net, int *cme_err)
+{
+    //LOG("req_net_sel_mode_get() 0");
+    //sleep(1);
+    ATResponse *response = NULL;
+    int tmp_int;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT+COPS?", "+COPS:", &response);
+    //LOG("req_net_sel_mode_get() 00");
+    //sleep(1);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        if(cme_err != NULL)
+            *cme_err = at_get_cme_error(response);
+        err = -1;
+        goto exit;
+    }
+    //LOG("req_net_sel_mode_get() 1");
+    //sleep(1);
+    char *line = response->p_intermediates->line;
+    if(line == NULL) {
+        LOG("line is NULL");
+        goto exit;
+    }
+    //LOG("req_net_sel_mode_get() 2");
+    //sleep(1);
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    //LOG("req_net_sel_mode_get() 3");
+    //sleep(1);
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    net->net_sel_mode = (uint8)tmp_int;
+    //LOG("req_net_sel_mode_get() 4");
+    //sleep(1);
+    // +COPS: 1
+    if(!at_tok_hasmore(&line)) {
+        goto exit;
+    }
+    //LOG("req_net_sel_mode_get() 5");
+    //sleep(1);
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    //LOG("req_net_sel_mode_get() 6");
+    //sleep(1);
+    err = at_tok_nextstr(&line, &tmp_ptr);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    // memcpy(net->plmn, tmp_ptr, strlen(tmp_ptr));
+    net->plmn = (uint32)atoi(tmp_ptr);
+    //LOG("req_net_sel_mode_get() 7");
+    //sleep(1);
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    net->net_type = (uint8)tmp_int;
+
+    net->net_state = (uint8)MBTK_NET_AVIL_STATE_CURRENT;
+
+exit:
+    //LOG("req_net_sel_mode_get() 8");
+    //sleep(1);
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+COPS=0
+or
+AT+COPS=1,2,"46000",7
+
+OK
+
+*/
+static int req_net_sel_mode_set(mbtk_net_info_t* net, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[50] = {0};
+    char* cmp_ptr = cmd;
+    if(net == NULL) {
+        cmp_ptr += sprintf(cmp_ptr, "AT+COPS=0");
+     } else {
+        if(net->net_sel_mode == 0) {
+            cmp_ptr += sprintf(cmp_ptr, "AT+COPS=0");
+        } else if(net->net_type == 0xFF) {
+            cmp_ptr += sprintf(cmp_ptr, "AT+COPS=1,2,\"%d\"",net->plmn);
+        } else {
+            cmp_ptr += sprintf(cmp_ptr, "AT+COPS=1,2,\"%d\",%d",net->plmn, net->net_type);
+        }
+     }
+
+    int err = at_send_command(cmd, &response);
+
+    if (err < 0 || response->success == 0) {
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+EEMOPT=1
+OK
+
+// LTE
+AT+EEMGINFO?
+// <mcc>, <length of mnc>, <mnc>, <tac>, <PCI>, <dlEuarfcn>, < ulEuarfcn >, <band>, <dlBandwidth>,
+// <rsrp>,<rsrq>, <sinr>,
+// errcModeState,emmState,serviceState,IsSingleEmmRejectCause,EMMRejectCause,mmeGroupId,mmeCode,mTmsi,
+// cellId,subFrameAssignType,specialSubframePatterns,transMode
+// mainRsrp,diversityRsrp,mainRsrq,diversityRsrq,rssi,cqi,pathLoss,tb0DlTpt,tb1DlTpt,tb0DlPeakTpt,tb1DlPeakTpt,tb0UlPeakTpt,
+// tb1UlPeakTpt,dlThroughPut,dlPeakThroughPut,averDlPRB,averCQITb0,averCQITb1,rankIndex,grantTotal,ulThroughPut,ulPeakThroughPut,currPuschTxPower,averUlPRB,
+// dlBer, ulBer,
+// diversitySinr, diversityRssi
++EEMLTESVC: 1120, 2, 0, 33584, 430, 40936, 40936, 41, 20,
+0, 0, 0,
+1, 10, 0, 1, 0, 1059, 78, 3959566565,
+105149248, 2, 7, 7,
+0, 0, 0, 0, 0, 0, 0, 1190919, 0, 0, 0, 16779777,
+0, 5112867, 3959566565, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+0, 0,
+7, 44
+
+// index,phyCellId,euArfcn,rsrp,rsrq
++EEMLTEINTER: 0, 65535, 38950, 0, 0
+
++EEMLTEINTER: 1, 0, 0, 0, 0
+
++EEMLTEINTER: 2, 0, 4294967295, 255, 255
+
++EEMLTEINTER: 3, 65535, 1300, 0, 0
+
++EEMLTEINTER: 4, 0, 0, 0, 0
+
++EEMLTEINTER: 5, 0, 4294967295, 247, 0
+
++EEMLTEINTER: 6, 197, 41332, 24, 9
+
++EEMLTEINTER: 7, 0, 0, 0, 0
+
++EEMLTEINTER: 8, 0, 0, 0, 0
+
++EEMLTEINTRA: 0, 429, 40936, 56, 12
+
++EEMLTEINTERRAT: 0,0
+
++EEMLTEINTERRAT: 1,0
+
++EEMGINFO: 3, 2         // <state>:
+                        // 0: ME in Idle mode
+                        // 1: ME in Dedicated mode
+                        // 2: ME in PS PTM mode
+                        // 3: invalid state
+                        // <nw_type>:
+                        // 0: GSM 1: UMTS 2: LTE
+
+OK
+
+// WCDMA
+AT+EEMGINFO?
+// Mode, sCMeasPresent, sCParamPresent, ueOpStatusPresent,
+
+// if sCMeasPresent == 1
+// cpichRSCP, utraRssi, cpichEcN0, sQual, sRxLev, txPower,
+// endif
+
+// if sCParamPresent == 1
+// rac, nom, mcc, mnc_len, mnc, lac, ci,
+// uraId, psc, arfcn, t3212, t3312, hcsUsed, attDetAllowed,
+// csDrxCycleLen, psDrxCycleLen, utranDrxCycleLen, HSDPASupport, HSUPASupport,
+// endif
+
+// if ueOpStatusPresent == 1
+// rrcState, numLinks, srncId, sRnti,
+// algPresent, cipherAlg, cipherOn, algPresent, cipherAlg, cipherOn,
+// HSDPAActive, HSUPAActive, MccLastRegisteredNetwork, MncLastRegisteredNetwork, TMSI, PTMSI, IsSingleMmRejectCause, IsSingleGmmRejectCause,
+// MMRejectCause, GMMRejectCause, mmState, gmmState, gprsReadyState, readyTimerValueInSecs, NumActivePDPContext, ULThroughput, DLThroughput,
+// serviceStatus, pmmState, LAU_status, LAU_count, RAU_status, RAU_count
+// endif
+//
++EEMUMTSSVC: 3, 1, 1, 1,
+-80, 27, -6, -18, -115, -32768,
+1, 1, 1120, 2, 1, 61697, 168432821,
+15, 24, 10763, 0, 0, 0, 0,
+128, 128, 65535, 0, 0,
+2, 255, 65535, 4294967295,
+0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0, 1, 1,
+28672, 28672, 0, 0, 0, 0, 0, 0, 0,
+0, 0, 0, 0, 0, 0
+
+// index, cpichRSCP, utraRssi, cpichEcN0, sQual, sRxLev ,mcc, mnc, lac, ci, arfcn, psc
++EEMUMTSINTRA: 0, -32768, -1, -32768, -18, -115, 0, 0, 65534, 1, 10763, 32
+
++EEMUMTSINTRA: 1, -1, -32768, -18, -115, 0, 0, 65534, 2, 10763, 40, 32768
+
++EEMUMTSINTRA: 2, -32768, -18, -115, 0, 0, 65534, 3, 10763, 278, 32768, 65535
+
++EEMUMTSINTRA: 3, -18, -115, 0, 0, -2, 4, 10763, 28, 32768, 65535, 32768
+
++EEMUMTSINTRA: 4, -115, 0, 0, -2, 5, 10763, 270, 32768, 65535, 32768, 65518
+
++EEMUMTSINTRA: 5, 0, 0, -2, 6, 10763, 286, 32768, 65535, 32768, 65518, 65421
+
++EEMUMTSINTRA: 6, 0, -2, 7, 10763, 80, 32768, 65535, 32768, 65518, 65421, 0
+
++EEMUMTSINTRA: 7, -2, 8, 10763, 206, -32768, 65535, 32768, 65518, 65421, 0, 0
+
++EEMUMTSINTRA: 8, 9, 10763, 11, -32768, -1, 32768, 65518, 65421, 0, 0, 65534
+
++EEMUMTSINTRA: 9, 10763, 19, -32768, -1, -32768, 65518, 65421, 0, 0, 65534, 11
+
++EEMUMTSINTRA: 10, 232, -32768, -1, -32768, -18, 65421, 0, 0, 65534, 12, 10763
+
++EEMUMTSINTRA: 11, -32768, -1, -32768, -18, -115, 0, 0, 65534, 13, 10763, 66
+
++EEMUMTSINTRA: 12, -1, -32768, -18, -115, 0, 0, 65534, 14, 10763, 216, 32768
+
++EEMUMTSINTRA: 13, -32768, -18, -115, 0, 0, 65534, 15, 10763, 183, 32768, 65535
+
++EEMUMTSINTRA: 14, -18, -115, 0, 0, -2, 16, 10763, 165, 32768, 65535, 32768
+
++EEMUMTSINTRA: 15, -115, 0, 0, -2, 17, 10763, 151, 32768, 65535, 32768, 65518
+
++EEMUMTSINTRA: 16, 0, 0, -2, 18, 10763, 43, 32768, 65535, 32768, 65518, 65421
+
++EEMUMTSINTRA: 17, 0, -2, 19, 10763, 72, 32768, 65535, 32768, 65518, 65421, 0
+
++EEMUMTSINTRA: 18, -2, 20, 10763, 157, -32768, 65535, 32768, 65518, 65421, 0, 0
+
++EEMUMTSINTRA: 19, 21, 10763, 165, -32768, -1, 32768, 65518, 65421, 0, 0, 65534
+
++EEMUMTSINTRA: 20, 10763, 301, -32768, -1, -32768, 65518, 65421, 0, 0, 65534, 23
+
++EEMUMTSINTRA: 21, 23, -32768, -1, -32768, -18, 65421, 0, 0, 65534, 24, 10763
+
++EEMUMTSINTRA: 22, -32768, -1, -32768, -18, -115, 0, 0, 65534, 25, 10763, 0
+
++EEMUMTSINTRA: 23, -1, -32768, -18, -115, 0, 0, 65534, 26, 10763, 167, 32768
+
++EEMUMTSINTRA: 24, -32768, -18, -115, 0, 0, 65534, 27, 10763, 34, 32768, 65535
+
++EEMUMTSINTRA: 25, -18, -115, 0, 0, -2, 28, 10763, 313, 32768, 65535, 32768
+
++EEMUMTSINTRA: 26, -115, 0, 0, -2, 29, 10763, 152, 32768, 65535, 32768, 65518
+
++EEMUMTSINTRA: 27, 0, 0, -2, 30, 10763, 239, 0, 0, 0, 0, 0
+
++EEMUMTSINTRA: 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+
++EEMUMTSINTRA: 29, 0, 0, 0, 0, -115, 0, 0, 65534, 30, 10763, 239
+
+// index,gsmRssi,rxLev,C1,C2,mcc,mnc,lac,ci,arfcn,bsic
++EEMUMTSINTERRAT: 0, -32768, -107, -1, -1, 0, 0, 65534, 0, 117, 36
+
++EEMUMTSINTERRAT: 1, -107, -1, -1, 0, 0, 65534, 1, 72, 49, 0
+
++EEMUMTSINTERRAT: 2, -1, -1, 0, 0, 65534, 2, 119, 15, 32768, 149
+
++EEMUMTSINTERRAT: 3, -1, 0, 0, -2, 3, 121, 23, 0, 0, 0
+
++EEMGINFO: 3, 1
+
+OK
+
+
+// GSM
+AT+EEMGINFO?
++EEMGINFOBASIC: 2
+
+// mcc, mnc_len, mnc, lac, ci, nom, nco,
+// bsic, C1, C2, TA, TxPwr,
+// RxSig, RxSigFull, RxSigSub, RxQualFull, RxQualSub,
+// ARFCB_tch, hopping_chnl, chnl_type, TS, PacketIdle, rac, arfcn,
+// bs_pa_mfrms, C31, C32, t3212, t3312, pbcch_support, EDGE_support,
+// ncc_permitted, rl_timeout, ho_count, ho_succ, chnl_access_count, chnl_access_succ_count,
+// gsmBand,channelMode
++EEMGINFOSVC: 1120, 2, 0, 32784, 24741, 2, 0,
+63, 36, 146, 1, 7,
+46, 42, 42, 7, 0,
+53, 0, 8, 0, 1, 6, 53,
+2, 0, 146, 42, 54, 0, 1,
+1, 32, 0, 0, 0, 0,
+0, 0
+
+// PS_attached, attach_type, service_type, tx_power, c_value,
+// ul_ts, dl_ts, ul_cs, dl_cs, ul_modulation, dl_modulation,
+// gmsk_cv_bep, 8psk_cv_bep, gmsk_mean_bep, 8psk_mean_bep, EDGE_bep_period, single_gmm_rej_cause
+// pdp_active_num, mac_mode, network_control, network_mode, EDGE_slq_measurement_mode, edge_status
++EEMGINFOPS: 1, 255, 0, 0, 0,
+0, 0, 268435501, 1, 0, 0,
+4, 0, 96, 0, 0, 0,
+0, 0, 0, 65535, 0, 13350
+
++EEMGINFO: 0, 0
+
+OK
+
+*/
+static int req_cell_info_get(int *cme_err)
+{
+    ATResponse *response = NULL;
+    int tmp_int;
+    int buff_size = 0;
+    // AT+EEMOPT=1 in the first.
+    int err = at_send_command("AT+EEMOPT=1", &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    // Reset buffer in the first.
+    memset(&cell_info, 0xFF, sizeof(mbtK_cell_pack_info_t));
+    cell_info.running = true;
+    cell_info.cell_num = 0;
+
+    err = at_send_command_singleline("AT+EEMGINFO?", "+EEMGINFO:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    // Now, cell infomation has get from URC message.
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    cell_info.type = (uint8)tmp_int;
+    cell_info.running = false;
+
+#if 0
+    while(lines_ptr)
+    {
+        // LTE
+        if(strStartsWith(line, "+EEMLTESVC:")) // LTE Server Cell
+        {
+
+        }
+        else if(strStartsWith(line, "+EEMLTEINTER:")) // LTE ???§³??
+        {
+
+        }
+        else if(strStartsWith(line, "+EEMLTEINTRA:")) // LTE ??§³??
+        {
+
+        }
+        else if(strStartsWith(line, "+EEMLTEINTERRAT:")) // LTE RAT§³?????
+        {
+
+        }
+        else if(strStartsWith(line, "+EEMGINFO:")) // <state>: 0: ME in Idle mode 1: ME in Dedicated mode 2: ME in PS PTM mode 3: invalid state
+                                                   // <nw_type>: 0: GSM 1: UMTS 2: LTE
+        {
+
+        }
+        // WCDMA
+        else if(strStartsWith(line, "+EEMUMTSSVC:")) // WCDMA Server Cell
+        {
+
+        }
+        else if(strStartsWith(line, "+EEMUMTSINTRA:")) // WCDMA???§³??
+        {
+
+        }
+        else if(strStartsWith(line, "+EEMUMTSINTERRAT:")) // WCDMA RAT§³?????
+        {
+
+        }
+        // GSM
+        else if(strStartsWith(line, "+EEMGINFOBASIC:")) // Basic information in GSM
+        // 0: ME in Idle mode   1: ME in Dedicated mode   2: ME in PS PTM mode
+        {
+
+        }
+        else if(strStartsWith(line, "+EEMGINFOSVC:")) // GSM Server Cell
+        {
+
+        }
+        else if(strStartsWith(line, "+EEMGINFOPS:")) // PS???
+        {
+
+        }
+
+
+        lines_ptr = lines_ptr->p_next;
+    }
+#endif
+
+exit:
+    at_response_free(response);
+    return buff_size;
+}
+
+static int req_cell_info_set(const char *cmgl, char *reg, int len, int *cme_err)
+{
+    printf("req_cmgl_set(2)-----------------start\n");
+    printf("cmgl:%s\n", cmgl);
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+	char data[218] = {0};
+    int err = 0;
+
+	memcpy(data, cmgl, len);
+
+	sprintf(cmd, "at*cell=%s", data);
+	printf("cmd:%s\n", cmd);
+
+	if(strlen(cmd) > 0)
+	{
+        err = at_send_command_multiline(cmd, "", &response);
+		if (err < 0 || response->success == 0 || !response->p_intermediates){
+			*cme_err = at_get_cme_error(response);
+        //    printf("at_send_command_multiline() is err-----------------\n");
+			goto exit;
+		}
+
+        ATLine* lines_ptr = response->p_intermediates;
+        char *line = NULL;
+        int reg_len = 0;
+		bool flag = false;
+        while(lines_ptr)
+        {
+            line = lines_ptr->line;
+            if(line ==NULL)
+            {
+                printf("line is null----------------------\n");
+            }
+            printf("-----line:%s\n", line);
+
+            lines_ptr = lines_ptr->p_next;
+        }
+	}
+    err = 0;
+	memcpy(reg, "req_cell_info_set succss", strlen("req_cell_info_set succss"));
+exit:
+    at_response_free(response);
+    printf("req_cell_info_set()-----------------end\n");
+    return err;
+}
+
+
+
+/*
+AT+CSQ
++CSQ: 31,99
+
+OK
+
+AT+CESQ
++CESQ: 60,99,255,255,20,61
+
+OK
+
+AT+COPS?
++COPS: 0,2,"46001",7
+
+OK
+
+*/
+static int req_net_signal_get(mbtk_signal_info_t *signal, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int tmp_int;
+    char *tmp_ptr = NULL;
+    // AT+EEMOPT=1 in the first.
+    int err = at_send_command_singleline("AT+CSQ", "+CSQ:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        if(cme_err != NULL)
+            *cme_err = at_get_cme_error(response);
+        err = -1;
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    signal->rssi = (uint8)tmp_int;
+    at_response_free(response);
+
+    err = at_send_command_singleline("AT+CESQ", "+CESQ:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        if(cme_err != NULL)
+            *cme_err = at_get_cme_error(response);
+        err = -1;
+        goto exit;
+    }
+
+    line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    signal->rxlev = (uint8)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    signal->ber = (uint8)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    signal->rscp = (uint8)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    signal->ecno = (uint8)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    signal->rsrq = (uint8)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    signal->rsrp = (uint8)tmp_int;
+
+    at_response_free(response);
+    err = at_send_command_singleline("AT+COPS?", "+COPS:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        if(cme_err != NULL)
+            *cme_err = at_get_cme_error(response);
+        err = -1;
+        goto exit;
+    }
+    line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    if(!at_tok_hasmore(&line)) {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextstr(&line, &tmp_ptr);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    signal->type = (uint8)tmp_int;
+    net_info.net_type = signal->type;
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CREG=3
+OK
+
+AT+CREG?
++CREG: 3,1,"8330","06447340",7
+
+OK
+
+AT+CREG?
++CREG: 3,0
+
+OK
+
+AT+CEREG?
++CEREG: 3,1,"8330","06447340",7
+
+OK
+
+
+AT+CIREG?
++CIREG: 2,1,15
+
+OK
+
+AT+CIREG?
++CIREG: 0
+
+OK
+
+
+*/
+static int req_net_reg_get(mbtk_net_reg_info_t *reg, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int tmp_int;
+    char *tmp_str = NULL;
+    int err = at_send_command("AT+CREG=3", &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+    at_response_free(response);
+
+    err = at_send_command_multiline("AT+CREG?", "+CREG:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int); // n
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);// stat
+    if (err < 0)
+    {
+        goto exit;
+    }
+    reg->call_state = (uint8)tmp_int;
+
+    if(at_tok_hasmore(&line)) {
+        err = at_tok_nextstr(&line, &tmp_str); // lac
+        if (err < 0)
+        {
+            goto exit;
+        }
+        reg->lac = strtol(tmp_str, NULL, 16);
+
+        err = at_tok_nextstr(&line, &tmp_str); // ci
+        if (err < 0)
+        {
+            goto exit;
+        }
+        reg->ci = strtol(tmp_str, NULL, 16);
+
+        err = at_tok_nextint(&line, &tmp_int);// AcT
+        if (err < 0)
+        {
+            goto exit;
+        }
+        reg->type = (uint8)tmp_int;
+    }
+    at_response_free(response);
+
+    err = at_send_command_multiline("AT+CEREG?", "+CEREG:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int); // n
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);// stat
+    if (err < 0)
+    {
+        goto exit;
+    }
+    reg->data_state = (uint8)tmp_int;
+
+    if(reg->lac == 0 && at_tok_hasmore(&line)) {
+        err = at_tok_nextstr(&line, &tmp_str); // lac
+        if (err < 0)
+        {
+            goto exit;
+        }
+        reg->lac = strtol(tmp_str, NULL, 16);
+
+        err = at_tok_nextstr(&line, &tmp_str); // ci
+        if (err < 0)
+        {
+            goto exit;
+        }
+        reg->ci = strtol(tmp_str, NULL, 16);
+
+        err = at_tok_nextint(&line, &tmp_int);// AcT
+        if (err < 0)
+        {
+            goto exit;
+        }
+        reg->type = (uint8)tmp_int;
+    }
+    at_response_free(response);
+
+    err = at_send_command_multiline("AT+CIREG?", "+CIREG:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        reg->ims_state = (uint8)0;
+        err = 0;
+        goto exit;
+    }
+    line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int); // n/stat
+    if (err < 0)
+    {
+        goto exit;
+    }
+    if(at_tok_hasmore(&line)) {
+        err = at_tok_nextint(&line, &tmp_int);// stat
+        if (err < 0)
+        {
+            goto exit;
+        }
+        reg->ims_state = (uint8)tmp_int;
+    } else {
+        reg->ims_state = (uint8)tmp_int;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CGDCONT?
++CGDCONT: 1,"IPV4V6","cmnet.MNC000.MCC460.GPRS","10.131.67.146 254.128.0.0.0.0.0.0.0.1.0.2.200.2.158.0",0,0,,,,
+
++CGDCONT: 8,"IPV4V6","IMS","254.128.0.0.0.0.0.0.0.1.0.2.200.2.160.160",0,0,0,2,1,1
+
+OK
+
+
+*/
+static int req_apn_get(void *data, int *data_len, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command_multiline("AT+CGDCONT?", "+CGDCONT:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    ATLine* lines_ptr = response->p_intermediates;
+    char *line = NULL;
+    int tmp_int;
+    char *tmp_str = NULL;
+    /*
+    <apn_num[1]><cid[1]><ip_type[1]><apn_len[2]><apn><user_len[2]><user><pass_len[2]><pass><auth_len[2]><auth>...
+                <cid[1]><ip_type[1]><apn_len[2]><apn><user_len[2]><user><pass_len[2]><pass><auth_len[2]><auth>
+    */
+    uint8* apn_num = (uint8*)data;
+    uint8* data_ptr = (uint8*)(data + sizeof(uint8)); // Jump apn_num[1]
+    mbtk_apn_info_t apn;
+    while(lines_ptr)
+    {
+        line = lines_ptr->line;
+        err = at_tok_start(&line);
+        if (err < 0)
+        {
+            goto exit;
+        }
+
+        err = at_tok_nextint(&line, &tmp_int); // cid
+        if (err < 0)
+        {
+            goto exit;
+        }
+        // Only get CID 1-7
+        if(tmp_int >= MBTK_APN_CID_MIN && tmp_int <= MBTK_APN_CID_MAX) {
+            memset(&apn, 0x0, sizeof(mbtk_apn_info_t));
+            apn.cid = tmp_int;
+            *data_ptr++ = (uint8)tmp_int; // cid
+
+            err = at_tok_nextstr(&line, &tmp_str);// ip type
+            if (err < 0)
+            {
+                goto exit;
+            }
+            if(!strcasecmp(tmp_str, "IP")) {
+                *data_ptr++ = (uint8)MBTK_IP_TYPE_IP;
+                apn.ip_type = MBTK_IP_TYPE_IP;
+            } else if(!strcasecmp(tmp_str, "IPV6")) {
+                *data_ptr++ = (uint8)MBTK_IP_TYPE_IPV6;
+                apn.ip_type = MBTK_IP_TYPE_IPV6;
+            } else if(!strcasecmp(tmp_str, "IPV4V6")) {
+                *data_ptr++ = (uint8)MBTK_IP_TYPE_IPV4V6;
+                apn.ip_type = MBTK_IP_TYPE_IPV4V6;
+            } else {
+                *data_ptr++ = (uint8)MBTK_IP_TYPE_PPP;
+                apn.ip_type = MBTK_IP_TYPE_PPP;
+            }
+
+            err = at_tok_nextstr(&line, &tmp_str); // apn
+            if (err < 0)
+            {
+                goto exit;
+            }
+            if(str_empty(tmp_str)) {
+                uint16_2_byte((uint16)0, data_ptr, false);
+                data_ptr += sizeof(uint16);
+            } else {
+                uint16_2_byte((uint16)strlen(tmp_str), data_ptr, false);
+                data_ptr += sizeof(uint16);
+                memcpy(data_ptr, tmp_str, strlen(tmp_str));
+                data_ptr += strlen(tmp_str);
+                memcpy(apn.apn, tmp_str, strlen(tmp_str));
+            }
+
+            if(apn_user_pass_set_by_cid(apn.cid, &apn)) {
+                // user
+                uint16_2_byte((uint16)0, data_ptr, false);
+                data_ptr += sizeof(uint16);
+
+                // pass
+                uint16_2_byte((uint16)0, data_ptr, false);
+                data_ptr += sizeof(uint16);
+
+                // auth
+                uint16_2_byte((uint16)0, data_ptr, false);
+                data_ptr += sizeof(uint16);
+            } else {
+                // user
+                if(str_empty(apn.user)) {
+                    uint16_2_byte((uint16)0, data_ptr, false);
+                    data_ptr += sizeof(uint16);
+                } else {
+                    uint16_2_byte((uint16)strlen(apn.user), data_ptr, false);
+                    data_ptr += sizeof(uint16);
+                    memcpy(data_ptr, apn.user, strlen(apn.user));
+                    data_ptr += strlen(apn.user);
+                }
+
+                // pass
+                if(str_empty(apn.pass)) {
+                    uint16_2_byte((uint16)0, data_ptr, false);
+                    data_ptr += sizeof(uint16);
+                } else {
+                    uint16_2_byte((uint16)strlen(apn.pass), data_ptr, false);
+                    data_ptr += sizeof(uint16);
+                    memcpy(data_ptr, apn.pass, strlen(apn.pass));
+                    data_ptr += strlen(apn.pass);
+                }
+
+                // auth
+                if(str_empty(apn.auth)) {
+                    uint16_2_byte((uint16)0, data_ptr, false);
+                    data_ptr += sizeof(uint16);
+                } else {
+                    uint16_2_byte((uint16)strlen(apn.auth), data_ptr, false);
+                    data_ptr += sizeof(uint16);
+                    memcpy(data_ptr, apn.auth, strlen(apn.auth));
+                    data_ptr += strlen(apn.auth);
+                }
+            }
+
+            (*apn_num)++;
+        }
+
+        lines_ptr = lines_ptr->p_next;
+    }
+
+    *data_len = data_ptr - (uint8*)data;
+
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+#if 0
+/*
+LTE APN
+AT+CFUN=4
+AT*CGDFLT=1,IP,"private.vpdn",1,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1
+AT*CGDFAUTH=1,2,"noc@njcc.vpdn.js","123456"
+AT+CFUN=1
+AT+CEREG?
+AT+CGDCONT?
+
+2/3G APN
+AT+CGREG?
+AT+CGDCONT=6,IP,"private.vpdn"
+AT*AUTHREQ=6,2,"noc@njcc.vpdn.js","123456"
+AT+CGDATA="",6
+AT+CGDCONT?
+*/
+static int req_apn_set_username(mbtk_apn_info_t *apn, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[400] = {0};
+    int index = 0;
+    int err = 0;
+
+    err = at_send_command_singleline("AT+COPS?", "+COPS:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        if(cme_err != NULL)
+            *cme_err = at_get_cme_error(response);
+        err = -1;
+        goto apn_set;
+    }
+
+    int tmp_int = 0;
+    int state=0;
+    char cmd_buf[64];
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto apn_set;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto apn_set;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto apn_set;
+    }
+    err = at_tok_nextstr(&line, &cmd_buf);
+    if (err < 0)
+    {
+        goto apn_set;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto apn_set;
+    }
+    else
+        state = tmp_int;
+
+apn_set:
+    at_response_free(response);
+    *cme_err = MBTK_INFO_ERR_CME_NON;
+    //if(state == 7 && apn->cid == 1)    //LTE && cid = 1
+    if(0)    //LTE && cid = 1
+    {
+        err = at_send_command("AT+CFUN=4", &response);
+        if (err < 0 || response->success == 0){
+            *cme_err = at_get_cme_error(response);
+            goto exit;
+        }
+        at_response_free(response);
+
+        memset(cmd, 0, 400);
+        index = 0;
+        index += sprintf(cmd, "AT*CGDFLT=%d,", 1);
+        switch(apn->ip_type) {
+            case MBTK_IP_TYPE_IP: {
+                index += sprintf(cmd + index,"\"IP\",");
+                break;
+            }
+            case MBTK_IP_TYPE_IPV6: {
+                index += sprintf(cmd + index,"\"IPV6\",");
+                break;
+            }
+            case MBTK_IP_TYPE_IPV4V6: {
+                index += sprintf(cmd + index,"\"IPV4V6\",");
+                break;
+            }
+            default: {
+                index += sprintf(cmd + index,"\"PPP\",");
+                break;
+            }
+        }
+
+        index += sprintf(cmd + index,"\"%s\",1,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1",apn->apn);
+        err = at_send_command(cmd, &response);
+        if (err < 0 || response->success == 0){
+            *cme_err = at_get_cme_error(response);
+            goto exit;
+        }
+        at_response_free(response);
+
+        memset(cmd, 0, 400);
+        int cmd_auth=0;
+        if(strstr(apn->auth,"NONE"))
+            cmd_auth = 0;
+        else if(strstr(apn->auth,"PAP"))
+            cmd_auth = 1;
+        else if(strstr(apn->auth,"CHAP"))
+            cmd_auth = 2;
+        else if(strstr(apn->auth,"PAP AND CHAP"))
+            cmd_auth = 3;
+        else
+            goto exit;
+
+        sprintf(cmd,"AT*CGDFAUTH=1,%d,%s,%s",cmd_auth,apn->user,apn->pass);
+
+        err = at_send_command(cmd, &response);
+        if (err < 0 || response->success == 0){
+            *cme_err = at_get_cme_error(response);
+            goto exit;
+        }
+    }
+    else                //2/3G
+    {
+        memset(cmd,0,400);
+        index = 0;
+        index += sprintf(cmd, "AT+CGDCONT=%d,", apn->cid);
+        switch(apn->ip_type) {
+            case MBTK_IP_TYPE_IP: {
+                index += sprintf(cmd + index,"\"IP\",");
+                break;
+            }
+            case MBTK_IP_TYPE_IPV6: {
+                index += sprintf(cmd + index,"\"IPV6\",");
+                break;
+            }
+            case MBTK_IP_TYPE_IPV4V6: {
+                index += sprintf(cmd + index,"\"IPV4V6\",");
+                break;
+            }
+            default: {
+                index += sprintf(cmd + index,"\"PPP\",");
+                break;
+            }
+        }
+        index += sprintf(cmd + index, "\"%s\"", apn->apn);
+
+        err = at_send_command(cmd, &response);
+        if (err < 0 || response->success == 0){
+            *cme_err = at_get_cme_error(response);
+            goto exit;
+        }
+        at_response_free(response);
+
+        memset(cmd,0,400);
+        int cmd_auth=0;
+        if(strstr(apn->auth,"NONE"))
+            cmd_auth = 0;
+        else if(strstr(apn->auth,"PAP"))
+            cmd_auth = 1;
+        else if(strstr(apn->auth,"CHAP"))
+            cmd_auth = 2;
+        else if(strstr(apn->auth,"PAP AND CHAP"))
+            cmd_auth = 3;
+        else
+            goto exit;
+
+        sprintf(cmd, "AT*AUTHREQ=%d,%d,%s,%s",apn->cid,cmd_auth,apn->user,apn->pass);
+        err = at_send_command(cmd, &response);
+        if (err < 0 || response->success == 0){
+            *cme_err = at_get_cme_error(response);
+            goto exit;
+        }
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+#endif
+
+/*
+AT+CGDCONT=1,"IPV4V6","cmnet"
+OK
+
+AT*CGDFLT=1,"IPv4v6","reliance.grevpdn.zj",,,,,,,,,,,,,,,,,,1
+OK
+
+*/
+static int req_apn_set(mbtk_apn_info_t *apn, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[400] = {0};
+    int index = 0;
+    int err = 0;
+
+    index += sprintf(cmd, "AT+CGDCONT=%d,", apn->cid);
+    switch(apn->ip_type) {
+        case MBTK_IP_TYPE_IP: {
+            index += sprintf(cmd + index,"\"IP\",");
+            break;
+        }
+        case MBTK_IP_TYPE_IPV6: {
+            index += sprintf(cmd + index,"\"IPV6\",");
+            break;
+        }
+        case MBTK_IP_TYPE_IPV4V6: {
+            index += sprintf(cmd + index,"\"IPV4V6\",");
+            break;
+        }
+        default: {
+            index += sprintf(cmd + index,"\"PPP\",");
+            break;
+        }
+    }
+    if(strlen(apn->apn) > 0) {
+        index += sprintf(cmd + index,"\"%s\"", apn->apn);
+    } else {
+        LOGE("No set APN.");
+        err = -1;
+        goto exit;
+    }
+
+    err = at_send_command(cmd, &response);
+    if (err < 0 || response->success == 0){
+        if(cme_err) {
+            *cme_err = at_get_cme_error(response);
+        }
+        goto exit;
+    }
+
+    if(!str_empty(apn->user) || !str_empty(apn->pass)) {
+        at_response_free(response);
+
+        memset(cmd,0,400);
+        int cmd_auth=0;
+        if(strstr(apn->auth,"NONE"))
+            cmd_auth = 0;
+        else if(strstr(apn->auth,"PAP"))
+            cmd_auth = 1;
+        else if(strstr(apn->auth,"CHAP"))
+            cmd_auth = 2;
+#if 0
+        else if(strstr(apn->auth,"PAP AND CHAP"))
+            cmd_auth = 3;
+#endif
+        else
+            goto exit;
+
+        sprintf(cmd, "AT*AUTHREQ=%d,%d,%s,%s",apn->cid,cmd_auth,apn->user,apn->pass);
+        err = at_send_command(cmd, &response);
+        if (err < 0 || response->success == 0){
+            *cme_err = at_get_cme_error(response);
+            goto exit;
+        }
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+int wait_cgact_complete(int timeout)
+{
+    int count = timeout * 10; // timeout * 1000 / 100
+    int i = 0;
+
+    while(cgact_wait.waitting && i < count) {
+        i++;
+        usleep(100000); // 100ms
+    }
+
+    if(i == count) { // Timeout
+        return -1;
+    } else {
+        return 0;
+    }
+}
+
+/*
+AT+CGDATA="",6
+CONNECT
+
+OK
+
+AT+CFUN=1
+
+OK
+
+*/
+static int req_data_call_user_start(int cid, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[400] = {0};
+    int index = 0;
+    int err = 0;
+
+    err = at_send_command_singleline("AT+COPS?", "+COPS:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        if(cme_err != NULL)
+            *cme_err = at_get_cme_error(response);
+        err = -1;
+        goto exit;
+    }
+
+    int tmp_int;
+    char cmd_buf[64];
+    char *line = response->p_intermediates->line;
+    err = at_tok_start(&line);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextstr(&line, &cmd_buf);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    at_response_free(response);
+
+    if(tmp_int == 7 && cid == 1)    //LTE && cid = 1
+    {
+        ATResponse *response = NULL;
+        char cmd[400] = {0};
+        int err = 0;
+
+        err = at_send_command("AT+CFUN=1", &response);
+        if (err < 0 || response->success == 0){
+            if(cme_err) {
+                *cme_err = at_get_cme_error(response);
+            }
+            goto exit;
+        }
+    }
+    else
+    {
+        ATResponse *response = NULL;
+        char cmd[400] = {0};
+        int err = 0;
+        sprintf(cmd, "AT+CGDATA=\"\",%d", cid);
+        err = at_send_command(cmd, &response);
+        if (err < 0 || response->success == 0){
+            if(cme_err) {
+                *cme_err = at_get_cme_error(response);
+            }
+            goto exit;
+        }
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CGACT?
++CGACT: 1,1
++CGACT: 8,1
+OK
+
+AT+CGACT=1,<cid>
+OK
+
+*/
+static int req_data_call_start(int cid, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[400] = {0};
+    int err = 0;
+#if 0
+    err = at_send_command_multiline("AT+CGACT?", "+CGACT:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+    ATLine* lines_ptr = response->p_intermediates;
+    char *line = NULL;
+    int tmp_int;
+    while(lines_ptr)
+    {
+        line = lines_ptr->line;
+        err = at_tok_start(&line);
+        if (err < 0)
+        {
+            goto exit;
+        }
+
+        err = at_tok_nextint(&line, &tmp_int); // cid
+        if (err < 0)
+        {
+            goto exit;
+        }
+        if(tmp_int == cid) { // Found cid
+            err = at_tok_nextint(&line, &tmp_int); // cid
+            if (err < 0)
+            {
+                goto exit;
+            }
+            if(tmp_int == 1) { // This cid has active.
+                goto net_config;
+            } else {
+                goto cid_active;
+            }
+            break;
+        }
+
+        lines_ptr = lines_ptr->p_next;
+    }
+
+    if(lines_ptr == NULL) { // No found this cid.
+        LOGE("No found cid : %d", cid);
+        goto exit;
+    }
+    at_response_free(response);
+
+    // Start active cid.
+cid_active:
+#endif
+
+    sprintf(cmd, "AT+CGACT=1,%d", cid);
+    err = at_send_command(cmd, &response);
+    if (err < 0 || response->success == 0){
+        if(cme_err) {
+            *cme_err = at_get_cme_error(response);
+        }
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CGACT=0,<cid>
+OK
+
+*/
+static int req_data_call_stop(int cid, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[400] = {0};
+    int err = 0;
+#if 0
+    err = at_send_command_multiline("AT+CGACT?", "+CGACT:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+    ATLine* lines_ptr = response->p_intermediates;
+    char *line = NULL;
+    int tmp_int;
+    while(lines_ptr)
+    {
+        line = lines_ptr->line;
+        err = at_tok_start(&line);
+        if (err < 0)
+        {
+            goto exit;
+        }
+
+        err = at_tok_nextint(&line, &tmp_int); // cid
+        if (err < 0)
+        {
+            goto exit;
+        }
+        if(tmp_int == cid) { // Found cid
+            err = at_tok_nextint(&line, &tmp_int); // cid
+            if (err < 0)
+            {
+                goto exit;
+            }
+            if(tmp_int == 1) { // This cid has active.
+                goto net_config;
+            } else {
+                goto cid_active;
+            }
+            break;
+        }
+
+        lines_ptr = lines_ptr->p_next;
+    }
+
+    if(lines_ptr == NULL) { // No found this cid.
+        LOGE("No found cid : %d", cid);
+        goto exit;
+    }
+    at_response_free(response);
+
+    // Start active cid.
+cid_active:
+#endif
+
+    sprintf(cmd, "AT+CGACT=0,%d", cid);
+    err = at_send_command(cmd, &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+IPv4 : 10.255.74.26
+IPv6 : 254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239
+*/
+static bool is_ipv4(const char *ip)
+{
+    const char *ptr = ip;
+    int count = 0;
+    while(*ptr) {
+        if(*ptr == '.')
+            count++;
+        ptr++;
+    }
+
+    if(count == 3) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+/*
+AT+CGCONTRDP=1
++CGCONTRDP: 1,7,"cmnet-2.MNC000.MCC460.GPRS","10.255.74.26","","223.87.253.100","223.87.253.253","","",0,0
++CGCONTRDP: 1,7,"cmnet-2.MNC000.MCC460.GPRS","254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239","","36.9.128.98.32.0.0.2.0.0.0.0.0.0.0.1","36.9.128.98.32.0.0.2.0.0.0.0.0.0.0.2","","",0,0
+
+OK
+
+*/
+static int req_data_call_state_get(int cid, mbtk_ipv4_info_t *ipv4, mbtk_ipv6_info_t *ipv6, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[50] = {0};
+    int err = 0;
+
+    sprintf(cmd, "AT+CGCONTRDP=%d", cid);
+
+    err = at_send_command_multiline(cmd, "+CGCONTRDP:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+    ATLine* lines_ptr = response->p_intermediates;
+    char *line = NULL;
+    int tmp_int;
+    char *tmp_ptr = NULL;
+    while(lines_ptr)
+    {
+        line = lines_ptr->line;
+        err = at_tok_start(&line);
+        if (err < 0)
+        {
+            goto exit;
+        }
+
+        err = at_tok_nextint(&line, &tmp_int); // cid
+        if (err < 0)
+        {
+            goto exit;
+        }
+        err = at_tok_nextint(&line, &tmp_int); // bearer_id
+        if (err < 0)
+        {
+            goto exit;
+        }
+        err = at_tok_nextstr(&line, &tmp_ptr); // APN
+        if (err < 0)
+        {
+            goto exit;
+        }
+
+        err = at_tok_nextstr(&line, &tmp_ptr); // IP
+        if (err < 0 || str_empty(tmp_ptr))
+        {
+            goto exit;
+        }
+        if(is_ipv4(tmp_ptr)) {
+            if(inet_pton(AF_INET, tmp_ptr, &(ipv4->IPAddr)) < 0) {
+                LOGE("inet_pton() fail.");
+                err = -1;
+                goto exit;
+            }
+
+            ipv4->valid = true;
+            //log_hex("IPv4", &(ipv4->IPAddr), sizeof(struct in_addr));
+        } else {
+            if(str_2_ipv6(tmp_ptr, &(ipv6->IPV6Addr))) {
+                LOGE("str_2_ipv6() fail.");
+                err = -1;
+                goto exit;
+            }
+
+            ipv6->valid = true;
+            //log_hex("IPv6", &(ipv6->IPV6Addr), 16);
+        }
+
+        err = at_tok_nextstr(&line, &tmp_ptr); // Gateway
+        if (err < 0)
+        {
+            goto exit;
+        }
+        if(!str_empty(tmp_ptr)) { // No found gateway
+            if(is_ipv4(tmp_ptr)) {
+                if(inet_pton(AF_INET, tmp_ptr, &(ipv4->GateWay)) < 0) {
+                    LOGE("inet_pton() fail.");
+                    err = -1;
+                    goto exit;
+                }
+
+                //log_hex("IPv4", &(ipv4->GateWay), sizeof(struct in_addr));
+            } else {
+                if(str_2_ipv6(tmp_ptr, &(ipv6->GateWay))) {
+                    LOGE("str_2_ipv6() fail.");
+                    err = -1;
+                    goto exit;
+                }
+
+                //log_hex("IPv6", &(ipv6->GateWay), 16);
+            }
+        }
+
+        err = at_tok_nextstr(&line, &tmp_ptr); // prim_DNS
+        if (err < 0)
+        {
+            goto exit;
+        }
+        if(!str_empty(tmp_ptr)) { // No found Primary DNS
+            if(is_ipv4(tmp_ptr)) {
+                if(inet_pton(AF_INET, tmp_ptr, &(ipv4->PrimaryDNS)) < 0) {
+                    LOGE("inet_pton() fail.");
+                    err = -1;
+                    goto exit;
+                }
+
+                //log_hex("IPv4", &(ipv4->PrimaryDNS), sizeof(struct in_addr));
+            } else {
+                if(str_2_ipv6(tmp_ptr, &(ipv6->PrimaryDNS))) {
+                    LOGE("str_2_ipv6() fail.");
+                    err = -1;
+                    goto exit;
+                }
+
+                //log_hex("IPv6", &(ipv6->PrimaryDNS), 16);
+            }
+        }
+
+        err = at_tok_nextstr(&line, &tmp_ptr); // sec_DNS
+        if (err < 0)
+        {
+            goto exit;
+        }
+        if(!str_empty(tmp_ptr)) { // No found Secondary DNS
+            if(is_ipv4(tmp_ptr)) {
+                if(inet_pton(AF_INET, tmp_ptr, &(ipv4->SecondaryDNS)) < 0) {
+                    LOGE("inet_pton() fail.");
+                    err = -1;
+                    goto exit;
+                }
+
+                //log_hex("IPv4", &(ipv4->SecondaryDNS), sizeof(struct in_addr));
+            } else {
+                if(str_2_ipv6(tmp_ptr, &(ipv6->SecondaryDNS))) {
+                    LOGE("str_2_ipv6() fail.");
+                    err = -1;
+                    goto exit;
+                }
+
+                //log_hex("IPv6", &(ipv6->SecondaryDNS), 16);
+            }
+        }
+
+        lines_ptr = lines_ptr->p_next;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CGCONTRDP
++CGCONTRDP: 1,5,"cmnet.MNC000.MCC460.GPRS","10.156.238.86","","223.87.253.100","223.87.253.253","","",0,0
++CGCONTRDP: 1,5,"cmnet.MNC000.MCC460.GPRS","254.128.0.0.0.0.0.0.0.1.0.1.181.5.77.221","","36.9.128.98.32.0.0.2.0.0.0.0.0.0.0.1","36.9.128.98.32.0.0.2.0,0,0
++CGCONTRDP: 8,6,"IMS.MNC000.MCC460.GPRS","254.128.0.0.0.0.0.0.0.1.0.1.181.5.79.116","","","","36.9.128.98.80.2.0.87.0.0.0.0.0.3.31.1","36.9.128.98.80.2,1,0
+OK
+
+*/
+static int apn_state_get(list_node_t **apn_list)
+{
+    ATResponse *response = NULL;
+    int err = 0;
+    *apn_list = list_create(NULL);
+    if(*apn_list == NULL)
+    {
+        LOG("list_create() fail.");
+        return -1;
+    }
+
+    err = at_send_command_multiline("AT+CGCONTRDP", "+CGCONTRDP:", &response);
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        goto exit;
+    }
+    ATLine* lines_ptr = response->p_intermediates;
+    char *line = NULL;
+    int tmp_int;
+    char *tmp_ptr = NULL;
+    int cid_current = 0;
+    info_apn_ip_t *apn = NULL;
+    while(lines_ptr)
+    {
+        line = lines_ptr->line;
+        err = at_tok_start(&line);
+        if (err < 0)
+        {
+            goto exit;
+        }
+
+        err = at_tok_nextint(&line, &tmp_int); // cid
+        if (err < 0)
+        {
+            goto exit;
+        }
+
+        if(tmp_int != 1 && tmp_int != 8) { // Not process cid 1 and 8.
+            if(cid_current != tmp_int) { // New cid.
+                apn = (info_apn_ip_t*)malloc(sizeof(info_apn_ip_t));
+                if(apn == NULL) {
+                    goto exit;
+                }
+                memset(apn, 0, sizeof(info_apn_ip_t));
+                apn->cid = tmp_int;
+                cid_current = tmp_int;
+
+                list_add(*apn_list, apn);
+            }
+            err = at_tok_nextint(&line, &tmp_int); // bearer_id
+            if (err < 0)
+            {
+                goto exit;
+            }
+            err = at_tok_nextstr(&line, &tmp_ptr); // APN
+            if (err < 0)
+            {
+                goto exit;
+            }
+
+            err = at_tok_nextstr(&line, &tmp_ptr); // IP
+            if (err < 0 || str_empty(tmp_ptr))
+            {
+                goto exit;
+            }
+            if(is_ipv4(tmp_ptr)) {
+                apn->ipv4_valid = true;
+                memcpy(apn->ipv4, tmp_ptr, strlen(tmp_ptr));
+            } else {
+                apn->ipv6_valid = true;
+                uint8 tmp_ipv6[16];
+                if(str_2_ipv6(tmp_ptr, tmp_ipv6)) {
+                    LOGE("str_2_ipv6() fail.");
+                    err = -1;
+                    goto exit;
+                }
+
+                if(inet_ntop(AF_INET6, tmp_ipv6, apn->ipv6, 50) == NULL) {
+                    err = -1;
+                    LOGE("inet_ntop ipv6 ip fail.");
+                    goto exit;
+                }
+            }
+        }
+
+        lines_ptr = lines_ptr->p_next;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+mbtk_info_err_enum call_pack_req_process(sock_client_info_t* cli_info, mbtk_info_pack_t* pack);
+mbtk_info_err_enum sms_pack_req_process(sock_client_info_t* cli_info, mbtk_info_pack_t* pack);
+mbtk_info_err_enum pb_pack_req_process(sock_client_info_t* cli_info, mbtk_info_pack_t* pack);
+//mbtk wyq for data_call_ex add start
+void data_call_bootconn_save(int cid, int bootconn);
+//mbtk wyq for data_call_ex add end
+
+//void net_list_free(void *data);
+// Return MBTK_INFO_ERR_SUCCESS,will call pack_error_send() to send RSP.
+// Otherwise, do not call pack_error_send().
+static mbtk_info_err_enum pack_req_process(sock_client_info_t* cli_info, mbtk_info_pack_t* pack)
+{
+    if(pack->info_id > MBTK_INFO_ID_CALL_BEGIN && pack->info_id < MBTK_INFO_ID_CALL_END) {
+        return call_pack_req_process(cli_info, pack);
+    } else if(pack->info_id > MBTK_INFO_ID_SMS_BEGIN && pack->info_id < MBTK_INFO_ID_SMS_END) {
+        return sms_pack_req_process(cli_info, pack);
+    } else if(pack->info_id > MBTK_INFO_ID_PB_BEGIN && pack->info_id < MBTK_INFO_ID_PB_END) {
+        return pb_pack_req_process(cli_info, pack);
+    } else {
+        mbtk_info_err_enum err = MBTK_INFO_ERR_SUCCESS;
+        int cme_err = MBTK_INFO_ERR_CME_NON;
+        switch(pack->info_id)
+        {
+            case MBTK_INFO_ID_DEV_IMEI_REQ: // <string> IMEI
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get IMEI
+                {
+                    char imei[20] = {0};
+                    if(req_imei_get(imei, &cme_err) || strlen(imei) == 0 || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get IMEI fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_DEV_IMEI_RSP, imei, strlen(imei));
+                    }
+                }
+                else     // Set IMEI(Unsupport).
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport set IMEI.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_DEV_SN_REQ: // <string> SN
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get SN
+                {
+                    char sn[20] = {0};
+                    if(req_sn_get(sn, &cme_err) || strlen(sn) == 0 || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get SN fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_DEV_SN_RSP, sn, strlen(sn));
+                    }
+                }
+                else     // Set SN(Unsupport).
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport set SN.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_DEV_MEID_REQ: // <string> MEID (Only for CDMA)
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get MEID
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Support only for CDMA.");
+                }
+                else     // Set MEID(Unsupport).
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport set MEID.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_DEV_VERSION_REQ: // <string> VERSION
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get VERSION
+                {
+                    char version[50] = {0};
+                    if(req_version_get(version, &cme_err) || strlen(version) == 0 || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get Version fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_DEV_VERSION_RSP, version, strlen(version));
+                    }
+                }
+                else     // Set VERSION(Unsupport).
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport set VERSION.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_DEV_MODEL_REQ: //MODEL
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get MODEL
+                {
+                    char model[50] = {0};
+                    if(req_model_get(model, &cme_err) || strlen(model) == 0 || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get model fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_DEV_VERSION_RSP, model, strlen(model));
+                    }
+                }
+                else     // Set model(Unsupport).
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport set model.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_DEV_MODEM_REQ: //MODEM
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get MODEM
+                {
+                    int modem = -1;
+                    if(req_modem_get(&modem, &cme_err) || modem < 0 || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get modem fail.");
+                    }
+                    else
+                    {
+                        uint8 modem_type = (uint8)modem;
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_DEV_MODEM_RSP, &modem_type, sizeof(uint8));
+                    }
+                }
+                else     // Set modem
+                {
+                    mbtk_modem_info_t *modem = (mbtk_modem_info_t *)pack->data;
+                    if(pack->data_len != sizeof(mbtk_modem_info_t))
+                    {
+                        err = MBTK_INFO_ERR_REQ_PARAMETER;
+                        LOG("Set modem error.");
+                        break;
+                    }
+                    if(req_modem_set(modem, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        LOG("Set modem fail.");
+                        err = MBTK_INFO_ERR_FORMAT;
+                    } else {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_DEV_MODEM_RSP, NULL, 0);
+                    }
+                }
+                break;
+            }
+            case MBTK_INFO_ID_DEV_TIME_REQ: // <uint8><string>  YYYY-MM-DD-HH:MM:SS
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get Time
+                {
+                    int type = -1;
+                    if(req_time_get(&type, &cme_err) || type < 0 || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get Time fail.");
+                    }
+                    else
+                    {
+                        uint8 time_type = (uint8)type;
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_DEV_TIME_RSP, &time_type, sizeof(uint8));
+                    }
+                }
+                else     // Set Time
+                {
+                    if(pack->data_len == sizeof(uint8)) {
+                        if(req_time_set(*(pack->data), NULL, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                        {
+                            LOG("Set Time fail.");
+                            err = MBTK_INFO_ERR_FORMAT;
+                        } else {
+                            pack_rsp_send(cli_info->fd, MBTK_INFO_ID_DEV_TIME_RSP, NULL, 0);
+                        }
+                    } else {
+                        char time_ptr[100] = {0};
+                        memcpy(time_ptr, pack->data + sizeof(uint8), pack->data_len - sizeof(uint8));
+                        if(req_time_set(*(pack->data), time_ptr, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                        {
+                            LOG("Set Time fail.");
+                            err = MBTK_INFO_ERR_FORMAT;
+                        } else {
+                            pack_rsp_send(cli_info->fd, MBTK_INFO_ID_DEV_TIME_RSP, NULL, 0);
+                        }
+                    }
+                }
+                break;
+            }
+            case MBTK_INFO_ID_NET_TIME_REQ: // <string>  YYYY-MM-DD-HH:MM:SS
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get Time
+                {
+                    char time[100];
+                    if(req_net_time_get(time, &cme_err) || strlen(time) == 0 || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get Time fail.");
+                    }
+                    else
+                    {
+                        char time_ser[100]={0};
+                        memcpy(time_ser,time,strlen(time));
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_TIME_RSP, time_ser, strlen(time_ser));
+                    }
+                }
+                else     // Set Time
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport set TIME.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_DEV_VOLTE_REQ:  // <uint8> 0:Close 1:Open
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+                {
+                    int state;
+                    if(req_volte_get(&state, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get VoLTE state fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_DEV_VOLTE_RSP, &state, sizeof(uint8));
+                    }
+                }
+                else     // Set VoLTE state.
+                {
+                    uint8 on = *(pack->data);
+                    if(pack->data_len != sizeof(uint8) || (on != 0 && on != 1))
+                    {
+                        err = MBTK_INFO_ERR_REQ_PARAMETER;
+                        LOG("Set VOLTE parameter error.");
+                        break;
+                    }
+
+                    if(req_volte_set(on, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Set VoLTE state fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_DEV_VOLTE_RSP, NULL, 0);
+
+                        // Restart is required to take effect.
+                        LOG("Will reboot system...");
+                    }
+                }
+                break;
+            }
+            case MBTK_INFO_ID_DEV_TEMP_REQ:  // <string> Temperature
+            {
+                if(pack->data_len == sizeof(uint8) && pack->data) {
+                    int temp;
+                    if(req_temp_get(*(pack->data), &temp, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get temperature fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_DEV_TEMP_RSP, &temp, sizeof(uint8));
+                    }
+                } else {
+                    err = MBTK_INFO_ERR_FORMAT;
+                    LOG("Unsupport get Temperature.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_SIM_PLMN_REQ: // plmn
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   //  plmn
+                {
+                    mbtk_plmn_info plmn;
+                    if(req_plmn_get(&plmn, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get PLMN fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SIM_PLMN_RSP, &plmn, sizeof(mbtk_plmn_info));
+                    }
+                }
+                else     // Set
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Set sim state fail.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_SIM_STATE_REQ: // mbtk_sim_state_enum
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get sim state.
+                {
+                    uint8 sim_state = (uint8)getSIMStatus();
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SIM_STATE_RSP, &sim_state, sizeof(uint8));
+                }
+                else     // Set
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Set sim state fail.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_SIM_STYPE_REQ: // mbtk_sim_card_type_enum
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get sim card type
+                {
+                    uint8 sim_card_type;
+                    if(req_sim_card_type_get(&sim_card_type, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get IMSI fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SIM_STYPE_RSP, &sim_card_type, sizeof(uint8));
+                    }
+                }
+                else     // Set
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Set sim state fail.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_SIM_PINPUK_TIMES_REQ: // mbtk_pin_puk_last_times
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get sim card type
+                {
+                    mbtk_pin_puk_last_times pin_puk_last_times;
+                    if(req_pin_puk_last_times_get(&pin_puk_last_times, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get IMSI fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SIM_PINPUK_TIMES_RSP, &pin_puk_last_times, sizeof(mbtk_pin_puk_last_times));
+                    }
+                }
+                else     // Set
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Set sim state fail.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_SIM_ENABLE_PIN_REQ:   // <string> PIN
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Enable PIN
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport GET PIN.");
+                }
+                else     // Enable PIN
+                {
+                    mbtk_enable_pin_info *pin = NULL;
+                    pin = (mbtk_enable_pin_info *)pack->data;
+                    if(req_pin_enable(pin, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get IMSI fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SIM_ENABLE_PIN_RSP, NULL, 0);
+                    }
+                }
+                break;
+            }
+            case MBTK_INFO_ID_SIM_PIN_REQ:   // <string> PIN
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // PIN
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport GET PIN.");
+                }
+                else     // Set PIN
+                {
+                    char pin[16] = {0};
+                    memcpy(pin, pack->data, pack->data_len);
+                    if(req_pin_verify(pin, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Set PIN fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SIM_PIN_RSP, NULL, 0);
+                    }
+                }
+                break;
+            }
+            case MBTK_INFO_ID_SIM_PUK_REQ:   // <string> PUK
+            {
+                if(pack->data_len == 0 || pack->data == NULL)
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport.");
+                }
+                else     // change PIN
+                {
+                    mbtk_unlock_pin_info *pin_info = NULL;
+                    pin_info = (mbtk_unlock_pin_info *)pack->data;
+                    if(req_puk_unlock_pin(pin_info, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get IMSI fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SIM_CHANGE_PIN_RSP, NULL, 0);
+                    }
+                }
+                break;
+            }
+            case MBTK_INFO_ID_SIM_CHANGE_PIN_REQ:   // <string> <string> old_PIN new_PIN
+            {
+                if(pack->data_len == 0 || pack->data == NULL)
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport.");
+                }
+                else     // change PIN
+                {
+                    mbtk_change_pin_info *pin_info = NULL;
+                    pin_info = (mbtk_change_pin_info *)pack->data;
+                    if(req_pin_change(pin_info, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get IMSI fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SIM_CHANGE_PIN_RSP, NULL, 0);
+                    }
+                }
+                break;
+            }
+            case MBTK_INFO_ID_SIM_IMSI_REQ:  // <string> IMSI
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get IMSI
+                {
+                    char imsi[20] = {0};
+                    if(req_imsi_get(imsi, &cme_err) || strlen(imsi) == 0 || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get IMSI fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SIM_IMSI_RSP, imsi, strlen(imsi));
+                    }
+                }
+                else     // Set IMSI(Unsupport).
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport set IMSI.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_SIM_ICCID_REQ: // <string> ICCID
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get ICCID
+                {
+                    //log_hex("pack", pack, sizeof(mbtk_info_pack_t));
+                    //sleep(1);
+                    char iccid[50] = {0};
+                    if(req_iccid_get(iccid, &cme_err) || strlen(iccid) == 0 || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get ICCID fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SIM_ICCID_RSP, iccid, strlen(iccid));
+                    }
+                }
+                else     // Set ICCID(Unsupport).
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport set ICCID.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_SIM_PN_REQ: // <string> Phone Number
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get Phone Number
+                {
+                    //log_hex("pack", pack, sizeof(mbtk_info_pack_t));
+                    //sleep(1);
+                    char phone_number[50] = {0};
+                    if(req_phone_number_get(phone_number, &cme_err) || strlen(phone_number) == 0 || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get Phone Number fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SIM_PN_RSP, phone_number, strlen(phone_number));
+                    }
+                }
+                else     // Set Phone Number(Unsupport).
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport set Phone Number.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_NET_SEL_MODE_REQ: // <mbtk_net_info_t> Operator
+            {
+                if(pack->data_len == 0 || pack->data == NULL) // Get
+                {
+                    mbtk_net_info_t info;
+                    memset(&info, 0, sizeof(mbtk_net_info_t));
+                    if(req_net_sel_mode_get(&info, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get Net select mode fail.");
+                    }
+                    else
+                    {
+                        LOG("NET : %d, %d, %d, %d", info.net_sel_mode, info.net_type, info.net_state, info.plmn);
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_SEL_MODE_RSP, &info, sizeof(mbtk_net_info_t));
+                    }
+                }
+                else     // Set
+                {
+                    //LOG("1 pack-%p,data-%p,data_len-%d", pack, pack->data, pack->data_len);
+                    //log_hex("pack", pack, sizeof(mbtk_info_pack_t));
+                    //log_hex("data", pack->data, pack->data_len);
+
+                    mbtk_net_info_t* info = (mbtk_net_info_t*)pack->data;//(mbtk_net_info_t*)mbtk_info_pack_data_get(pack, NULL);
+                    if(info == NULL) {
+                        err = MBTK_INFO_ERR_FORMAT;
+                        LOG("Get Net select mode fail.");
+                    } else {
+                        LOG("NET : %d, %d, %d", info->net_sel_mode, info->net_type, info->plmn);
+                        if(req_net_sel_mode_set(info, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON) {
+                            if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                                err = MBTK_INFO_ERR_CME + cme_err;
+                            } else {
+                                err = MBTK_INFO_ERR_UNKNOWN;
+                            }
+                            LOG("Get Net select mode fail.");
+                        } else {
+                            pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_SEL_MODE_RSP, NULL, 0);
+                        }
+                    }
+                }
+                break;
+            }
+            case MBTK_INFO_ID_NET_AVAILABLE_REQ:// sel_mode(uint8)type(uint8)plmn(uint32)...sel_mode(uint8)type(uint8)plmn(uint32)
+            {
+                if(pack->data_len == 0 || pack->data == NULL) // Get Available Net.
+                {
+                    int buffer_size;
+                    uint8 buffer[SOCK_MSG_LEN_MAX];
+                    memset(buffer, 0, SOCK_MSG_LEN_MAX);
+                    if((buffer_size = req_available_net_get(buffer, &cme_err)) <= 0 || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get Available Net fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_AVAILABLE_RSP, buffer, buffer_size);
+                    }
+                }
+                else     // Set Available Net(Unsupport).
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Unsupport set available net.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_NET_BAND_REQ:
+            {
+                if(pack->data_len == 0 || pack->data == NULL)
+                {
+                    err = MBTK_INFO_ERR_REQ_PARAMETER;
+                    LOG("No data found.");
+                }
+                else     // Get support/current bands.
+                {
+                    if(pack->data_len == sizeof(uint8)) {
+                        if(*(pack->data)) { // Get current bands.
+                            mbtk_band_info_t band;
+                            if(req_band_get(&band, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                            {
+                                if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                                    err = MBTK_INFO_ERR_CME + cme_err;
+                                } else {
+                                    err = MBTK_INFO_ERR_UNKNOWN;
+                                }
+                                LOG("Get net band fail.");
+                            }
+                            else
+                            {
+                                pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_BAND_RSP, &band, sizeof(mbtk_band_info_t));
+                            }
+                        } else { // Get support bands.
+                            band_support_get();
+                            if(band_support.net_pref != 0)
+                            {
+                                err = MBTK_INFO_ERR_UNKNOWN;
+                                LOG("Get support bands fail.");
+                            }
+                            else
+                            {
+                                pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_BAND_RSP, &band_support, sizeof(mbtk_band_info_t));
+                            }
+                        }
+                    } else { // Set current bands.
+                        mbtk_band_info_t* band = (mbtk_band_info_t*)pack->data;
+                        if(pack->data_len != sizeof(mbtk_band_info_t))
+                        {
+                            err = MBTK_INFO_ERR_REQ_PARAMETER;
+                            LOG("Set net band error.");
+                            break;
+                        }
+
+                        if(req_band_set(band, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                        {
+                            if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                                err = MBTK_INFO_ERR_CME + cme_err;
+                            } else {
+                                err = MBTK_INFO_ERR_UNKNOWN;
+                            }
+                            LOG("Set net band fail.");
+                        }
+                        else
+                        {
+                            pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_BAND_RSP, NULL, 0);
+                        }
+                    }
+                }
+                break;
+            }
+            case MBTK_INFO_ID_NET_CELL_REQ: // mbtk_cell_info_t[]
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get net cell.
+                {
+                    if(req_cell_info_get(&cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get net cell fail.");
+                    }
+                    else
+                    {
+                        LOG("req_cell_info_get() success,cell number: %d", cell_info.cell_num);
+                        //sleep(1);
+                        // mbtK_cell_pack_info_t
+                        if(cell_info.cell_num > 0 && cell_info.cell_num <= CELL_NUM_MAX && cell_info.type >= 0 && cell_info.type <= 2) {
+                            uint8 *data = (uint8*)malloc(sizeof(uint8) + sizeof(mbtk_cell_info_t) * cell_info.cell_num);
+                            if(data == NULL){
+                                err = MBTK_INFO_ERR_MEMORY;
+                                LOG("Get net cell fail.");
+                            } else {
+                                *data = cell_info.type; // Set network type.
+                                // Copy cell info item.
+                                #if 0
+                                int i = 0;
+                                while(i < cell_info.cell_num) {
+                                    memcpy(data + sizeof(uint8) + sizeof(mbtk_cell_info_t) * i,
+                                        &(cell_info.cell[i]),
+                                        sizeof(mbtk_cell_info_t));
+                                    i++;
+                                }
+                                #else
+                                memcpy(data + sizeof(uint8),
+                                        &(cell_info.cell),
+                                        sizeof(mbtk_cell_info_t) * cell_info.cell_num);
+                                #endif
+                                pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_CELL_RSP, data, sizeof(uint8) + sizeof(mbtk_cell_info_t) * cell_info.cell_num);
+                                free(data);
+                            }
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                            LOG("Get net cell fail.");
+                        }
+                    }
+                }
+                else     // Lock cell
+                {
+	                char *mem = (char*)(pack->data);
+					int len = pack->data_len;
+	                char reg[100] = {0};
+	                printf("mem:%s, len:%d", pack->data, pack->data_len);
+
+	                if(req_cell_info_set(mem, reg, len, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+	                {
+	                //    printf("cpms_set fail\n");
+	                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+	                        err = MBTK_INFO_ERR_CME + cme_err;
+	                    } else {
+	                        err = MBTK_INFO_ERR_UNKNOWN;
+	                    }
+	                //    LOG("Set req_cell_info_set fail.");
+	                }
+	                else
+	                {
+
+	                    printf("req_cell_info_set success, reg:%s\n", reg);
+	                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_CELL_RSP, reg, strlen(reg));
+
+	                    // Restart is required to take effect.
+	                    LOG("Will reboot system...");
+	                }
+                }
+                break;
+            }
+            case MBTK_INFO_ID_NET_RADIO_REQ: // <uint8> 0:OFF 1:ON
+            {
+                if(pack->data_len == 0 || pack->data == NULL) // Get
+                {
+                    uint8 radio_on = (uint8)isRadioOn();
+                    if(radio_on < 0)
+                    {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                        LOG("Get radio state fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_RADIO_RSP, &radio_on, sizeof(uint8));
+                    }
+                }
+                else     // Set
+                {
+                    uint8 radio_on = *(pack->data);
+                    if(radio_on != 0 && radio_on != 1)
+                    {
+                        err = MBTK_INFO_ERR_REQ_PARAMETER;
+                        LOG("Set radio state fail.");
+                    }
+                    else
+                    {
+                        setRadioPower(radio_on);
+                        if((radio_on && net_info.radio_state == MBTK_RADIO_STATE_ON)
+                            || (!radio_on && net_info.radio_state == MBTK_RADIO_STATE_OFF)) {
+                            pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_RADIO_RSP, NULL, 0);
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                            LOG("Set radio state fail.");
+                        }
+                    }
+                }
+                break;
+            }
+            case MBTK_INFO_ID_NET_SIGNAL_REQ:  // mbtk_signal_info_t
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get net signal.
+                {
+                    mbtk_signal_info_t signal;
+                    memset(&signal, 0, sizeof(mbtk_signal_info_t));
+                    if(req_net_signal_get(&signal, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get net signal fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_SIGNAL_RSP, &signal, sizeof(mbtk_signal_info_t));
+                    }
+                }
+                else     // Set
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Set net signal fail.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_NET_REG_REQ:  // mbtk_net_reg_info_t
+            {
+                if(pack->data_len == 0 || pack->data == NULL)   // Get net reg.
+                {
+                    mbtk_net_reg_info_t reg;
+                    memset(&reg, 0, sizeof(mbtk_net_reg_info_t));
+                    if(req_net_reg_get(&reg, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get net reg fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_REG_RSP, &reg, sizeof(mbtk_net_reg_info_t));
+                    }
+                }
+                else     // Set
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                    LOG("Set net reg fail.");
+                }
+                break;
+            }
+            case MBTK_INFO_ID_NET_APN_REQ:   // mbtk_apn_info_t
+            {
+                if(pack->data_len == 0 || pack->data == NULL) // Get APN
+                {
+                    uint8 buff[SOCK_MSG_LEN_MAX];
+                    memset(buff, 0, SOCK_MSG_LEN_MAX);
+                    int data_len = 0;
+                    if(req_apn_get(buff, &data_len, &cme_err) || data_len <= 0 || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Get APN fail.");
+                    }
+                    else
+                    {
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_APN_RSP, buff, data_len);
+                    }
+                }
+                else     // Set
+                {
+                    // <cid[1]><ip_type[1]><apn_len[2]><apn><user_len[2]><user><pass_len[2]><pass><auth_len[2]><auth>
+                    const uint8* ptr = pack->data;
+                    mbtk_apn_info_t apn;
+                    int len;
+                    memset(&apn, 0, sizeof(mbtk_apn_info_t));
+                    // cid
+                    apn.cid = *ptr++;
+
+                    // ip_type
+                    apn.ip_type = (mbtk_ip_type_enum)(*ptr++);
+
+                    // apn
+                    len = byte_2_uint16(ptr, false);
+                    ptr += sizeof(uint16);
+                    if(len > 0) {
+                        memcpy(apn.apn, ptr, len);
+                        ptr += len;
+                    }
+
+                    // user
+                    len = byte_2_uint16(ptr, false);
+                    ptr += sizeof(uint16);
+                    if(len > 0) {
+                        memcpy(apn.user, ptr, len);
+                        ptr += len;
+                    }
+
+                    // pass
+                    len = byte_2_uint16(ptr, false);
+                    ptr += sizeof(uint16);
+                    if(len > 0) {
+                        memcpy(apn.pass, ptr, len);
+                        ptr += len;
+                    }
+
+                    // auth
+                    len = byte_2_uint16(ptr, false);
+                    ptr += sizeof(uint16);
+                    if(len > 0) {
+                        memcpy(apn.auth, ptr, len);
+                        ptr += len;
+                    }
+
+                    LOGD("APN : %d, %d, %s, %s, %s, %s", apn.cid, apn.ip_type, str_empty(apn.apn) ? "NULL" : apn.apn,
+                        str_empty(apn.user) ? "NULL" : apn.user, str_empty(apn.pass) ? "NULL" : apn.pass, str_empty(apn.auth) ? "NULL" : apn.auth);
+                    if(req_apn_set(&apn, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                            err = MBTK_INFO_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_INFO_ERR_UNKNOWN;
+                        }
+                        LOG("Set APN fail.");
+                    }
+                    else
+                    {
+                        // Save apn.
+                        apn_prop_set(&apn);
+
+                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_APN_RSP, NULL, 0);
+                    }
+                }
+                break;
+            }
+            case MBTK_INFO_ID_NET_DATA_CALL_REQ:
+            {
+                if(pack->data_len == 0 || pack->data == NULL)
+                {
+                    err = MBTK_INFO_ERR_UNSUPPORTED;
+                }
+                else
+                {
+                    /* <call_type[1]><cid[1]><auto_conn_interval[1]><boot_conn[1]><timeout[1]>
+                     call_type : mbtk_data_call_type_enum
+                     cid : 2 - 7
+                     timeout : second
+                    */
+                    mbtk_data_call_type_enum call_type = (mbtk_data_call_type_enum)pack->data[0];
+                    int cid = pack->data[1];
+                    int reconn = 0;
+
+                    if(cid < MBTK_APN_CID_MIN || cid > MBTK_APN_CID_MAX) {
+                        err = MBTK_INFO_ERR_CID;
+                        break;
+                    }
+
+                    LOG("cid_active[%d] = %d", cid, cid_active[cid]);
+                    memset(&cgact_wait, 0, sizeof(info_cgact_wait_t));
+                    switch(call_type) {
+                        case MBTK_DATA_CALL_START: {
+                            //mbtk wyq for data_call_ex add start
+                            int auto_conn_interval = pack->data[2];
+                            int boot_conn = pack->data[3];
+                            int timeout = pack->data[4];
+                            data_call_bootconn_save(cid, boot_conn);
+                            
+                            if(net_info.net_type != MBTK_RADIO_TECH_E_UTRAN)
+                            {
+                                err = MBTK_INFO_ERR_NET_NO_INIT;
+                                break;
+                            }
+                            
+                            if(cid_active[cid] == 1)
+                            {
+                                err = MBTK_INFO_ERR_CID_EXIST;
+                                break;
+                            }
+                            
+                            data_call_reconn:
+                            //mbtk wyq for data_call_ex add end
+                            cgact_wait.waitting = true;
+                            cgact_wait.cid = cid;
+                            cgact_wait.act = true;
+                            if(req_data_call_start(cid, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                            {
+                                //mbtk wyq for data_call_ex add start
+                                if(reconn < 5 && auto_conn_interval > 0)
+                                {
+                                    sleep(auto_conn_interval);
+                                    reconn++;
+                                    cme_err = MBTK_INFO_ERR_CME_NON;
+                                    LOG("data_call restart call.");
+                                    goto data_call_reconn;
+                                }
+                                //mbtk wyq for data_call_ex add end
+                                if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                                    err = MBTK_INFO_ERR_CME + cme_err;
+                                } else {
+                                    err = MBTK_INFO_ERR_UNKNOWN;
+                                }
+                                LOG("%d active fail.", cid);
+                            }
+                            else
+                            {
+                                // Wait for "CONNECT" or "+CGEV:"
+                                if(wait_cgact_complete(timeout)) { // Timeout
+                                    err = MBTK_INFO_ERR_TIMEOUT;
+                                    break;
+                                }
+
+                                // Get IP information.
+                                mbtk_ipv4_info_t ipv4;
+                                mbtk_ipv6_info_t ipv6;
+                                memset(&ipv4, 0, sizeof(mbtk_ipv4_info_t));
+                                memset(&ipv6, 0, sizeof(mbtk_ipv6_info_t));
+                                if(req_data_call_state_get(cid, &ipv4, &ipv6, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                                {
+                                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                                        err = MBTK_INFO_ERR_CME + cme_err;
+                                    } else {
+                                        err = MBTK_INFO_ERR_UNKNOWN;
+                                    }
+                                    LOG("Get %d state fail.", cid);
+                                }
+                                else
+                                {
+                                    // Config IPv4 address.
+#if 1
+                                    if(ipv4.valid) {
+                                        char dev[20] = {0};
+                                        sprintf(dev, "ccinet%d", cid - 1);
+
+                                        char ip[20] = {0};
+                                        char gateway[20] = {0};
+                                        char *gateway_ptr = NULL;
+                                        char netmask[20] = {0};
+                                        char *netmask_ptr = NULL;
+                                        if(inet_ntop(AF_INET, &(ipv4.IPAddr), ip, 20) == NULL) {
+                                            err = MBTK_INFO_ERR_UNKNOWN;
+                                            LOGE("inet_ntop ipv4 ip fail.");
+                                            log_hex("IPv4", &(ipv4.IPAddr), 4);
+                                            break;
+                                        }
+
+                                        if(ipv4.GateWay) {
+                                            if(inet_ntop(AF_INET, &(ipv4.GateWay), gateway, 20) == NULL) {
+                                                err = MBTK_INFO_ERR_UNKNOWN;
+                                                LOGE("inet_ntop ipv4 gateway fail.");
+                                                log_hex("IPv4", &(ipv4.IPAddr), 4);
+                                                break;
+                                            } else {
+                                                gateway_ptr = gateway;
+                                            }
+                                        }
+
+                                        if(ipv4.NetMask) {
+                                            if(inet_ntop(AF_INET, &(ipv4.NetMask), netmask, 20) == NULL) {
+                                                err = MBTK_INFO_ERR_UNKNOWN;
+                                                LOGE("inet_ntop ipv4 netmask fail.");
+                                                log_hex("IPv4", &(ipv4.IPAddr), 4);
+                                                break;
+                                            } else {
+                                                netmask_ptr = netmask;
+                                            }
+                                        }
+
+                                        if(netmask_ptr == NULL) {
+                                            netmask_ptr = netmask;
+                                            memcpy(netmask_ptr, "255.255.255.0", strlen("255.255.255.0"));
+                                        }
+
+                                        if(mbtk_ifc_configure2(dev, ip, 0, gateway_ptr, netmask_ptr)) {
+                                            LOGD("Config %s IPv4 %s fail.", dev, ip);
+                                        } else {
+                                            LOGD("Config %s IPv4 %s success.", dev, ip);
+                                        }
+
+                                    }
+#endif
+                                    // Config IPv6 address.
+                                    if(ipv6.valid) {
+                                        char ip[50] = {0};
+                                        char dev[20] = {0};
+                                        sprintf(dev, "ccinet%d", cid - 1);
+
+                                        if(inet_ntop(AF_INET6, &(ipv6.IPV6Addr), ip, 50) == NULL) {
+                                            err = MBTK_INFO_ERR_UNKNOWN;
+                                            LOGE("inet_ntop ipv6 ip fail.");
+                                            log_hex("IPv6", &(ipv6.IPV6Addr), 16);
+                                            break;
+                                        }
+
+                                        if(mbtk_ipv6_config(dev, ip, 64)) {
+                                            LOGD("Config %s IPv6 %s fail.", dev, ip);
+                                        } else {
+                                            LOGD("Config %s IPv6 %s success.", dev, ip);
+                                        }
+                                    }
+
+                                    cid_active[cid] = 1;
+                                    if(cli_info->fd != DATA_CALL_BOOTCONN_FD)
+                                    {
+                                        pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_DATA_CALL_RSP, NULL, 0);
+                                    }
+                                    else
+                                    {
+                                        free(pack->data);
+                                        free(cli_info);
+                                        LOG("data_call bootconn success.");
+                                    }
+                                }
+                            }
+                            break;
+                        }
+                        case MBTK_DATA_CALL_STOP: {
+                            //mbtk wyq for data_call_ex add start
+                            if(cid_active[cid] == 0)
+                            {
+                                err = MBTK_INFO_ERR_CID_NO_EXIST;
+                                break;
+                            }
+
+                            int timeout = pack->data[2];
+                            //mbtk wyq for data_call_ex add end
+                            
+                            cgact_wait.waitting = true;
+                            cgact_wait.cid = cid;
+                            cgact_wait.act = false;
+                            if(req_data_call_stop(cid, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                            {
+                                if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                                    err = MBTK_INFO_ERR_CME + cme_err;
+                                } else {
+                                    err = MBTK_INFO_ERR_UNKNOWN;
+                                }
+                                LOG("%d deactive fail.", cid);
+                            }
+                            else
+                            {
+                                // Wait for "CONNECT" or "+CGEV:"
+                                if(wait_cgact_complete(timeout)) { // Timeout
+                                    err = MBTK_INFO_ERR_TIMEOUT;
+                                    break;
+                                }
+                                char dev[20] = {0};
+                                sprintf(dev, "ccinet%d", cid - 1);
+
+                                // Config network.
+                                if(mbtk_ifc_configure2(dev, NULL, 0, NULL, NULL)) {
+                                    LOGD("Config %s IPv4 0 fail.", dev);
+                                } else {
+                                    LOGD("Config %s IPv4 0 success.", dev);
+                                }
+
+#if 0
+                                if(mbtk_ipv6_config(dev, NULL, 64)) {
+                                    LOGD("Config %s IPv6 0 fail.", dev);
+                                } else {
+                                    LOGD("Config %s IPv6 0 success.", dev);
+                                }
+#endif
+                                cid_active[cid] = 0;
+                                pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_DATA_CALL_RSP, NULL, 0);
+                            }
+                            break;
+                        }
+                        case MBTK_DATA_CALL_STATE: {
+                            mbtk_ipv4_info_t ipv4;
+                            mbtk_ipv6_info_t ipv6;
+                            memset(&ipv4, 0, sizeof(mbtk_ipv4_info_t));
+                            memset(&ipv6, 0, sizeof(mbtk_ipv6_info_t));
+                            if(req_data_call_state_get(cid, &ipv4, &ipv6, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                            {
+                                if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                                    err = MBTK_INFO_ERR_CME + cme_err;
+                                } else {
+                                    err = MBTK_INFO_ERR_UNKNOWN;
+                                }
+                                LOG("Get %d state fail.", cid);
+                            }
+                            else
+                            {
+                                uint8 buff[SOCK_MSG_LEN_MAX] = {0};
+                                int buff_len = 0;
+                                if(ipv4.valid && ipv6.valid) {
+                                    buff[0] = (uint8)2;
+                                    buff_len++;
+
+                                    memcpy(buff + buff_len, &ipv4, sizeof(mbtk_ipv4_info_t));
+                                    buff_len += sizeof(mbtk_ipv4_info_t);
+                                    memcpy(buff + buff_len, &ipv6, sizeof(mbtk_ipv6_info_t));
+                                    buff_len += sizeof(mbtk_ipv6_info_t);
+                                } else if(ipv4.valid) {
+                                    buff[0] = (uint8)0;
+                                    buff_len++;
+
+                                    memcpy(buff + buff_len, &ipv4, sizeof(mbtk_ipv4_info_t));
+                                    buff_len += sizeof(mbtk_ipv4_info_t);
+                                } else if(ipv6.valid) {
+                                    buff[0] = (uint8)1;
+                                    buff_len++;
+
+                                    memcpy(buff + buff_len, &ipv6, sizeof(mbtk_ipv6_info_t));
+                                    buff_len += sizeof(mbtk_ipv6_info_t);
+                                } else {
+                                    LOGE("Get IPv4/IPv6 fail.");
+                                    err = MBTK_INFO_ERR_UNKNOWN;
+                                    break;
+                                }
+                                pack_rsp_send(cli_info->fd, MBTK_INFO_ID_NET_DATA_CALL_RSP, buff, buff_len);
+                            }
+                            break;
+                        }
+                        default: {
+                            err = MBTK_INFO_ERR_FORMAT;
+                            break;
+                        }
+                    }
+                }
+                break;
+            }
+            default:
+            {
+                err = MBTK_INFO_ERR_REQ_UNKNOWN;
+                LOG("Unknown request : %s", id2str(pack->info_id));
+                break;
+            }
+        }
+
+        return err;
+    }
+}
+
+// Process AT URC data
+static int send_pack_to_queue(sock_client_info_t* cli_info, void* pack)
+{
+    if(info_queue.count >= PACK_PROCESS_QUEUE_MAX)
+    {
+        LOG("Packet process queue is full");
+        return -1;
+    }
+
+    info_queue_item_t *item = (info_queue_item_t*)malloc(sizeof(info_queue_item_t));
+    if(!item)
+    {
+        LOG("malloc() fail[%d].", errno);
+        return -1;
+    }
+    item->cli_info = cli_info;
+    item->pack = pack;
+    mbtk_queue_put(&info_queue, item);
+
+    // If thread is waitting,continue it.
+    if(1/*!is_running*/)
+    {
+        pthread_mutex_lock(&info_mutex);
+        pthread_cond_signal(&info_cond);
+        pthread_mutex_unlock(&info_mutex);
+    }
+    else
+    {
+        LOG("Packet process thread is process...");
+    }
+
+    return 0;
+}
+
+static void radio_state_change(void *data, int data_len)
+{
+    uint8 *data_ptr = (uint8*)data;
+    if(data_ptr[0]) {
+        net_info.radio_state = MBTK_RADIO_STATE_ON;
+    } else {
+        net_info.radio_state = MBTK_RADIO_STATE_OFF;
+    }
+
+    sock_client_info_t *cli = NULL;
+    list_first(sock_client_list);
+    while ((cli = (sock_client_info_t*) list_next(sock_client_list)))
+    {
+        if(cli->ind_num > 0) {
+            int i;
+            for(i = 0; i < IND_REGISTER_MAX; i++) {
+                // Registe MBTK_INFO_ID_IND_RADIO_STATE_CHANGE
+                if(cli->ind_register[i] == MBTK_INFO_ID_IND_RADIO_STATE_CHANGE) {
+                    pack_rsp_send(cli->fd , MBTK_INFO_ID_IND_RADIO_STATE_CHANGE, data, data_len);
+                    break;
+                }
+            }
+        }
+    }
+}
+
+static void pdp_state_change(void *data, int data_len)
+{
+    sock_client_info_t *cli = NULL;
+    list_first(sock_client_list);
+    while ((cli = (sock_client_info_t*) list_next(sock_client_list)))
+    {
+        if(cli->ind_num > 0) {
+            int i;
+            for(i = 0; i < IND_REGISTER_MAX; i++) {
+                if(cli->ind_register[i] == MBTK_INFO_ID_IND_PDP_STATE_CHANGE) {
+                    pack_rsp_send(cli->fd , MBTK_INFO_ID_IND_PDP_STATE_CHANGE, data, data_len);
+                    break;
+                }
+            }
+        }
+    }
+}
+
+static void net_state_change(void *data, int data_len)
+{
+    sock_client_info_t *cli = NULL;
+    list_first(sock_client_list);
+    while ((cli = (sock_client_info_t*) list_next(sock_client_list)))
+    {
+        if(cli->ind_num > 0) {
+            int i;
+            for(i = 0; i < IND_REGISTER_MAX; i++) {
+                // Registe MBTK_INFO_ID_IND_NET_STATE_CHANGE
+                if(cli->ind_register[i] == MBTK_INFO_ID_IND_NET_STATE_CHANGE) {
+                    pack_rsp_send(cli->fd , MBTK_INFO_ID_IND_NET_STATE_CHANGE, data, data_len);
+                    break;
+                }
+            }
+        }
+    }
+}
+
+static void call_state_change(void *data, int data_len)
+{
+    sock_client_info_t *cli = NULL;
+    list_first(sock_client_list);
+    while ((cli = (sock_client_info_t*) list_next(sock_client_list)))
+    {
+        if(cli->ind_num > 0) {
+            int i;
+            for(i = 0; i < IND_REGISTER_MAX; i++) {
+                // Registed MBTK_INFO_ID_IND_RADIO_STATE_CHANGE
+                if(cli->ind_register[i] == MBTK_INFO_ID_IND_CALL_STATE_CHANGE) {
+                    pack_rsp_send(cli->fd , MBTK_INFO_ID_IND_CALL_STATE_CHANGE, data, data_len);
+                    break;
+                }
+            }
+        }
+    }
+}
+
+static void sim_state_change(void *data, int data_len)
+{
+    sock_client_info_t *cli = NULL;
+    list_first(sock_client_list);
+    while ((cli = (sock_client_info_t*) list_next(sock_client_list)))
+    {
+        if(cli->ind_num > 0) {
+            int i;
+            for(i = 0; i < IND_REGISTER_MAX; i++) {
+                // Registed MBTK_INFO_ID_IND_RADIO_STATE_CHANGE
+                if(cli->ind_register[i] == MBTK_INFO_ID_IND_SIM_STATE_CHANGE) {
+                    pack_rsp_send(cli->fd , MBTK_INFO_ID_IND_SIM_STATE_CHANGE, data, data_len);
+                    break;
+                }
+            }
+        }
+    }
+}
+
+static void sms_state_change(void *data, int data_len)
+{
+    sock_client_info_t *cli = NULL;
+    list_first(sock_client_list);
+    while ((cli = (sock_client_info_t*) list_next(sock_client_list)))
+    {
+        if(cli->ind_num > 0) {
+            int i;
+            for(i = 0; i < IND_REGISTER_MAX; i++) {
+                // Registed MBTK_INFO_ID_IND_SMS_STATE_CHANGE
+                if(cli->ind_register[i] == MBTK_INFO_ID_IND_SMS_STATE_CHANGE) {
+                    pack_rsp_send(cli->fd , MBTK_INFO_ID_IND_SMS_STATE_CHANGE, data, data_len);
+                    break;
+                }
+            }
+        }
+    }
+}
+
+int urc_msg_distribute(bool async_process, info_urc_msg_id_enum msg, void *data, int data_len)
+{
+#if 0
+    if(urc_queue.count >= PACK_PROCESS_QUEUE_MAX)
+    {
+        LOG("Packet process queue is full");
+        return -1;
+    }
+
+    info_urc_msg_t *urc = (info_urc_msg_t*)malloc(sizeof(info_urc_msg_t));
+    if(!urc)
+    {
+        LOG("malloc() fail[%d].", errno);
+        return -1;
+    }
+    urc->msg = msg;
+    urc->data = memdup(data, data_len);
+    urc->data_len = data_len;
+
+    mbtk_queue_put(&urc_queue, urc);
+
+    // If thread is waitting,continue it.
+    if(1/*!is_running*/)
+    {
+        pthread_mutex_lock(&urc_mutex);
+        pthread_cond_signal(&urc_cond);
+        pthread_mutex_unlock(&urc_mutex);
+    }
+    else
+    {
+        LOG("Packet process thread is process...");
+    }
+
+    return 0;
+#else
+    if(async_process) {
+        info_urc_msg_t *urc = (info_urc_msg_t*)malloc(sizeof(info_urc_msg_t));
+        if(!urc)
+        {
+            LOG("malloc() fail[%d].", errno);
+            return -1;
+        }
+        urc->msg = msg;
+        if(data && data_len > 0) {
+            urc->data = memdup(data, data_len);
+            urc->data_len = data_len;
+        } else {
+            urc->data = NULL;
+            urc->data_len = 0;
+        }
+        return send_pack_to_queue(NULL, urc);
+    } else {
+        switch(msg) {
+            case INFO_URC_MSG_NET_CS_REG_STATE:
+            {
+                net_state_change(data, data_len);
+                break;
+            }
+            case INFO_URC_MSG_CALL_STATE:
+            {
+                call_state_change(data, data_len);
+                break;
+            }
+            case INFO_URC_MSG_SMS_STATE:
+            {
+                sms_state_change(data, data_len);
+                break;
+            }
+            case INFO_URC_MSG_SIM_STATE:
+            {
+                sim_state_change(data, data_len);
+                break;
+            }
+            case INFO_URC_MSG_PDP_STATE:
+            {
+                pdp_state_change(data, data_len);
+                break;
+            }
+            default: {
+                LOGE("Unknown msg : %d", msg);
+                break;
+            }
+        }
+
+        return 0;
+    }
+#endif
+}
+
+
+static void ind_regisger(sock_client_info_t* cli_info, uint16 ind)
+{
+    uint32 i = 0;
+    while(i < cli_info->ind_num)
+    {
+        if(cli_info->ind_register[i] == ind)
+            break;
+        i++;
+    }
+
+    if(i == cli_info->ind_num)   // No found IND
+    {
+        cli_info->ind_register[i] = ind;
+        cli_info->ind_num++;
+        LOG("Register IND : %s", id2str(ind));
+    }
+    else
+    {
+        LOG("IND had exist.");
+    }
+}
+
+static void pack_distribute(sock_client_info_t* cli_info, mbtk_info_pack_t* pack)
+{
+    // Register IND Message.
+    if(mbtk_info_type_get(pack->info_id) == MBTK_INFO_TYPE_IND)
+    {
+        mbtk_info_err_enum err = MBTK_INFO_ERR_SUCCESS;
+        if(cli_info->ind_num >= IND_REGISTER_MAX)
+        {
+            LOG("IND if full.");
+            err = MBTK_INFO_ERR_IND_FULL;
+        }
+        else
+        {
+            ind_regisger(cli_info, pack->info_id);
+        }
+
+        pack_error_send(cli_info->fd, pack->info_id, err);
+
+        mbtk_info_pack_free(&pack);
+    }
+    else     // Request Information.
+    {
+        LOG("Start process REQ(%s), Length : %d", id2str(pack->info_id), pack->data_len);
+        if(0 && pack->data_len > 0)
+        {
+            log_hex("DATA", pack->data, pack->data_len);
+        }
+
+        // Send to REQ_process_thread process.
+        send_pack_to_queue(cli_info, pack);
+
+        // For test.
+        // pack_error_send(cli_info->fd, pack->info_id + 1, MBTK_INFO_ERR_SUCCESS);
+    }
+}
+
+static sock_client_info_t* cli_find(int fd)
+{
+    sock_client_info_t *result = NULL;
+    list_first(sock_client_list);
+    while ((result = (sock_client_info_t*) list_next(sock_client_list)))
+    {
+        if (result->fd == fd)
+            return result;
+    }
+
+    return NULL;
+}
+
+//mbtk wyq for server_ready_status add start
+void server_ready_set(void)
+{
+    server_ready_status = 1;
+}
+
+char server_ready_get(void)
+{
+    return server_ready_status;
+}
+
+static void server_state_send(void)
+{
+    sock_client_info_t *cli = NULL;
+    list_first(sock_client_list);
+    while ((cli = (sock_client_info_t*) list_next(sock_client_list)))
+    {
+        if(cli->ind_num > 0) {
+            if(cli->ind_register[0] == MBTK_INFO_ID_IND_SERVER_STATE_CHANGE) {
+                cli->ind_num = 0;
+                cli->ind_register[0] = 0;
+                pack_rsp_send(cli->fd , MBTK_INFO_ID_IND_SERVER_STATE_CHANGE, "1", 1);
+                break;
+            }
+        }
+        else
+        {
+            break;
+        }
+    }
+    LOG("handshake message send ok.");
+}
+
+//mbtk wyq for server_ready_status add end
+
+//mbtk wyq for data_call_ex add start
+//Save the cid that "DATA_CALL" needs to be automatically connected after startup
+void data_call_bootconn_save(int cid, int bootconn)
+{
+    if(cid_bootconn[cid] == bootconn + '0')
+    {
+        return;
+    }
+    cid_bootconn[cid] = bootconn + '0';
+
+    LOG("data_call_bootconn_set cid_bootconn = %s", cid_bootconn);
+    property_set("persist.mbtk.datacall.bootconn", cid_bootconn);
+}
+
+static void* data_call_bootconn_pthread(void *arg)
+{
+    UNUSED(arg);
+    LOG("data_call_bootconn_pthread enter.");
+    int i = 0;
+    int send_sum = 0;
+    int bootconn = 0;
+    
+    while(1)
+    {
+        if(server_ready_get() && send_sum == 0)
+        {
+            server_state_send();
+            send_sum = 1;
+        }
+        
+        if(net_info.sim_state == MBTK_SIM_READY && net_info.net_type == MBTK_RADIO_TECH_E_UTRAN && bootconn == 0)
+        {
+            //data_call_bootconn_exec();
+            property_get("persist.mbtk.datacall.bootconn", cid_bootconn, "00000000");
+            LOG("data_call_bootconn_exec cid_bootconn = %s", cid_bootconn);
+            
+            for(i = MBTK_APN_CID_MIN; i < MBTK_APN_CID_MAX + 1; i++)
+            {
+                if(cid_bootconn[i] == '1')
+                {
+                        sock_client_info_t *info = (sock_client_info_t*)malloc(sizeof(sock_client_info_t));
+                        if(info == NULL)
+                        {
+                            LOG("clinent_info  malloc() fail.");
+                            continue;
+                        }
+                        memset(info, 0, sizeof(sock_client_info_t));
+                        info->fd = DATA_CALL_BOOTCONN_FD;
+                        
+                        mbtk_info_pack_t* pack = mbtk_info_pack_creat(MBTK_INFO_ID_NET_DATA_CALL_REQ);
+                        if(pack == NULL)
+                        {
+                            free(info);
+                            LOG("Packet malloc() fail.");
+                            continue;
+                        }
+
+                        // "info_err"
+                        //pack->info_err = byte_2_uint16(ptr, false)
+
+                        // "data_len"
+                        pack->data_len = 5;
+
+                        char *p = (char *)malloc(5);
+                        p[0] = MBTK_DATA_CALL_START;
+                        p[1] = i;
+                        p[2] = 0;
+                        p[3] = 1;
+                        p[4] = 10;
+                        pack->data = p;
+                        send_pack_to_queue(info, pack);
+                }
+            }
+
+            bootconn = 1;
+        }
+
+        if(bootconn == 1 && send_sum == 1)
+        {
+            break;
+        }
+        else
+        {
+            sleep(1);
+        }
+    }
+
+    LOG("data_call_bootconn_pthread exit.");
+    return NULL;
+}
+
+//mbtk wyq for data_call_ex add end
+
+static void* info_main_pthread(void* arg)
+{
+    UNUSED(arg);
+    epoll_fd = epoll_create(SOCK_CLIENT_MAX + 1);
+    if(epoll_fd < 0)
+    {
+        LOG("epoll_create() fail[%d].", errno);
+        return NULL;
+    }
+
+    uint32 event = EPOLLIN | EPOLLET;
+    struct epoll_event ev;
+    ev.data.fd = sock_listen_fd;
+    ev.events = event; //EPOLLIN | EPOLLERR | EPOLLET;
+    epoll_ctl(epoll_fd,EPOLL_CTL_ADD,sock_listen_fd,&ev);
+
+    int nready = -1;
+    struct epoll_event epoll_events[EPOLL_LISTEN_MAX];
+    while(1)
+    {
+        nready = epoll_wait(epoll_fd, epoll_events, EPOLL_LISTEN_MAX, -1);
+        if(nready > 0)
+        {
+            sock_client_info_t *cli_info = NULL;
+            int i;
+            for(i = 0; i < nready; i++)
+            {
+                LOG("fd[%d] event = %x",epoll_events[i].data.fd, epoll_events[i].events);
+                if(epoll_events[i].events & EPOLLHUP)   // Client Close.
+                {
+                    if((cli_info = cli_find(epoll_events[i].data.fd)) != NULL)
+                    {
+                        cli_close(cli_info);
+                    }
+                    else
+                    {
+                        LOG("Unknown client[fd = %d].", epoll_events[i].data.fd);
+                    }
+                }
+                else if(epoll_events[i].events & EPOLLIN)
+                {
+                    if(epoll_events[i].data.fd == sock_listen_fd)   // New clients connected.
+                    {
+                        int client_fd = -1;
+                        while(1)
+                        {
+                            struct sockaddr_in cliaddr;
+                            socklen_t clilen = sizeof(cliaddr);
+                            client_fd = accept(epoll_events[i].data.fd, (struct sockaddr *) &cliaddr, &clilen);
+                            if(client_fd < 0)
+                            {
+                                if(errno == EAGAIN)
+                                {
+                                    LOG("All client connect get.");
+                                }
+                                else
+                                {
+                                    LOG("accept() error[%d].", errno);
+                                }
+                                break;
+                            }
+                            // Set O_NONBLOCK
+                            int flags = fcntl(client_fd, F_GETFL, 0);
+                            if (flags > 0)
+                            {
+                                flags |= O_NONBLOCK;
+                                if (fcntl(client_fd, F_SETFL, flags) < 0)
+                                {
+                                    LOG("Set flags error:%d", errno);
+                                }
+                            }
+
+                            memset(&ev,0,sizeof(struct epoll_event));
+                            ev.data.fd = client_fd;
+                            ev.events = event;//EPOLLIN | EPOLLERR | EPOLLET;
+                            epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev);
+
+                            sock_client_info_t *info = (sock_client_info_t*)malloc(sizeof(sock_client_info_t));
+                            if(info)
+                            {
+                                memset(info, 0, sizeof(sock_client_info_t));
+                                info->fd = client_fd;
+                                if(server_ready_get() == 1)
+                                {
+                                    info->ind_num = 0;
+                                    pack_rsp_send(info->fd , MBTK_INFO_ID_IND_SERVER_STATE_CHANGE, "1", 1);
+                                    LOG("server ready ok.");
+                                }
+                                else
+                                {
+                                    info->ind_num = 1;
+                                    info->ind_register[0] = MBTK_INFO_ID_IND_SERVER_STATE_CHANGE;
+                                    LOG("server ready no.");
+                                }
+                                list_add(sock_client_list, info);
+                                LOG("Add New Client FD Into List.");
+                            }
+                            else
+                            {
+                                LOG("malloc() fail.");
+                            }
+                        }
+                    }
+                    else if((cli_info = cli_find(epoll_events[i].data.fd)) != NULL)    // Client data arrive.
+                    {
+                        // Read and process every message.
+                        mbtk_info_err_enum err = MBTK_INFO_ERR_SUCCESS;
+                        mbtk_info_pack_t** pack = mbtk_info_pack_recv(cli_info->fd, true, &err);
+
+                        // Parse packet error,send error response to client.
+                        if(pack == NULL)
+                        {
+                            if(err != MBTK_INFO_ERR_SUCCESS)
+                            {
+                                pack_error_send(cli_info->fd, MBTK_INFO_ID_REQ_UNKNOWN, err);
+                            }
+                        }
+                        else
+                        {
+#if 0
+                            int i = 0;
+                            while(pack[i] != NULL)
+                            {
+                                pack_distribute(cli_info, pack[i]);
+                                // Not free,will free in pack_process() or packet process thread.
+                                //mbtk_info_pack_free(&(pack[i]));
+                                i++;
+                            }
+                            free(pack);
+#else
+                            mbtk_info_pack_t** pack_ptr = pack;
+                            while(*pack_ptr)
+                            {
+                                pack_distribute(cli_info, *pack_ptr);
+                                // Not free,will free in pack_process() or packet process thread.
+                                //mbtk_info_pack_free(pack_ptr);
+                                pack_ptr++;
+                            }
+
+                            free(pack);
+#endif
+                        }
+                    }
+                    else
+                    {
+                        LOG("Unknown socket : %d", epoll_events[i].data.fd);
+                    }
+                }
+                else
+                {
+                    LOG("Unknown event : %x", epoll_events[i].events);
+                }
+            }
+        }
+        else
+        {
+            LOG("epoll_wait() fail[%d].", errno);
+        }
+    }
+
+    return NULL;
+}
+
+static void data_call_restart()
+{
+#if 0
+    // Waitting for network ok.
+    mbtk_net_info_t info;
+    int cme_err;
+    int i = 0;
+    while(i < 15) { // 15s timeout
+        cme_err = MBTK_INFO_ERR_CME_NON;
+        memset(&info, 0, sizeof(mbtk_net_info_t));
+        if(!req_net_sel_mode_get(&info, &cme_err) && cme_err == MBTK_INFO_ERR_CME_NON)
+        {
+            if(info.net_type >= 2) {
+                break;
+            }
+        }
+
+        sleep(1);
+        i++;
+    }
+#endif
+    // +CGACT
+    int cid;
+    LOGD("Start active APN.");
+    for(cid = MBTK_APN_CID_MIN; cid <= MBTK_APN_CID_MAX && cid_active[cid]; cid++) {
+        LOG("Active cid : %d", cid);
+        req_data_call_start(cid, NULL);
+    }
+}
+
+/*
+void mbtk_radio_ready_cb()
+{
+    pthread_t radio_pid;
+    pthread_attr_t thread_attr;
+    pthread_attr_init(&thread_attr);
+    if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
+    {
+        LOG("pthread_attr_setdetachstate() fail.");
+        return;
+    }
+
+    if(pthread_create(&radio_pid, &thread_attr, radio_ready_thread, NULL))
+    {
+        LOG("pthread_create() fail.");
+    }
+
+    pthread_attr_destroy(&thread_attr);
+}
+*/
+
+static void net_ifc_state_change(bool act, int cid)
+{
+    if(cid < MBTK_APN_CID_MIN || cid > MBTK_APN_CID_MAX) { // No nothing for cid 1 and 8
+        return;
+    }
+
+    char dev[20] = {0};
+    sprintf(dev, "ccinet%d", cid - 1);
+    if(act) { // Config IP.
+        // Get IP information.
+        mbtk_ipv4_info_t ipv4;
+        mbtk_ipv6_info_t ipv6;
+        memset(&ipv4, 0, sizeof(mbtk_ipv4_info_t));
+        memset(&ipv6, 0, sizeof(mbtk_ipv6_info_t));
+        int cme_err = MBTK_INFO_ERR_CME_NON;
+        if(!req_data_call_state_get(cid, &ipv4, &ipv6, &cme_err) && cme_err == MBTK_INFO_ERR_CME_NON)
+        {
+            // Config IPv4 address.
+            if(ipv4.valid) {
+                char ip[20] = {0};
+                if(inet_ntop(AF_INET, &(ipv4.IPAddr), ip, 20) == NULL) {
+                    LOGE("inet_ntop ipv4 ip fail.");
+                    return;
+                }
+
+                if(mbtk_ifc_configure2(dev, ip, 0, NULL, "255.255.255.0")) {
+                    LOGD("Config %s IPv4 %s fail.", dev, ip);
+                } else {
+                    LOGD("Config %s IPv4 %s success.", dev, ip);
+                }
+            }
+
+            // Config IPv6 address.
+            if(ipv6.valid) {
+                char ip[50] = {0};
+
+                if(inet_ntop(AF_INET6, &(ipv6.IPV6Addr), ip, 50) == NULL) {
+                    LOGE("inet_ntop ipv6 ip fail.");
+                    return;
+                }
+
+                if(mbtk_ipv6_config(dev, ip, 64)) {
+                    LOGD("Config %s IPv6 %s fail.", dev, ip);
+                } else {
+                    LOGD("Config %s IPv6 %s success.", dev, ip);
+                }
+            }
+        }
+    } else { // Del IP
+        if(mbtk_ifc_configure2(dev, NULL, 0, NULL, NULL)) {
+            LOGD("Config %s IPv4 0 fail.", dev);
+        } else {
+            LOGD("Config %s IPv4 0 success.", dev);
+        }
+    }
+}
+
+static void urc_msg_process(info_urc_msg_t *msg)
+{
+    uint8 *data = NULL;
+    if(msg->data) {
+        data = (uint8*)msg->data;
+    }
+    switch(msg->msg) {
+        case INFO_URC_MSG_RADIO_STATE:
+        {
+            radio_state_change(msg->data, msg->data_len);
+            // Reconfig APN while radio on.
+            if(data[0]) {
+                apn_prop_get();
+            }
+            break;
+        }
+        case INFO_URC_MSG_CGEV:
+        {
+            bool act = data[0];
+            int cid = data[1];
+            if(cid > 0) {
+                net_ifc_state_change(act, cid);
+            }
+            break;
+        }
+        case INFO_URC_MSG_NET_PS_REG_STATE:
+        {
+            uint8 net_data[3];
+            net_data[0] = (uint8)MBTK_NET_PS_STATE;
+            net_data[1] = data[0];
+            mbtk_net_reg_state_enum state = (mbtk_net_reg_state_enum)data[0];
+            if(state == MBTK_NET_REG_STATE_HOME
+                || state == MBTK_NET_REG_STATE_ROAMING) { // Registered, home network or roaming.
+                mbtk_net_info_t info;
+                int cme_err = MBTK_INFO_ERR_CME_NON;
+                memset(&info, 0, sizeof(mbtk_net_info_t));
+                if(!req_net_sel_mode_get(&info, &cme_err) && cme_err == MBTK_INFO_ERR_CME_NON)
+                {
+                    net_data[2] = info.net_type;
+                    net_state_change(net_data, sizeof(net_data));
+
+                    if(info.net_type >= MBTK_RADIO_TECH_UTRAN) {
+                        data_call_restart();
+                    }
+                } else {
+                    net_data[2] = (uint8)0xFF;
+                    net_state_change(net_data, sizeof(net_data));
+                }
+            } else {
+                net_data[2] = (uint8)0xFF;
+                net_state_change(net_data, sizeof(net_data));
+            }
+            break;
+        }
+        case INFO_URC_MSG_NET_STATE_LOG:
+        {
+            // Get network state and signal.
+            char buff[256] = {0};
+            mbtk_signal_info_t signal;
+            memset(&signal, 0xFF, sizeof(mbtk_signal_info_t));
+            if(!req_net_signal_get(&signal, NULL)) {
+                char tmp[50] = {0};
+                struct timeval log_time;
+                gettimeofday(&log_time, NULL);
+                struct tm* tm_t = localtime(&(log_time.tv_sec));
+                strftime(tmp, 50, "%F %T", tm_t);
+                snprintf(buff, sizeof(buff), "%s:%d,%d,%d,%d,%d,%d,%d,%d", tmp, signal.type, signal.rssi, signal.rxlev, signal.ber, signal.rscp, signal.ecno,
+                    signal.rsrq, signal.rsrp);
+                mbtk_signal_log(buff);
+            }
+            //
+            break;
+        }
+        default:
+        {
+            LOGE("Unknown URC : %d", msg->msg);
+            break;
+        }
+    }
+}
+
+static void* pack_process_thread(void* arg)
+{
+    UNUSED(arg);
+    info_queue_item_t* item = NULL;
+    mbtk_queue_init(&info_queue);
+    pthread_mutex_init(&info_mutex, NULL);
+    pthread_cond_init(&info_cond, NULL);
+
+    memset(&band_support, 0xFF, sizeof(mbtk_band_info_t));
+
+    pthread_mutex_lock(&info_mutex);
+    while(TRUE)
+    {
+        if(mbtk_queue_empty(&info_queue))
+        {
+            LOG("Packet process wait...");
+            pthread_cond_wait(&info_cond, &info_mutex);
+            LOG("Packet process continue...");
+        }
+        else
+        {
+            LOG("Packet process queue not empty,continue...");
+        }
+
+        // Process all information request.
+        mbtk_info_err_enum err;
+        while((item = (info_queue_item_t*)mbtk_queue_get(&info_queue)) != NULL)
+        {
+            if(item->cli_info) { // REQ form client.
+                mbtk_info_pack_t *pack = (mbtk_info_pack_t*)item->pack;
+                LOG("Process REQ %s.", id2str(pack->info_id));
+                at_process = true;
+                err = pack_req_process(item->cli_info, pack);
+                if(err != MBTK_INFO_ERR_SUCCESS)
+                {
+                    if(item->cli_info->fd != DATA_CALL_BOOTCONN_FD)
+                    {
+                        pack_error_send(item->cli_info->fd, pack->info_id + 1, err);
+                    }
+                    else
+                    {
+                        free(pack->data);
+                        free(item->cli_info);
+                    }
+                }
+                at_process = false;
+                mbtk_info_pack_free(&pack);
+                free(item);
+            } else { // REQ from myself.
+                info_urc_msg_t *urc = (info_urc_msg_t*)item->pack;
+                LOG("Process URC %d.", urc->msg);
+                urc_msg_process(urc);
+                if(!urc->data)
+                    free(urc->data);
+                free(urc);
+            }
+        }
+    }
+    pthread_mutex_unlock(&info_mutex);
+    return NULL;
+}
+
+void apn_prop_get()
+{
+    char prop_name[20];
+    char prop_data[300];
+    // cid : 2 - 7
+    int cid = MBTK_APN_CID_MIN;
+    mbtk_apn_info_t apn;
+    for(; cid <= MBTK_APN_CID_MAX; cid++) {
+        memset(prop_name, 0, 20);
+        memset(prop_data, 0, 300);
+        memset(&apn, 0, sizeof(mbtk_apn_info_t));
+        sprintf(prop_name, "%s_%d",MBTK_APN_PROP,cid);
+        if(property_get(prop_name, prop_data, "") > 0 && !str_empty(prop_data)) {
+            apn.cid = cid;
+            char *ptr_1 = prop_data;
+            apn.ip_type = (mbtk_ip_type_enum)atoi(ptr_1);
+            ptr_1 = strstr(ptr_1, ",");
+            if(!ptr_1) {
+                continue;
+            }
+            ptr_1++; // Jump ',' to apn
+
+            char *ptr_2 = strstr(ptr_1, ",");
+            if(!ptr_2) {
+                continue;
+            }
+            memcpy(apn.apn, ptr_1, ptr_2 - ptr_1); // apn
+
+            ptr_2++; // Jump ',' to user
+            ptr_1 = strstr(ptr_2, ",");
+            if(!ptr_1) {
+                continue;
+            }
+            if(memcmp(ptr_2, "NULL", 4)) { // Not "NULL"
+                memcpy(apn.user, ptr_2, ptr_1 - ptr_2); // user
+            }
+
+            ptr_1++; // Jump ',' to pass
+            ptr_2 = strstr(ptr_1, ",");
+            if(!ptr_2) {
+                continue;
+            }
+            if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+                memcpy(apn.pass, ptr_1, ptr_2 - ptr_1); // pass
+            }
+
+            ptr_2++; // Jump ',' to auth (Is last item)
+            if(memcmp(ptr_2, "NULL", 4)) { // Not "NULL"
+                memcpy(apn.auth, ptr_2, strlen(ptr_2)); // auth
+            }
+
+            req_apn_set(&apn, NULL);
+        }
+    }
+}
+
+/*
+AT*BAND=15,78,147,482,134742231
+
+OK
+*/
+static int lte_b28_set()
+{
+    int err = -1;
+    ATResponse *p_response = NULL;
+    char *line;
+    char *ipv4 = NULL, *ipv6 = NULL;
+    err = at_send_command("AT*BAND=15,78,147,482,134742231", &p_response);
+    if ((err < 0) || (p_response == NULL) || (p_response->success == 0))
+    {
+        LOGE("*BAND exec error.");
+        err = -1;
+        goto error;
+    }
+
+    LOGD("Set B28 Success.");
+    err = 0;
+
+error:
+    at_response_free(p_response);
+    return err;
+}
+
+static void* net_monitor_thread(void* arg)
+{
+    UNUSED(arg);
+    // Start network monitor
+    int cid;
+    while(1) {
+#if 0
+        // Config IP
+        list_node_t* apn_list = NULL;
+        if(!apn_state_get(&apn_list) && apn_list != NULL) {
+            info_apn_ip_t *apn = NULL;
+            for(cid = MBTK_APN_CID_MIN; cid <= MBTK_APN_CID_MAX && cid_active[cid]; cid++) {
+                bool ip_found = false;
+                list_first(apn_list);
+                while ((apn = (info_apn_ip_t*) list_next(apn_list))) {
+                    if(cid == apn->cid) {
+                        ip_found = true;
+                        break;
+                    }
+                }
+
+                char dev[20] = {0};
+                sprintf(dev, "ccinet%d", cid - 1);
+                if(ip_found) { // Ip ok,set IP.
+                    if(apn->ipv4_valid) {
+                        if(mbtk_ifc_configure2(dev, (char*)apn->ipv4, 0, NULL, "255.255.255.0")) {
+                            LOGD("Config %s IPv4 %s fail.", dev, apn->ipv4);
+                        } else {
+                            LOGD("Config %s IPv4 %s success.", dev, apn->ipv4);
+                        }
+                    }
+
+                    if(apn->ipv6_valid) {
+                        if(mbtk_ipv6_config(dev, (char*)apn->ipv6, 64)) {
+                            LOGD("Config %s IPv6 %s fail.", dev, apn->ipv6);
+                        } else {
+                            LOGD("Config %s IPv6 %s success.", dev, apn->ipv6);
+                        }
+                    }
+                } else { // No ip
+                    if(mbtk_ifc_configure2(dev, NULL, 0, NULL, NULL)) {
+                        LOGD("Config %s IPv4 0 fail.", dev);
+                    } else {
+                        LOGD("Config %s IPv4 0 success.", dev);
+                    }
+                }
+            }
+
+            list_free(apn_list);
+        }
+#endif
+
+        if(net_info.radio_state == MBTK_RADIO_STATE_ON && net_info.sim_state == MBTK_SIM_READY) {
+#if 0
+            urc_msg_distribute(true, INFO_URC_MSG_NET_CS_REG_STATE, NULL, 0);
+#else
+            info_urc_msg_t *urc = (info_urc_msg_t*)malloc(sizeof(info_urc_msg_t));
+            if(!urc)
+            {
+                LOG("malloc() fail[%d].", errno);
+            } else {
+                urc->msg = INFO_URC_MSG_NET_STATE_LOG;
+                urc->data = NULL;
+                urc->data_len = 0;
+                send_pack_to_queue(NULL, urc);
+            }
+#endif
+        }
+
+        sleep(15);
+    }
+
+    LOGD("monitor_thread exit.");
+    return NULL;
+}
+
+static void* urc_process_thread(void* arg)
+{
+    UNUSED(arg);
+    info_urc_msg_t* item = NULL;
+    mbtk_queue_init(&urc_queue);
+    pthread_mutex_init(&urc_mutex, NULL);
+    pthread_cond_init(&urc_cond, NULL);
+
+    pthread_mutex_lock(&urc_mutex);
+    while(TRUE)
+    {
+        if(mbtk_queue_empty(&urc_queue))
+        {
+            LOG("URC process wait...");
+            pthread_cond_wait(&urc_cond, &urc_mutex);
+            LOG("URC process continue...");
+        }
+        else
+        {
+            LOG("URC process queue not empty,continue...");
+        }
+
+        // Process all information request.
+        while((item = (info_urc_msg_t*)mbtk_queue_get(&urc_queue)) != NULL)
+        {
+            LOG("Process URC %d.", item->msg);
+            uint8 *data = (uint8*)item->data;
+            switch(item->msg) {
+                case INFO_URC_MSG_RADIO_STATE:
+                {
+                    radio_state_change(item->data, item->data_len);
+                    break;
+                }
+                case INFO_URC_MSG_CGEV:
+                {
+                    bool act = data[0];
+                    int cid = data[1];
+                    if(cid > 0) {
+                        net_ifc_state_change(act, cid);
+                    }
+                    break;
+                }
+                default:
+                {
+                    LOGE("Unknown URC : %d", item->msg);
+                    break;
+                }
+            }
+            if(!item->data)
+                free(item->data);
+            free(item);
+        }
+    }
+    pthread_mutex_unlock(&urc_mutex);
+
+    return NULL;
+}
+
+static void ril_at_ready_process()
+{
+    net_info.radio_state = (isRadioOn() == 1) ? MBTK_RADIO_STATE_ON : MBTK_RADIO_STATE_OFF;
+#if 1
+    if (net_info.radio_state != MBTK_RADIO_STATE_ON)
+    {
+        setRadioPower(1);
+    } else { // Radio has ON
+        apn_prop_get();
+    }
+
+    if(net_info.radio_state == MBTK_RADIO_STATE_ON)
+    {
+        at_send_command("AT+CEREG=2", NULL);
+    }
+
+    int count = 0;
+#endif
+    net_info.sim_state = getSIMStatus();
+#if 0
+    while (net_info.sim_state != MBTK_SIM_READY && count < 30)
+    {
+        if(net_info.radio_state != MBTK_RADIO_STATE_ON)
+        {
+            setRadioPower(1);
+        }
+        LOGD("Waitting for SIM READY...");
+        sleep(1);
+        net_info.sim_state = getSIMStatus();
+        count++;
+    }
+#endif
+    if(net_info.sim_state == MBTK_SIM_READY)
+    {
+        LOGD("SIM READY!");
+    }
+    else
+    {
+        LOGE("SIM NOT READY!");
+    }
+
+    // Set B28
+    // AT*BAND=15,78,147,482,134742231
+#if MBTK_LTE_B28_SUPPORT
+    char b28_config[10];
+    memset(b28_config, 0, 10);
+    property_get("persist.mbtk.b28_config", b28_config, "0");
+    if(atoi(b28_config) == 0) {
+        if(!lte_b28_set()) { // Set B28 success.
+            property_set("persist.mbtk.b28_config", "1");
+        }
+    }
+#endif
+}
+
+int mbtk_info_server_start()
+{
+    signal(SIGPIPE, SIG_IGN);
+
+    if(sock_listen_fd > 0)
+    {
+        LOG("Information Server Has Started.");
+        return -1;
+    }
+
+    struct sockaddr_un server_addr;
+    sock_listen_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+    if(sock_listen_fd < 0)
+    {
+        LOG("socket() fail[%d].", errno);
+        return -1;
+    }
+
+    // Set O_NONBLOCK
+    int flags = fcntl(sock_listen_fd, F_GETFL, 0);
+    if (flags < 0)
+    {
+        LOG("Get flags error:%d", errno);
+        goto error;
+    }
+    flags |= O_NONBLOCK;
+    if (fcntl(sock_listen_fd, F_SETFL, flags) < 0)
+    {
+        LOG("Set flags error:%d", errno);
+        goto error;
+    }
+
+    unlink(SOCK_INFO_PATH);
+    memset(&server_addr, 0, sizeof(struct sockaddr_un));
+    server_addr.sun_family = AF_LOCAL;
+    strcpy(server_addr.sun_path, SOCK_INFO_PATH);
+    if(bind(sock_listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)))
+    {
+        LOG("bind() fail[%d].", errno);
+        goto error;
+    }
+
+    if(listen(sock_listen_fd, SOCK_CLIENT_MAX))
+    {
+        LOG("listen() fail[%d].", errno);
+        goto error;
+    }
+
+    sock_client_list = list_create(sock_cli_free_func);
+    if(sock_client_list == NULL)
+    {
+        LOG("list_create() fail.");
+        goto error;
+    }
+
+    pthread_t info_pid, pack_pid, monitor_pid, urc_pid, bootconn_pid;
+    pthread_attr_t thread_attr;
+    pthread_attr_init(&thread_attr);
+    if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
+    {
+        LOG("pthread_attr_setdetachstate() fail.");
+        goto error;
+    }
+
+    if(pthread_create(&info_pid, &thread_attr, info_main_pthread, NULL))
+    {
+        LOG("pthread_create() fail.");
+        goto error;
+    }
+
+    if(pthread_create(&pack_pid, &thread_attr, pack_process_thread, NULL))
+    {
+        LOG("pthread_create() fail.");
+        goto error;
+    }
+
+#if 0
+    if(pthread_create(&urc_pid, &thread_attr, urc_process_thread, NULL))
+    {
+        LOG("pthread_create() fail.");
+        goto error;
+    }
+#endif
+
+    ril_at_ready_process();
+
+    if(pthread_create(&monitor_pid, &thread_attr, net_monitor_thread, NULL))
+    {
+        LOG("pthread_create() fail.");
+    }
+
+    //mbtk wyq for data_call_ex add start
+    if(pthread_create(&bootconn_pid, &thread_attr, data_call_bootconn_pthread, NULL))
+    {
+        LOG("pthread_create() fail.");
+    }
+    //mbtk wyq for data_call_ex add end
+
+    pthread_attr_destroy(&thread_attr);
+
+    LOG("MBTK Information Server Start...");
+
+    return 0;
+
+error:
+    close(sock_listen_fd);
+    sock_listen_fd = -1;
+    return -1;
+}
+
+#if 0
+int main(int argc, char *argv[])
+{
+    if(mbtk_info_server_start())
+    {
+        return -1;
+    }
+
+    while(1)
+    {
+        sleep(24 * 60 * 60);
+    }
+
+    return 0;
+}
+#endif
+
+
diff --git a/mbtk/mbtk_ril/src/mbtk_phonebook.c b/mbtk/mbtk_ril/src/mbtk_phonebook.c
new file mode 100755
index 0000000..215727c
--- /dev/null
+++ b/mbtk/mbtk_ril/src/mbtk_phonebook.c
@@ -0,0 +1,54 @@
+#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 <fcntl.h>
+#include <signal.h>
+
+#include "mbtk_type.h"
+#include "mbtk_info.h"
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_utils.h"
+#include "info_data.h"
+
+void pack_rsp_send(int fd, int info_id, const void* data, int data_len);
+
+//void net_list_free(void *data);
+// Return MBTK_INFO_ERR_SUCCESS,will call pack_error_send() to send RSP.
+// Otherwise, do not call pack_error_send().
+mbtk_info_err_enum pb_pack_req_process(sock_client_info_t* cli_info, mbtk_info_pack_t* pack)
+{
+    mbtk_info_err_enum err = MBTK_INFO_ERR_SUCCESS;
+    int cme_err = MBTK_INFO_ERR_CME_NON;
+    switch(pack->info_id)
+    {
+        case MBTK_INFO_ID_PB_STATE_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+            }
+            else     // Set
+            {
+
+            }
+            break;
+        }
+        default:
+        {
+            err = MBTK_INFO_ERR_REQ_UNKNOWN;
+            LOG("Unknown request : %s", id2str(pack->info_id));
+            break;
+        }
+    }
+
+    return err;
+}
+
+
diff --git a/mbtk/mbtk_ril/src/mbtk_sms.c b/mbtk/mbtk_ril/src/mbtk_sms.c
new file mode 100755
index 0000000..5235a18
--- /dev/null
+++ b/mbtk/mbtk_ril/src/mbtk_sms.c
@@ -0,0 +1,1212 @@
+#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 <fcntl.h>
+#include <signal.h>
+
+#include "mbtk_type.h"
+#include "mbtk_info.h"
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_utils.h"
+#include "info_data.h"
+
+void pack_rsp_send(int fd, int info_id, const void* data, int data_len);
+
+/*
+AT+CMGF?
++CMGF: 0
+
+OK
+
+*/
+static int req_cmgf_get(int *state, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT+CMGF?", "", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    printf("req_cmgf_get() ---line:%s\n", line);
+    char* ptr = strstr(line, "+CMGF: ");
+    printf("req_cmgf_get() ---ptr:%s\n",ptr);
+    if(ptr)
+    {
+        *state = atoi(ptr + strlen("+CMGF: "));
+    }
+    else
+    {
+        err = -1;
+    }
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CMGF=0"
+or
+AT+CMGF=1"
+
+OK
+*/
+static int req_cmgf_set(int state, int *cme_err)
+{
+    printf("req_cmgf_set()-------------start\n");
+    printf("state:%d\n",state);
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+    if(state)
+    {
+        strcpy(cmd, "AT+CMGF=1");
+    }
+    else
+    {
+        strcpy(cmd, "AT+CMGF=0");
+    }
+
+    printf("req_cmgf_set()----cmd:%s\n", cmd);
+    int err = at_send_command(cmd, &response);
+
+    if (err < 0 || response->success == 0) {
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    err = 0;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*set AT+CNMI=1,2*/
+static int req_cnmi_set(int *cme_err)
+{
+    printf("req_cnmi_set()-------------start3\n");
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+
+	strcpy(cmd, "AT+CNMI=1,2");
+
+    printf("req_cnmi_set()----cmd:%s\n", cmd);
+    int err = at_send_command(cmd, &response);
+
+    if (err < 0 || response->success == 0) {
+		printf("err:%d, response->success:%d \n", err, response->success);
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    err = 0;
+exit:
+    at_response_free(response);
+    printf("exit,err:%d\n", err);
+    return err;
+}
+
+/*
+AT+CPMS?
+
++CPMS: "SM",15,50,"SM",15,50,"SM",15,50
+
+OK
+
+*/
+static int req_cpms_get(char *reg, int *cme_err)
+{
+	printf("req_cpms_get------------start(3)\n");
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT+CPMS?", "", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+	ATLine* lines_ptr = response->p_intermediates;
+	char *line = NULL;
+	int len = 0;
+	while(lines_ptr)
+	{
+		line = lines_ptr->line;
+		if(line ==NULL)
+		{
+			printf("line is null----------------------\n");
+		}
+
+		printf("-----------line:%s, strlen:%d, len:%d----------\n", line, strlen(line), len);
+		memcpy(reg+len, line, strlen(line));
+        len += strlen(line);
+		lines_ptr = lines_ptr->p_next;
+	}
+
+	printf("cpms_get()------reg:%s\n", reg);
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+
+/*
+AT+CPMS=<mem1>[,<mem2>[,<mem3>]]
+AT+CPMS="ME","ME","ME"
+
++CPMS: 14,50,14,50,14,50
+
+OK
+
+*/
+static int req_cpms_set(const char *mem, char *reg, int len, int *cme_err)
+{
+    printf("req_cpms_set(2)----------------start\n");
+    printf("mem:%s\n", mem);
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+    int err = 0;
+	char data[20] = {0};
+
+    if(mem != NULL)
+    {
+    	memcpy(data, mem, len);
+        sprintf(cmd, "AT+CPMS=%s", data);
+    }
+    else{
+        printf("mem is null\n");
+    }
+
+	printf("cmd:%s,data:%s---------\n", cmd,data);
+
+	if(strlen(cmd) > 8)
+	{
+        err = at_send_command_multiline(cmd, "+CPMS:", &response);
+        if (err < 0 || response->success == 0){
+            *cme_err = at_get_cme_error(response);
+            goto exit;
+        }
+
+        char *line = response->p_intermediates->line;
+        printf("line:%s, len:%d\n", line, strlen(line));
+
+        memcpy(reg, line, strlen(line));
+
+        printf("cpms_reg:%s\n", reg);
+	}
+    err = 0;
+exit:
+    printf("goto exit do");
+    at_response_free(response);
+    return err;
+}
+
+/*
+if PDU mode (+CMGF=0):
+	AT+CMGS=<length><CR>
+PDU is given<ctrl-Z/ESC>
+if text mode (+CMGF=1):
+	AT+CMGS=<da>[,<toda>]<CR>
+text is entered<ctrl-Z/ESC>
+
+	AT+CMGS=15775690697,hello world
+
+
+*/
+static int req_cmgs_set(char *cmgs, char *reg, int len, int *cme_err)
+{
+    printf("req_cmgs_set()----------------start\n");
+    printf("cmgs:%s\n", cmgs);
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+	char data[218] = {0};
+	char pnum[13] = {0};
+    char *ptr = cmgs;
+    int err = 0;
+	int data_len = 0;
+
+	char *src = strstr(cmgs, ",");
+	if(src != NULL)
+	{
+		memcpy(pnum, ptr,  src - ptr);
+		src++;
+		int data_len = 0;
+        data_len = len - (src - ptr);
+		memcpy(data, src, data_len);
+	}
+
+	sprintf(cmd, "AT+CMGS=%s", pnum);
+	printf("cmd:%s,data:%s---------\n", cmd,data);
+	
+
+	if(strlen(cmd) > 0)
+	{
+		int err = at_send_command_sms(cmd, data, "+CMGS: ", &response);
+		printf("err:%d, response:%d\n", err, response->success);
+
+		if (err < 0 || response->success == 0) {
+	        *cme_err = at_get_cme_error(response);
+	        goto exit;
+	    }
+		char *line;
+		line = response->p_intermediates->line;
+		memcpy(reg, line, strlen(line));
+		printf("line:%s\n", line);
+
+	}
+    err = 0;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+static int req_cmgw_set(char *cmgw,int len, int *cme_err)
+{
+    printf("req_cmgw_set()----------------start\n");
+    printf("cmgw:%s\n", cmgw);
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+	char data[218] = {0};
+	char pnum[13] = {0};
+    char *ptr = cmgw;
+    int err = 0;
+
+	char *src = strstr(cmgw, ",");
+	if(src != NULL)
+	{
+		memcpy(pnum, ptr,  src - ptr);
+		src++;
+		int data_len = 0;
+        data_len = len - (src - ptr);
+		memcpy(data, src, data_len);
+	}
+
+	sprintf(cmd, "AT+CMGW=%s", pnum);
+	printf("cmd:%s,data:%s---------\n", cmd,data);
+	
+	if(strlen(cmd) > 0)
+	{
+		int err = at_send_command_sms(cmd, data, "+CMGW: ", &response);
+		printf("err:%d, response:%d\n", err, response->success);
+
+		if (err < 0 || response->success == 0) {
+	        *cme_err = at_get_cme_error(response);
+	        goto exit;
+	    }
+		char *line;
+		line = response->p_intermediates->line;
+		printf("line:%s\n", line);
+	}
+    err = 0;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CMGD=25
+OK
+
++MMSG: 1, 0
+*/
+static int req_cmgd_set(char *cmgd, int len, int *cme_err)
+{
+    printf("0req_cmgd_set()--------------start\n");
+    printf("cmgd:%s\n", cmgd);
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+	char data[218] = {0};
+	char pnum[13] = {0};
+    char *ptr = cmgd;
+    int err = 0;
+
+	memcpy(data, cmgd, len );
+	sprintf(cmd, "AT+CMGD=%s", data);
+	printf("cmd:%s,data:%s---------\n", cmd,data);
+	
+	if(strlen(cmd) > 0)
+	{
+		int err = at_send_command(cmd, &response);
+	    if (err < 0 || response->success == 0) {
+	        *cme_err = at_get_cme_error(response);
+	        goto exit;
+	    }
+
+//     Format problem caused the crash
+//       char *line;
+//		line = response->p_intermediates->line;
+//		printf("line:%s\n", line);
+	}
+    err = 0;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CMGL="ALL"	
+
++CMGL: 1,"REC READ","10658678",,"22.11.14 10:41:44 GMT+8"
+
+56DB5DDD62
+
++CMGL: 2,"STO UNSENT","18927467953"
+hello world
+
+*/
+
+static int req_cmgl_set(const char *cmgl, char *reg, int len, int *cme_err)
+{
+    printf("req_cmgl_set(2)-----------------start\n");
+    printf("cmgl:%s\n", cmgl);
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+	char data[218] = {0};
+	char index_data[256] = {0};
+	int s_index = 0, g_index = 0;
+	bool index_flag = false;
+	char *ptr_index = index_data;
+	char phone[50];
+	char number[5] = {0};
+    int err = 0;
+
+	memcpy(data, cmgl, len);
+
+	char *ptr1 = data;
+	char *ptr2 = strstr(data, ",");
+	if(ptr2 != NULL)
+	{
+		memcpy(number,ptr1, ptr2-ptr1 );
+		s_index = atoi(number);
+		if(s_index == 0)
+		{
+			index_flag = TRUE;
+			memcpy(ptr_index, "+CMGL:", strlen("+CMGL:"));
+		}
+        memset(number, 0, sizeof(number));
+		ptr2++;
+	}else{
+		printf("cmgl set data is error\n eg:index,data\n");
+		return -1;
+	}
+
+	sprintf(cmd, "AT+CMGL=%s", ptr2);
+	printf("cmd:%s\n", cmd);
+
+	ptr1 = NULL;
+	ptr2 = NULL;
+	
+	if(strlen(cmd) > 0)
+	{
+        err = at_send_command_multiline(cmd, "", &response);
+		if (err < 0 || response->success == 0 || !response->p_intermediates){
+			*cme_err = at_get_cme_error(response);
+            printf("at_send_command_multiline() is err-----------------\n");
+			goto exit;
+		}
+
+        ATLine* lines_ptr = response->p_intermediates;
+        char *line = NULL;
+        int reg_len = 0;
+		bool flag = false;
+        while(lines_ptr)
+        {
+            line = lines_ptr->line;
+            if(line ==NULL)
+            {
+                printf("line is null----------------------\n");
+            }
+
+            printf("-----line:%s\n", line);
+			if(!flag)
+			{
+				ptr1 = strstr(line, "+CMGL: ");
+				if(ptr1 != NULL)
+				{
+                    ptr1 += 7;
+                    ptr2 = strstr(line, ",");
+                    memcpy(number,ptr1, ptr2-ptr1 );
+                    printf("number:%s, ptr1:%s, ptr2:%s\n", number, ptr1, ptr2);
+                    g_index = atoi(number);
+                    if(index_flag)
+                    {
+                        sprintf(ptr_index+strlen(ptr_index), "%d,", g_index);
+                    }
+				}
+				//if( g_index == s_index)
+                if( g_index == s_index  && !index_flag)
+				{
+                    printf("g_index == s_index, g_index:%d,s_index:%d\n", g_index, s_index);
+					flag = true;
+				}
+			}
+			if(flag && reg_len <=1024)
+			{
+	            memcpy(reg+reg_len, line, strlen(line));
+	            printf("-----memcpy------reg:%s----------\n", reg);
+	            printf("len:%d\n", reg_len);
+	            reg_len += strlen(line);
+			}
+
+            lines_ptr = lines_ptr->p_next;
+        }
+	}
+
+	if(index_flag)
+	{
+		memset(reg, 0, sizeof(reg));
+		memcpy(reg, ptr_index, strlen(ptr_index) );
+	}
+    err = 0;
+exit:
+    at_response_free(response);
+    printf("req_cmgl_set()-----------------end\n");
+    return err;
+}
+
+/*
+at+csca?
++CSCA: "+8613800280500",145
+OK
+*/
+static int req_csca_get(char *req, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT+CSCA?", "", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    char *line = response->p_intermediates->line;
+    printf("req_csca_get() ---line:%s\n", line);
+    char* ptr = strstr(line, "+CSCA: ");
+    printf("req_csca_get() ---ptr:%s\n",ptr);
+    if(ptr)
+    {
+        memcpy(req, line, strlen(line));
+        printf("err:%d, req:%s\n", err, req);
+        err = 0;
+    }
+    else
+    {
+        err = -1;
+    }
+    
+exit:
+    at_response_free(response);
+    return err;
+}
+
+static int req_csca_set(char *csca, int len, int *cme_err)
+{
+    printf("req_csca_set()--------------start\n");
+    printf("csca:%s\n", csca);
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+	char data[218] = {0};
+	char pnum[13] = {0};
+    char *ptr = csca;
+    int err = 0;
+
+	memcpy(data, csca, len);
+	sprintf(cmd, "AT+CSCA=%s", data);
+	printf("cmd:%s,data:%s---------\n", cmd,data);
+	
+	if(strlen(cmd) > 0)
+	{
+		int err = at_send_command(cmd, &response);
+	    if (err < 0 || response->success == 0) {
+	        *cme_err = at_get_cme_error(response);
+	        goto exit;
+	    }
+
+    //    char *line;
+	//	line = response->p_intermediates->line;
+	//	printf("line:%s\n", line);
+	}
+    err = 0;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+static int req_csmp_set(char *csmp, int len, int *cme_err)
+{
+    printf("req_csmp_set()-------------------start\n");
+    printf("csmp:%s\n", csmp);
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+	char data[218] = {0};
+	char pnum[13] = {0};
+    char *ptr = csmp;
+    int err = 0;
+
+	memcpy(data, csmp, len);
+	sprintf(cmd, "AT+CSMP=%s", data);
+	printf("cmd:%s,data:%s---------\n", cmd,data);
+	
+	if(strlen(cmd) > 0)
+	{
+		int err = at_send_command(cmd, &response);
+	    if (err < 0 || response->success == 0) {
+	        *cme_err = at_get_cme_error(response);
+	        goto exit;
+	    }
+
+        char *line;
+		line = response->p_intermediates->line;
+		printf("line:%s\n", line);
+	}
+    err = 0;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+static int req_cscb_set(char *cscb,int len, int *cme_err)
+{
+    printf("req_cscb_set()----------------start\n");
+    printf("cscb:%s\n", cscb);
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+	char data[218] = {0};
+	char pnum[13] = {0};
+    char *ptr = cscb;
+    int err = 0;
+
+	memcpy(data, cscb, len);
+	sprintf(cmd, "AT+CSCB=%s", cscb);
+	printf("cmd:%s,data:%s---------\n", cmd,data);
+	
+	if(strlen(cmd) > 0)
+	{
+		int err = at_send_command(cmd, &response);
+	    if (err < 0 || response->success == 0) {
+	        *cme_err = at_get_cme_error(response);
+	        goto exit;
+	    }
+
+        char *line;
+		line = response->p_intermediates->line;
+		printf("line:%s\n", line);
+	}
+    err = 0;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CMSS=13
++CMSS: 81
+OK
+*/
+static int req_cmss_set(const char *cmss, char *reg, int len, int *cme_err)
+{
+    printf("req_cmss_set()----------------start\n");
+    printf("cmss:%s\n", cmss);
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+	char data[20] = {0};
+    int err = 0;
+
+    if(cmss != NULL)
+    {
+    	memcpy(data, cmss, len);
+        sprintf(cmd, "AT+CMSS=%s", data);
+    //    sprintf(cmd, "AT+CMSS=%d", 8);
+    }
+    else{
+        printf("mem is null\n");
+    }
+
+    printf("cmss.   cmd:%s\n", cmd);
+
+	if(strlen(cmd) > 8)
+	{
+        err = at_send_command_multiline(cmd, "+CMSS:", &response);
+		if (err < 0 || response->success == 0){
+			*cme_err = at_get_cme_error(response);
+			goto exit;
+		}
+		
+		char *line = response->p_intermediates->line;
+		printf("line:%s\n", line);
+		
+		char *tmp_str = NULL;
+		err = at_tok_nextstr(&line, &tmp_str); // phone_number
+		if (err < 0)
+		{
+			goto exit;
+		}
+		memcpy(reg, tmp_str, strlen(tmp_str));
+		printf("cmss_reg:%s\n", reg);
+        /*
+	    int err = at_send_command(cmd, &response);
+
+	    if (err < 0 || response->success == 0) {
+	        *cme_err = at_get_cme_error(response);
+	        goto exit;
+	    }
+
+        char *line;
+		line = response->p_intermediates->line;
+		printf("line:%s\n", line);
+        */
+	}
+    err = 0;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+/*
+AT+CMGR=1
++CMGR: "REC READ","10658678",,"22.11.14 10:41:44 GMT+8"
+
+56DB5DDD624B673A62A5FF039003003400310034003500340035003F0073003D0037003800680061006C00450066
+
+OK
+*/
+static int req_cmgr_set(int index, char *reg, int *cme_err)
+{
+    printf("0req_cmgr_set()-------------------start\n");
+    printf("index:%d\n", index);
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+    int err = 0;
+    sprintf(cmd, "AT+CMGR=%d", index);
+
+    printf("req_cmgr_set()----cmd:%s\n", cmd);
+
+	if(strlen(cmd) > 0)
+	{
+        err = at_send_command_multiline(cmd, "", &response);
+		if (err < 0 || response->success == 0 || !response->p_intermediates){
+			*cme_err = at_get_cme_error(response);
+            printf("at_send_command_multiline() is err-----------------\n");
+			goto exit;
+		}
+
+        ATLine* lines_ptr = response->p_intermediates;
+        char *line = NULL;
+        int reg_len = 0;
+        while(lines_ptr)
+        {
+            line = lines_ptr->line;
+            if(line ==NULL)
+            {
+                printf("line is null----------------------\n");
+            }
+
+            if(reg_len > 0)
+			{
+				memcpy(reg+reg_len, "\r\n", strlen("\r\n"));
+				reg_len += strlen("\r\n");
+			}
+            memcpy(reg+reg_len, line, strlen(line));
+            printf("-----memcpy------reg:%s----------\n", reg);
+            printf("len:%d\n", reg_len);
+            reg_len += strlen(line);
+            lines_ptr = lines_ptr->p_next;
+        }
+	}
+
+    err = 0;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+//void net_list_free(void *data);
+// Return MBTK_INFO_ERR_SUCCESS,will call pack_error_send() to send RSP.
+// Otherwise, do not call pack_error_send().
+mbtk_info_err_enum sms_pack_req_process(sock_client_info_t* cli_info, mbtk_info_pack_t* pack)
+{
+    mbtk_info_err_enum err = MBTK_INFO_ERR_SUCCESS;
+    int cme_err = MBTK_INFO_ERR_CME_NON;
+    switch(pack->info_id)
+    {
+        case MBTK_INFO_ID_SMS_STATE_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+            }
+            else     // Set
+            {
+
+            }
+            break;
+        }
+        case MBTK_INFO_ID_SMS_CMGF_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                int state;
+                if(req_cmgf_get(&state, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Get SMS CMGF fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CMGF_RSP, &state, sizeof(uint8));
+                }
+            }
+            else     // Set VoLTE state.
+            {
+                uint8 mode = *(pack->data);
+                if(pack->data_len != sizeof(uint8) || (mode != 0 && mode != 1))
+                {
+                    err = MBTK_INFO_ERR_REQ_PARAMETER;
+                    LOG("Set SMS CMGF parameter error.");
+                    break;
+                }
+
+                if(req_cmgf_set(mode, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CMGF_RSP, NULL, 0);
+
+                    // Restart is required to take effect.
+                    LOG("Will reboot system...");
+                }
+            }
+            break;
+        }
+        case MBTK_INFO_ID_SMS_CNMI_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // SET at+cnmi=1,2.
+            {
+                int state;
+                if(req_cnmi_set(&cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    printf("set req_cnmi_set() fail.\n");
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("set sms cnmi fail.");
+                }
+                else
+                {
+                    printf("req_cnmi_set success\n");
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CNMI_RSP, NULL, 0);
+                }
+            }
+			break;
+		}
+        case MBTK_INFO_ID_SMS_CPMS_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                char reg[100] = {0};
+                if(req_cpms_get(reg, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Get SMS CMGF fail.");
+                }
+                else
+                {
+                    printf("req_cpms_get_ success, reg:%s, len:%d ", reg, strlen(reg));
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CPMS_RSP, reg, strlen(reg));
+                }
+            }
+            else     // Set VoLTE state.
+            {
+                char *mem = (char*)(pack->data);
+				int len = pack->data_len;
+                char reg[100] = {0};
+                printf("mem:%s, len:%d", pack->data, pack->data_len);
+
+                if(req_cpms_set(mem, reg, len, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    printf("cpms_set fail\n");
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    printf("cpms_set success, reg:%s\n", reg);
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CPMS_RSP, reg, strlen(reg));
+
+                    // Restart is required to take effect.
+                    LOG("Will reboot system...");
+                }
+            }
+            break;
+        }
+        case MBTK_INFO_ID_SMS_CMGS_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                printf("pack->data_len:%d,,pack->data:%s\n",pack->data_len, pack->data);
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+				char *cmgs = (char*)pack->data;
+				int len = pack->data_len;
+				char reg[50] ={0};
+                printf("mbtk_sms,cmgs:%s,len:%d\n", cmgs, len);
+
+                if(req_cmgs_set(cmgs,reg,len, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CMGS_RSP, reg, strlen(reg));
+
+                    // Restart is required to take effect.
+                    LOG("Will reboot system...");
+                }
+
+            }
+            break;
+        }
+        case MBTK_INFO_ID_SMS_CMSS_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                printf("pack->data_len:%d,,pack->data:%s\n",pack->data_len, pack->data);
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+				char *cmss = (char*)pack->data;
+				int len = pack->data_len;
+                char reg[128] = {0};
+                printf("mbtk_sms,cmgs:%s, len:%d\n", cmss, len);
+
+                if(req_cmss_set(cmss,reg, len, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    printf("req_cmss_set success, reg:%s", reg);
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CMSS_RSP, NULL, 0);
+
+                    // Restart is required to take effect.
+                    LOG("Will reboot system...");
+                }
+
+            }
+            break;
+        }
+        case MBTK_INFO_ID_SMS_CMGR_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                printf("pack->data_len:%d,,pack->data:%s\n",pack->data_len, pack->data);
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+                uint8 index = *(pack->data);
+                char reg[1024] = {0};
+                if(pack->data_len != sizeof(uint8) )
+                {
+                    err = MBTK_INFO_ERR_REQ_PARAMETER;
+                    LOG("Set SMS CMGF parameter error.");
+                    break;
+                }
+
+                if(req_cmgr_set(index, reg, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    printf("1req_cmgr_set_success, reg:%s\n", reg);
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CMGR_RSP, reg, strlen(reg));
+
+                    // Restart is required to take effect.
+                    LOG("Will reboot system...");
+                }
+
+            }
+            break;
+        }
+        case MBTK_INFO_ID_SMS_CMGW_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // +CMGW=<oa/da>[,<tooa/toda>[,<stat>]]<CR>
+            {
+                printf("pack->data_len:%d,,pack->data:%s\n",pack->data_len, pack->data);
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+            }
+            else     // Set cmgw data.
+            {
+				char *cmgw = (char*)pack->data;
+				int len = pack->data_len;
+                printf("mbtk_sms,cmgw:%s,len:%d\n", cmgw, len);
+
+                if(req_cmgw_set(cmgw, len, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CMGW_RSP, NULL, 0);
+
+                    // Restart is required to take effect.
+                    LOG("Will reboot system...");
+                }
+
+            }
+            break;
+        }
+        case MBTK_INFO_ID_SMS_CMGD_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                printf("pack->data_len:%d,,pack->data:%s\n",pack->data_len, pack->data);
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+				char *cmgd = (char*)pack->data;
+				int len = pack->data_len;
+                printf("mbtk_sms,cmgs:%s,len:%d\n", cmgd, len);
+
+                if(req_cmgd_set(cmgd,len, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CMGD_RSP, NULL, 0);
+
+                    // Restart is required to take effect.
+                    LOG("Will reboot system...");
+                }
+
+            }
+            break;
+        }
+        case MBTK_INFO_ID_SMS_CMGL_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                printf("pack->data_len:%d,,pack->data:%s\n",pack->data_len, pack->data);
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+				char *cmgl = (char*)pack->data;
+				int len = pack->data_len;
+                char reg[5*1024] = {0};
+                char reg1[1024+1] = {0};
+                printf("mbtk_sms,cmgs:%s, len:%d\n", cmgl, len);
+
+                if(req_cmgl_set(cmgl, reg, len, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                 //   printf("1cmgl_set_success---------len:%d\n reg:%s\n",strlen(reg), reg);
+                    memcpy(reg1, reg, 1024);
+                    printf("0len:%d, reg1:%s\n", strlen(reg1), reg1);
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CMGL_RSP, reg1, strlen(reg1));
+
+                    // Restart is required to take effect.
+                    LOG("Will reboot system...");
+                }
+
+            }
+            break;
+        }
+        case MBTK_INFO_ID_SMS_CSCA_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                char csca[50]={0};
+                if(req_csca_get(csca, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Get SMS CSCA fail.");
+                    printf("get sms csca fail\n");
+                }
+                else
+                {
+                    printf("get sms csca suscess\n");
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CSCA_RSP, csca, strlen(csca));
+                }
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+				char *csca = (char*)pack->data;
+				int len = pack->data_len;
+                printf("mbtk_sms,cmgs:%s,len:%d\n", csca, len);
+
+                if(req_csca_set(csca, len, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CSCA_RSP, NULL, 0);
+
+                    // Restart is required to take effect.
+                    LOG("Will reboot system...");
+                }
+
+            }
+            break;
+        }
+        case MBTK_INFO_ID_SMS_CSMP_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                printf("pack->data_len:%d,,pack->data:%s\n",pack->data_len, pack->data);
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+				char *csmp = (char*)pack->data;
+				int len = pack->data_len;
+                printf("mbtk_sms,cmgs:%s,len:%d\n", csmp, len);
+
+                if(req_csmp_set(csmp,len, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CSMP_RSP, NULL, 0);
+
+                    // Restart is required to take effect.
+                    LOG("Will reboot system...");
+                }
+
+            }
+            break;
+        }
+        case MBTK_INFO_ID_SMS_CSCB_REQ:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                printf("pack->data_len:%d,,pack->data:%s\n",pack->data_len, pack->data);
+                err = MBTK_INFO_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+				char *cscb = (char*)pack->data;
+				int len = pack->data_len;
+                printf("mbtk_sms,cmgs:%s, len:%d\n", cscb, len);
+
+                if(req_cscb_set(cscb,len, &cme_err) || cme_err != MBTK_INFO_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_INFO_ERR_CME_NON) {
+                        err = MBTK_INFO_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_INFO_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    pack_rsp_send(cli_info->fd, MBTK_INFO_ID_SMS_CSCB_RSP, NULL, 0);
+
+                    // Restart is required to take effect.
+                    LOG("Will reboot system...");
+                }
+
+            }
+            break;
+        }
+        default:
+        {
+            err = MBTK_INFO_ERR_REQ_UNKNOWN;
+            LOG("Unknown request : %s", id2str(pack->info_id));
+            break;
+        }
+    }
+
+    return err;
+}