Add mbtk_ril V2 (Default close)

Change-Id: Iaa5921fd74aeeb394771110f0cec7aa7742dc83a
diff --git a/build.sh b/build.sh
index 038f8ac..fd48038 100755
--- a/build.sh
+++ b/build.sh
@@ -35,6 +35,13 @@
 	export BUILD_STD_LIBC=glibc
 fi
 
+MBTK_SOURCE_VERSION_TEMP=`cat config | grep CONFIG_MBTK_SOURCE_VERSION | cut -d '=' -f 2`
+if [ "$MBTK_SOURCE_VERSION_TEMP" == "2" ];then
+	export MBTK_SOURCE_VERSION=2
+else
+	export MBTK_SOURCE_VERSION=1
+fi
+
 if [ "$BUILD_PLATFORM" == "master" ];then
 	if [ "`echo $BUILD_PROJECT_TEMP | cut -c 1-4`" == "L509" ];then
 		export BUILD_PROJECT=L509
@@ -227,6 +234,7 @@
 {
 	echo BUILD_PROJECT=$BUILD_PROJECT
 	echo BUILD_STD_LIBC=$BUILD_STD_LIBC
+	echo MBTK_SOURCE_VERSION=$MBTK_SOURCE_VERSION
 	echo MBTK_GNSS_MODE=$MBTK_GNSS_MODE
 	echo MBTK_AF_SUPPORT=$MBTK_AF_SUPPORT
 	echo MBTK_YX_SUPPORT=$MBTK_YX_SUPPORT
diff --git a/config b/config
index f4b451f..7e8a4e1 100755
--- a/config
+++ b/config
@@ -4,6 +4,9 @@
 # Libc glibc / musl
 CONFIG_MBTK_LIBC=glibc
 
+# mbtk_source version : 1 / 2
+CONFIG_MBTK_SOURCE_VERSION=1
+
 # MBTK gnss mode (gnss_all / gnss_5311 / gnss_6228 / gnss_8122)
 CONFIG_MBTK_GNSS_MODE=gnss_all
 
diff --git a/mbtk/Makefile b/mbtk/Makefile
index 58dbee1..7924744 100755
--- a/mbtk/Makefile
+++ b/mbtk/Makefile
@@ -3,13 +3,23 @@
 
 # Build so file.
 DIRS = libmbtk_lib libmbtk_net libmbtk_coap libmbtk_tcpip libmbtk_http libmbtk_ftp libmbtk_mqtt \
-		libmbtk_ril libmbtk_audio libmbtk_fota libmbtk_factory libmbtk_gnss
+       libmbtk_audio libmbtk_fota libmbtk_factory libmbtk_gnss
 
-# Build libql_lib and liblynq_lib.
-DIRS += libql_lib liblynq_lib
+# Build libmbtk_ril libql_lib and liblynq_lib.
+ifeq ($(MBTK_SOURCE_VERSION), 2)
+DIRS += libmbtk_ril_v2 libql_lib_v2 liblynq_lib_v2
+else
+DIRS += libmbtk_ril libql_lib liblynq_lib
+endif
 
 # Build bin file.
-DIRS += aboot-tiny mbtk_adbd mbtk_rild mbtk_logd mbtk_utils mbtk_utils_linux mbtk_sdk_ready mbtk_gnssd mbtk_servicesd
+ifeq ($(MBTK_SOURCE_VERSION), 2)
+DIRS += mbtk_rild_v2 mbtk_servicesd_v2
+else
+DIRS += mbtk_rild mbtk_servicesd
+endif
+
+DIRS += mbtk_sdk_ready aboot-tiny mbtk_adbd mbtk_logd mbtk_utils mbtk_utils_linux mbtk_gnssd
 
 # Build test file.
 DIRS += test
diff --git a/mbtk/include/mbtk/mbtk_ril_api.h b/mbtk/include/mbtk/mbtk_ril_api.h
new file mode 100755
index 0000000..1803411
--- /dev/null
+++ b/mbtk/include/mbtk/mbtk_ril_api.h
@@ -0,0 +1,982 @@
+/*
+*
+* Data : 2024/07/19 11:24:09
+* Author : LiuBin
+*/
+#ifndef _MBTK_INFO_API_2_H
+#define _MBTK_INFO_API_2_H
+#include <netinet/in.h>
+
+#include "mbtk_type.h"
+#include "mbtk_list.h"
+#include "mbtk_log.h"
+#include "mbtk_utils.h"
+#include "mbtk_pdu_sms.h"
+
+// LOG_DEBUG_LEVEL 7
+#define LOG LOGI
+
+#define MBTK_APN_CID_MIN 1
+#define MBTK_APN_CID_MAX 7
+#define CELL_NUM_MAX 50
+#define APN_STR_MAX 64
+#define RIL_PIN_STR_MAX 16
+
+typedef void (*mbtk_ril_callback_func)(const void* data, int data_len);
+
+typedef enum {
+    MBTK_RIL_CID_NUL = 0,   // Auto set cid.
+    MBTK_RIL_CID_DEF = MBTK_APN_CID_MIN,
+    MBTK_RIL_CID_1 = MBTK_RIL_CID_DEF,
+    MBTK_RIL_CID_2,
+    MBTK_RIL_CID_3,
+    MBTK_RIL_CID_4,
+    MBTK_RIL_CID_5,
+    MBTK_RIL_CID_6,
+    MBTK_RIL_CID_7 = MBTK_APN_CID_MAX
+} mbtk_ril_cid_enum;
+
+typedef enum {
+    MBTK_RIL_ERR_SUCCESS = 300,
+    MBTK_RIL_ERR_INITED,
+    MBTK_RIL_ERR_NOT_INIT,
+    MBTK_RIL_ERR_PARAMETER,     // Parameter error.
+    MBTK_RIL_ERR_FORMAT,       // Packet format error.
+    MBTK_RIL_ERR_SEND_PACK,    // Packet send fail.
+    MBTK_RIL_ERR_REQ_UNKNOWN,  // Unknown request.
+    MBTK_RIL_ERR_REQ_PARAMETER,  // Request parameter error.
+    MBTK_RIL_ERR_UNSUPPORTED,  // Unsupported operation.
+    MBTK_RIL_ERR_MEMORY,       // Insufficient memory.
+    MBTK_RIL_ERR_IND_FULL,     // Register IND fail(FULL).
+    MBTK_RIL_ERR_IND_UNKNOWN,  // Register IND fail(Unknown IND).
+    MBTK_RIL_ERR_CID,  // CID error.
+    MBTK_RIL_ERR_TIMEOUT,  // Timeout.
+    MBTK_RIL_ERR_TIME_FORMAT,  // Time format error.
+
+    MBTK_RIL_ERR_UNKNOWN = 400,  // Unknown error.
+    // CME error start index.
+    MBTK_RIL_ERR_CME = 500,
+    MBTK_RIL_ERR_CME_NON = 1000
+} mbtk_ril_err_enum;
+
+typedef enum {
+    MBTK_IP_TYPE_IP,
+    MBTK_IP_TYPE_IPV6,
+    MBTK_IP_TYPE_IPV4V6,
+    MBTK_IP_TYPE_PPP
+} mbtk_ip_type_enum;
+
+typedef enum {
+    MBTK_TEMP_TYPE_SOC,
+    MBTK_TEMP_TYPE_RF
+} mbtk_temp_type_enum;
+
+typedef enum {
+    MBTK_TIME_TYPE_CELL = 0,  //NITZ
+    MBTK_TIME_TYPE_NTP,
+    MBTK_TIME_TYPE_GNSS,
+    MBTK_TIME_TYPE_USER
+} mbtk_time_type_enum;
+
+/*
+0: GSM
+1: GSM Compact
+2: UTRAN
+3: GSM w/EGPRS
+4: UTRAN w/HSDPA
+5: UTRAN w/HSUPA
+6: UTRAN w/HSDPA and HSUPA
+7: E-UTRAN
+8: UTRAN HSPA+
+*/
+typedef enum {
+    MBTK_RADIO_TECH_GSM = 0,
+    MBTK_RADIO_TECH_GSM_COMPACT,
+    MBTK_RADIO_TECH_UTRAN,
+    MBTK_RADIO_TECH_GSM_EGPRS,
+    MBTK_RADIO_TECH_UTRAN_HSDPA,
+    MBTK_RADIO_TECH_UTRAN_HSUPA,
+    MBTK_RADIO_TECH_UTRAN_HSDPA_HSUPA,
+    MBTK_RADIO_TECH_E_UTRAN,      // LTE
+    MBTK_RADIO_TECH_UTRAN_HSPA
+} mbtk_radio_technology_enum;
+
+typedef enum {
+    MBTK_RADIO_STATE_UNKNOWN = -1,
+    MBTK_RADIO_STATE_MINI_FUNC = 0,
+    MBTK_RADIO_STATE_FULL_FUNC,
+    MBTK_RADIO_STATE_DIS_RECV_RF = 3,
+    MBTK_RADIO_STATE_DIS_RF,
+    MBTK_RADIO_STATE_DIS_SIM,
+    MBTK_RADIO_STATE_SEC_RX_OFF
+} mbtk_radio_state_enum;
+
+typedef enum {
+    MBTK_SIM_STATE_UNKNOWN = -1,
+    MBTK_SIM_STATE_ABSENT = 0,
+    MBTK_SIM_STATE_NOT_READY,
+    MBTK_SIM_STATE_READY,
+    MBTK_SIM_STATE_SIM_PIN,
+    MBTK_SIM_STATE_SIM_PUK,
+    MBTK_SIM_STATE_PH_SIMLOCK_PIN,
+    MBTK_SIM_STATE_PH_SIMLOCK_PUK,
+    MBTK_SIM_STATE_PH_FSIM_PIN,
+    MBTK_SIM_STATE_PH_FSIM_PUK,
+    MBTK_SIM_STATE_SIM_PIN2,
+    MBTK_SIM_STATE_SIM_PUK2,
+    MBTK_SIM_STATE_PH_NET_PIN,
+    MBTK_SIM_STATE_PH_NET_PUK,
+    MBTK_SIM_STATE_PH_NETSUB_PIN,
+    MBTK_SIM_STATE_PH_NETSUB_PUK,
+    MBTK_SIM_STATE_PH_SP_PIN,
+    MBTK_SIM_STATE_PH_SP_PUK,
+    MBTK_SIM_STATE_PH_CORP_PIN,
+    MBTK_SIM_STATE_PH_CORP_PUK
+} mbtk_sim_state_enum;
+
+
+typedef enum
+{
+    MBTK_NET_TYPE_UNKNOWN,
+    MBTK_NET_TYPE_GSM,
+    MBTK_NET_TYPE_UMTS,
+    MBTK_NET_TYPE_LTE
+} mbtk_net_type_enum;
+
+typedef enum
+{
+    MBTK_DEV_MODEM_MIN_FUN,                                   //Modem 最小功能
+    MBTK_DEV_MODEM_FULL_FUN,                                  //Modem 全功能
+    MBTK_DEV_MODEM_DISABLE_RECEIVE_RF_CIRCUITS = 3,           //Modem 禁用射频接收电路
+    MBTK_DEV_MODEM_DISABLE_TRANSMIT_AND_RECEIVE_RF_CIRCUITS,  //Modem禁用射频发射和接收电路
+    MBTK_DEV_MODEM_DISABLE_SIM,                               //Modem 禁用(U)SIM 卡
+    MBTK_DEV_MODEM_TURN_OFF_FULL_SECONDARY_RECEIVE,           //Modem 完全禁用辅助接收
+} MBTK_DEV_MODEM_FUNCTION;
+
+/*
+    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)
+*/
+typedef enum
+{
+    MBTK_NET_PREF_UNUSE = -1,
+    MBTK_NET_PREF_GSM_ONLY = 0,
+    MBTK_NET_PREF_UMTS_ONLY,
+    MBTK_NET_PREF_GSM_UMTS_AUTO,
+    MBTK_NET_PREF_GSM_UMTS_GSM_PREF,
+    MBTK_NET_PREF_GSM_UMTS_UMTS_PREF,
+    MBTK_NET_PREF_LTE_ONLY,
+    MBTK_NET_PREF_GSM_LTE_AUTO,
+    MBTK_NET_PREF_GSM_LTE_GSM_PREF,
+    MBTK_NET_PREF_GSM_LTE_LTE_PREF,
+    MBTK_NET_PREF_UMTS_LTE_AUTO,
+    MBTK_NET_PREF_UMTS_LTE_UMTS_PREF,
+    MBTK_NET_PREF_UMTS_LTE_LTE_PREF,
+    MBTK_NET_PREF_GSM_UMTS_LTE_AUTO,
+    MBTK_NET_PREF_GSM_UMTS_LTE_GSM_PREF,
+    MBTK_NET_PREF_GSM_UMTS_LTE_UMTS_PREF,
+    MBTK_NET_PREF_GSM_UMTS_LTE_LTE_PREF
+} mbtk_net_pref_enum;
+
+typedef struct
+{
+    /*
+    0: automatic
+    1: manual
+    */
+    uint8 net_sel_mode;
+    /*
+    0: GSM
+    1: GSM Compact
+    2: UTRAN
+    3: GSM w/EGPRS
+    4: UTRAN w/HSDPA
+    5: UTRAN w/HSUPA
+    6: UTRAN w/HSDPA and HSUPA
+    7: E-UTRAN
+    8: UTRAN HSPA+
+    0xFF: Unused
+    */
+    uint8 net_type;
+    //uint8 plmn[10]; // 46000
+    /*
+    0: unknown
+    1: available
+    2: current
+    3: forbidden
+    */
+    uint8 net_state;
+    uint32 plmn;
+} __attribute__((packed)) mbtk_net_info_t;
+
+typedef struct {
+    int num;
+    mbtk_net_info_t net_info[20];
+} mbtk_net_info_array_t;
+
+typedef struct
+{
+    mbtk_net_pref_enum net_pref;     // mbtk_net_pref_enum
+    uint32 gsm_band;    // mbtk_gsm_band_enum
+    uint32 umts_band;   // mbtk_umts_band_enum
+    uint32 tdlte_band;  // mbtk_tdlte_band_enum
+    uint32 fddlte_band; // mbtk_fddlte_band_enum
+    uint32 lte_ext_band; // mbtk_lte_ext_band_enum
+} __attribute__((packed)) mbtk_band_info_t;
+
+typedef enum
+{
+    MBTK_CELL_TYPE_GSM = 0,
+    MBTK_CELL_TYPE_UMTS,
+    MBTK_CELL_TYPE_LTE
+} mbtk_cell_type_enum;
+
+typedef struct {
+    bool valid;
+    uint32 IPAddr;
+    uint32 PrimaryDNS;
+    uint32 SecondaryDNS;
+    uint32 GateWay;
+    uint32 NetMask;
+} __attribute__((packed)) mbtk_ipv4_info_t;
+
+typedef struct {
+    bool valid;
+    uint32 IPV6Addr[4];
+    uint32 PrimaryDNS[4];
+    uint32 SecondaryDNS[4];
+    uint32 GateWay[4];
+    uint32 NetMask[4];
+} __attribute__((packed)) mbtk_ipv6_info_t;
+
+typedef struct {
+    mbtk_ipv4_info_t ipv4;
+    mbtk_ipv6_info_t ipv6;
+} __attribute__((packed)) mbtk_ip_info_t;
+
+typedef struct
+{
+    mbtk_radio_technology_enum type : 8; // mbtk_radio_technology_enum
+    uint8 rssi; // 0: 113 dBm or less
+                // 1: 111 dBm
+                // 2��30: 109��53 dBm
+                // 31: 51 dBm or greater
+                // 99: not known or not detectable
+    uint8 rxlev;// 0:rssi < -110 dBm
+                // 1: -110 dBm �� rssi < -109 dBm
+                // 2: -109 dBm �� rssi < -108 dBm
+                // ......
+                // 61: -50 dBm �� rssi < -49 dBm
+                // 62: -49 dBm �� rssi < -48 dBm
+                // 63: -48 dBm �� rssi
+                // 99: not known or not detectable
+    uint8 ber;  // 0...7 as RXQUAL values in the table in 3GPP TS 45.008 [20] subclause 8.2.4
+                // 99 not known or not detectable
+    uint8 rscp; // 0: rscp < -120 dBm
+                // 1: -120 dBm �� rscp < -119 dBm
+                // 2: -119 dBm �� rscp < -118 dBm
+                // ......
+                // 94: -27 dBm �� rscp < -26 dBm
+                // 95: -26 dBm �� rscp < -25 dBm
+                // 96: - 25 dBm �� rscp
+                // 255: not known or not detectable
+    uint8 ecno; // 0: Ec/Io < -24 dB
+                // 1: -24 dB �� Ec/Io < -23.5 dB
+                // 2: -23.5 dB �� Ec/Io < -23 dB
+                // ......
+                // 47: -1 dB �� Ec/Io < -0.5 dB
+                // 48: -0.5 dB �� Ec/Io < 0 dB
+                // 49: 0 dB �� Ec/Io
+                // 255: not known or not detectable
+    uint8 rsrq; // 0: rsrq < -19.5 dB
+                // 1: -19.5 dB �� rsrq < -19 dB
+                // 2: -19 dB �� rsrq < -18.5 dB
+                // ......
+                // 32: -4 dB �� rsrq < -3.5 dB
+                // 33: -3.5 dB �� rsrq < -3 dB
+                // 34: -3 dB �� rsrq
+                // 255: not known or not detectable
+    uint8 rsrp; // 0: rsrp < -140 dBm
+                // 1: -140 dBm �� rsrp < -139 dBm
+                // 2: -139 dBm �� rsrp < -138 dBm
+                // ......
+                // 95: -46 dBm �� rsrp < -45 dBm
+                // 96: -45 dBm �� rsrp < -44 dBm
+                // 97: -44 dBm �� rsrp
+                // 255: not known or not detectable
+} __attribute__((packed)) mbtk_signal_info_t;
+
+
+typedef enum {
+    MBTK_DATA_CALL_STOP = 0,    // Stop data call.
+    MBTK_DATA_CALL_START,       // Start data call.
+    MBTK_DATA_CALL_STATE        // Get data call state
+} mbtk_data_call_type_enum;
+
+/*
+0: not registered, MT is not currently searching a new operator to register to
+1: registered, home network
+2: not registered, but MT is currently searching a new operator to register to
+3: registration denied
+4: unknown
+5: registered, roaming
+6: registered, home network, SMS-only (applicable only when AcT is E-UTRAN)
+7: registered, roaming, SMS-only (applicable only when AcT is E-UTRAN)
+8: attached for emergency bearer services only (not applicable)
+9: registered for ��CSFB not preferred��,home network(applicable only when AcT is E-UTRAN)
+10: registered for ��CSFB not preferred��,roaming(applicable only when AcT is E-UTRAN)
+11: only emergency services are available
+*/
+typedef enum
+{
+    MBTK_NET_REG_STATE_NON = 0,
+    MBTK_NET_REG_STATE_HOME,
+    MBTK_NET_REG_STATE_SEARCHING,
+    MBTK_NET_REG_STATE_DENIED,
+    MBTK_NET_REG_STATE_UNKNOWN,
+    MBTK_NET_REG_STATE_ROAMING,
+    MBTK_NET_REG_STATE_SMS_ONLY,
+    MBTK_NET_REG_STATE_ROAMING_SMS,
+    MBTK_NET_REG_STATE_ATTACHED_EMERGENCY,
+    MBTK_NET_REG_STATE_CSFB_HOME,
+    MBTK_NET_REG_STATE_CSFB_ROAMING,
+    MBTK_NET_REG_STATE_EMERGENCY_ONLY
+} mbtk_net_reg_state_enum;
+
+typedef struct
+{
+    mbtk_net_reg_state_enum call_state : 8;// mbtk_net_reg_state_enum
+    mbtk_net_reg_state_enum data_state : 8;// mbtk_net_reg_state_enum
+    mbtk_net_reg_state_enum ims_state : 8;// mbtk_net_reg_state_enum
+    mbtk_radio_technology_enum type : 8; // mbtk_radio_technology_enum
+    uint16 lac;
+    uint32 ci;
+} __attribute__((packed)) mbtk_net_reg_info_t;
+
+typedef enum {
+	MBTK_APN_AUTH_PROTO_DEFAULT = 0,
+	MBTK_APN_AUTH_PROTO_NONE,
+	MBTK_APN_AUTH_PROTO_PAP,
+	MBTK_APN_AUTH_PROTO_CHAP,
+#if 0
+	MBTK_APN_AUTH_PROTO_PAP_CHAP,
+    //NOT SUPPORT
+#endif
+} mbtk_apn_auth_type_enum;
+
+typedef struct {
+    mbtk_ril_cid_enum cid : 8; // 1 - 7
+    mbtk_ip_type_enum ip_type : 8; // mbtk_ip_type_enum
+    mbtk_apn_auth_type_enum auth : 8;
+    uint8 auto_save;
+    uint8 auto_boot_call;
+    uint8 def_route;
+    uint8 apn[APN_STR_MAX];
+    uint8 user[APN_STR_MAX];
+    uint8 pass[APN_STR_MAX];
+} mbtk_apn_info_t;
+
+typedef struct {
+    mbtk_ril_cid_enum cid : 8; // 1 - 7
+    mbtk_ip_type_enum ip_type : 8; // mbtk_ip_type_enum
+    mbtk_apn_auth_type_enum auth : 8;
+    uint8 auto_save;
+    uint8 auto_boot_call;
+    uint8 apn[APN_STR_MAX];
+} mbtk_apn_get_info_t;
+
+typedef struct {
+    mbtk_ril_cid_enum cid_for_def_route;
+
+    int num;
+    mbtk_apn_get_info_t apns[MBTK_APN_CID_MAX];
+} mbtk_apn_info_array_t;
+
+typedef enum {
+    MBTK_SIM = 0,
+    MBTK_USIM = 1,
+    MBTK_TEST_SIM = 2,
+    MBTK_TEST_USIM = 3,
+    MBTK_UNKNOWN = 4,
+} mbtk_sim_card_type_enum;
+
+typedef struct
+{
+    uint8 p1_retry;
+    uint8 p2_retry;
+    uint8 puk1_retry;
+    uint8 puk2_retry;
+} mbtk_pin_puk_last_times_t;
+
+typedef enum {
+    MBTK_SIM_LOCK_TYPE_DISABLE = 0,     // Disable sim lock: [PIN]
+    MBTK_SIM_LOCK_TYPE_ENABLE,      // Enable sim lock: [PIN]
+    // MBTK_SIM_LOCK_TYPE_QUERY,       // Query sim lock state.
+    MBTK_SIM_LOCK_TYPE_CHANGE = 3,      // Change pin : [old PIN][new PIN]
+    MBTK_SIM_LOCK_TYPE_VERIFY_PIN,  // Verify pin : [PIN]
+    MBTK_SIM_LOCK_TYPE_VERIFY_PUK   // Verify puk : [PUK][new PIN]
+} mbtk_sim_lock_type_enum;
+
+typedef struct {
+    mbtk_sim_lock_type_enum type : 8;
+    uint8 pin1[RIL_PIN_STR_MAX];
+    uint8 pin2[RIL_PIN_STR_MAX];
+    uint8 puk[RIL_PIN_STR_MAX];
+} mbtk_sim_lock_info_t;
+
+typedef struct
+{
+    uint8 format;
+    char name[16];
+}MBTK_SIM_PLMN_INFO_C;  //string type
+
+typedef struct
+{
+    uint8 count;
+    MBTK_SIM_PLMN_INFO_C plmn[24];
+} mbtk_plmn_info;
+
+typedef struct
+{
+    // LTE server cell: tac, PCI, dlEuarfcn, ulEuarfcn, band
+    // LTE cell: phyCellId,euArfcn,rsrp,rsrq
+    // WCDMA server cell: lac, ci, arfcn
+    // WCDMA cell: lac, ci, arfcn
+    // GSM server cell: lac, ci, arfcn, bsic
+    // GSM cell:
+    mbtk_cell_type_enum type : 8;
+    uint32 value1;
+    uint32 value2;
+    uint32 value3;
+    uint32 value4;
+    uint32 value5;
+	uint32 value6;
+    uint32 value7;
+    uint32 value8;
+    uint32 value9;
+    uint32 value10;
+} __attribute__((packed)) mbtk_cell_info_t;
+
+typedef struct {
+    int num;
+    mbtk_cell_info_t cell[10];
+} mbtk_cell_info_array_t;
+
+typedef struct {
+    mbtk_data_call_type_enum type : 8;
+    mbtk_ril_cid_enum cid : 8;  // 1 - 7
+    uint8 auto_boot_call;       // Will reset proc if necessary.
+    uint8 def_route;            // Will reset proc if necessary.
+    uint16 retry_interval;      // second
+    uint16 timeout;             // second
+} mbtk_data_call_info_t;
+
+typedef struct
+{
+    uint8 call_wait;
+    uint8 dir1;
+    uint8 dir;
+    uint8 state;
+    uint8 mode;
+    uint8 mpty;
+    char phone_number[100];
+    uint8 type;
+    uint8 pas;
+    uint8 disconnected_id;
+} __attribute__((packed)) mbtk_call_info_t;
+
+typedef struct
+{
+    char character;
+    uint32 duration;
+} __attribute__((packed)) mbtk_call_dtmf_info_t;
+
+
+mbtk_ril_err_enum mbtk_ril_init();
+
+mbtk_ril_err_enum mbtk_ril_deinit();
+
+/*
+* Get platform version.
+*/
+mbtk_ril_err_enum mbtk_version_get(void *version);
+
+/*
+* Get platform model.
+*/
+mbtk_ril_err_enum mbtk_model_get(void *model);
+
+/*
+* Get platform IMEI.
+*/
+mbtk_ril_err_enum mbtk_imei_get(void *imei);
+
+/*
+* Get platform SN.
+*/
+mbtk_ril_err_enum mbtk_sn_get(void *sn);
+
+/*
+* Get platform MEID.
+*/
+mbtk_ril_err_enum mbtk_meid_get(void *meid);
+
+/*
+* Return VoLTE state.
+*/
+mbtk_ril_err_enum mbtk_volte_state_get(int *volte_state);
+
+/*
+* Set VoLTE state.
+*
+* volte_state:
+* 0 : Close VoLTE.
+* 1 : Open VoLTE.
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_volte_state_set(int volte_state);
+
+/*
+* Return radio state.
+*/
+mbtk_ril_err_enum mbtk_radio_state_get(mbtk_radio_state_enum *radio_state);
+
+/*
+* Set radio state.
+*
+* Refor to : mbtk_radio_state_enum
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_radio_state_set(mbtk_radio_state_enum radio_state, bool reset_modem);
+
+/*
+* Get system temperature.
+*
+* type[IN]:
+*   0: Soc temperature.
+*   1: RF temperature.
+* temp[OUT]:
+*   temperature in celsius.
+*/
+mbtk_ril_err_enum mbtk_temp_get(mbtk_temp_type_enum type, int* temp);
+
+/*
+* Get time type.
+* "23/05/24,06:09:32+32" -> "23/05/24 06:09:32 +32 00"
+*/
+mbtk_ril_err_enum mbtk_cell_time_get(char* time_str);
+
+/*
+* Get platform IMSI.
+*/
+mbtk_ril_err_enum mbtk_imsi_get(void *imsi);
+
+/*
+* Get platform ICCID.
+*/
+mbtk_ril_err_enum mbtk_iccid_get(void *iccid);
+
+/*
+* Get current phone number.
+*/
+mbtk_ril_err_enum mbtk_phone_number_get(void *phone_number);
+
+/*
+* Get platform ICCID.
+*/
+mbtk_ril_err_enum mbtk_sim_lock_get(int *lock_state);
+
+/*
+* Get platform ICCID.
+*/
+mbtk_ril_err_enum mbtk_sim_lock_set(mbtk_sim_lock_info_t *lock_info);
+
+/*
+* Get platform ICCID.
+*/
+mbtk_ril_err_enum mbtk_sim_lock_retry_times_get(mbtk_pin_puk_last_times_t *retry_times);
+
+/*
+* Get available network.
+*/
+mbtk_ril_err_enum mbtk_available_net_get(mbtk_net_info_array_t *net_array);
+
+/*
+* Set network select mode. (+COPS=...)
+*/
+mbtk_ril_err_enum mbtk_net_sel_mode_set(const mbtk_net_info_t *net);
+
+/*
+* Get network select mode. (+COPS?)
+*/
+mbtk_ril_err_enum mbtk_net_sel_mode_get(mbtk_net_info_t *net);
+
+/*
+* Get platform support bands.
+*/
+mbtk_ril_err_enum mbtk_support_band_get(mbtk_band_info_t *band);
+
+/*
+* Get platform current bands.
+*/
+mbtk_ril_err_enum mbtk_current_band_get(mbtk_band_info_t *band);
+
+/*
+* Set platform current bands.
+*/
+mbtk_ril_err_enum mbtk_current_band_set(const mbtk_band_info_t *band);
+
+/*
+* Get current cell infomation.
+*/
+mbtk_ril_err_enum mbtk_cell_get(mbtk_cell_info_array_t *cell_list);
+
+/*
+* Set AT*CELL.
+*/
+mbtk_ril_err_enum mbtk_cell_set(const mbtk_cell_info_t *cell);
+
+/*
+* Get current APN informations.
+*/
+mbtk_ril_err_enum mbtk_apn_get(mbtk_apn_info_array_t *apns);
+
+/*
+* Set current APN informations.
+*/
+mbtk_ril_err_enum mbtk_apn_set(const mbtk_apn_info_t *apn);
+
+/*
+* Start data call.
+*/
+mbtk_ril_err_enum mbtk_data_call_start(mbtk_ril_cid_enum cid, bool auto_boot_call,
+            bool def_route, int retry_interval, int timeout, mbtk_ip_info_t *rsp_info);
+
+/*
+* Stop data call.
+*/
+mbtk_ril_err_enum mbtk_data_call_stop(mbtk_ril_cid_enum cid, int timeout);
+
+/*
+* Get data call state.
+*/
+mbtk_ril_err_enum mbtk_data_call_state_get(int cid, mbtk_ip_info_t *ip);
+
+/*
+* Get current network signal.
+*/
+mbtk_ril_err_enum mbtk_net_signal_get(mbtk_signal_info_t *signal);
+
+/*
+* Get current network register information.
+*/
+mbtk_ril_err_enum mbtk_net_reg_get(mbtk_net_reg_info_t *reg);
+
+
+/*
+* Return sms cmgf.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgf_get(int *volte_state);
+
+/*
+* Set sms cmgf.
+*
+* volte_state:
+* 0 : PDU mode.
+* 1 :  text mode.
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgf_set(int mode);
+
+/*
+* Set sms cmgs.
+*
+if PDU mode (+CMGF=0):
++CMGS=<length><CR>
+PDU is given<ctrl-Z/ESC>
+
+if text mode (+CMGF=1):
++CMGS=<da>[,<toda>]<CR>
+text is entered<ctrl-Z/ESC>
+
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgs_set(char * cmgs, char *resp);
+
+/*
+* Set sms cmgw.
+*
+if text mode (+CMGF=1):
++CMGW=<oa/da>[,<tooa/toda>[,<stat>]]
+<CR>
+text is entered<ctrl-Z/ESC>
+if PDU mode (+CMGF=0):
++CMGW=<length>[,<stat>]<CR>PDU is
+given<ctrl-Z/ESC>
+
+*/
+mbtk_ril_err_enum mbtk_sms_cmgw_set(char * cmgw, char *resp);
+
+/*
+* Set sms cmgd.
+*
+* +CMGD=<index>[,<delflag>]
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgd_set(char * cmdg);
+
+/*
+* Set sms cmgl.
+*
+* AT+CMGL[=<stat>]
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgl_set(char * cmgl, char *resp);
+
+/*
+* Return sms csca.
+*/
+mbtk_ril_err_enum mbtk_sms_csca_get(char *buf);
+
+/*
+* Set sms csca.
+*
+* AT+CSCA=<number> [,<type>]
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_csca_set(char * csca);
+
+/*
+* Set sms csmp.
+*
+* AT+CSMP=[<fo>[,<vp>[,<pid>[,<dcs>]]]]
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_csmp_set(char * csmp);
+
+/*
+* Set sms cscb.
+*
+* AT+CSCB=<[<mode>[,<mids>[,<dcss>]]]>
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cscb_set(char * cscb);
+
+/*
+* Set sms cnmi.
+*
+at+cnmi=1,2
+
+OK
+if sending fails:
++CMS ERROR: <err>
+*/
+mbtk_ril_err_enum mbtk_sms_cnmi_set();
+
+/*
+* Set sms cmss.
+*
++CMSS=<index>[,<da>[,<toda>]]
+
+if sending successful:
++CMSS: <mr>
+OK
+if sending fails:
++CMS ERROR: <err>
+*/
+mbtk_ril_err_enum mbtk_sms_cmss_set(char * cmss, char *resp);
+
+/*
+* Return sms cmgf.
+*/
+mbtk_ril_err_enum mbtk_sms_cpms_get(char * mem);
+
+/*
+* Set sms cpms.
+*
+* AT+CPMS=<mem1>[,<mem2>[,<mem3>]]
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cpms_set(char * mem, char* response);
+
+/*
+* Set sms cm.
+*
+* +CMGR=<index>
+
+if PDU mode (+CMGF=0) ��command successful:
++CMGR: <stat>,[<alpha>],<length><CR><LF><pdu>
+OK
+if text mode (+CMGF=1), command successful and SMS-DELIVER:
++CMGR:<stat>,<oa>,[<alpha>],<scts>[,<tooa>,<fo>,<pid>,<dcs
+>, <sca>,<tosca>,<length>]<CR><LF><data>
+OK
+if text mode (+CMGF=1), command successful and SMS-SUBMIT:
++CMGR:
+<stat>,<da>,[<alpha>][,<toda>,<fo>,<pid>,<dcs>,[<vp>],
+<sca>,<tosca>,<length>]<CR><LF><data>
+OK
+otherwise:
++CMS ERROR: <err>
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgr_set(int index, char *resp);
+
+/*
+* Get sim state.
+*/
+mbtk_ril_err_enum mbtk_sim_state_get(mbtk_sim_state_enum *sim_state);
+
+/*
+* Get sim card type.
+*/
+mbtk_ril_err_enum mbtk_sim_type_get(mbtk_sim_card_type_enum *sim_card_type);
+
+/*
+* Get plmn list
+*/
+mbtk_ril_err_enum mbtk_plmn_list_get(mbtk_plmn_info *plmn_list);
+
+/*
+* call_start
+*
+*/
+mbtk_ril_err_enum mbtk_call_start(char* phone_number);
+
+/*
+* Answer the phone call.
+*
+*/
+mbtk_ril_err_enum mbtk_call_answer();
+
+/*
+* Hang up all call.
+*
+*/
+mbtk_ril_err_enum mbtk_call_hang();
+
+/*
+* Hang up a call.
+*
+*/
+mbtk_ril_err_enum mbtk_a_call_hang(int phone_id);
+
+/*
+* Hang up waiting or background call.
+*
+*/
+mbtk_ril_err_enum mbtk_waiting_or_background_call_hang();
+
+/*
+* Hang up foreground resume background call.
+*
+*/
+mbtk_ril_err_enum mbtk_foreground_resume_background_call_hang();
+
+/*
+* Get current call phone number.
+*/
+mbtk_ril_err_enum mbtk_call_reg_get(mbtk_call_info_t *reg);
+
+/*
+* Return mute state.
+*/
+mbtk_ril_err_enum mbtk_mute_state_get(int *mute_state);
+
+/*
+* Set mute state.
+*
+* mute_state:
+* 0 : of mute.
+* 1 : on mute.
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_mute_state_set(int mute_state);
+
+/*
+* System power.
+* type:
+* 0: Reboot system.
+* 1: Poweroff system.
+* 2: Halt system.
+*/
+int mbtk_system_reboot(int type);
+
+/*
+* Get time type.
+*/
+int mbtk_time_get(int *time_type);
+
+/*
+* Get net time.
+*/
+int mbtk_net_time_get(char* time_str);
+
+/*
+* Absolute time conversion
+*/
+int mbtk_get_abs_time(char *time_str, time_t *time_out);
+
+/*
+* Set pdp state change callback function.
+*/
+int mbtk_pdp_state_change_cb_reg(mbtk_ril_callback_func cb);
+
+/*
+* Set network state change callback function.
+*/
+int mbtk_net_state_change_cb_reg(mbtk_ril_callback_func cb);
+
+/*
+* Set call state change callback function.
+*/
+int mbtk_call_state_change_cb_reg(mbtk_ril_callback_func cb);
+
+/*
+* Set sms state change callback function.
+*/
+int mbtk_sms_state_change_cb_reg(mbtk_ril_callback_func cb);
+
+/*
+* Set radio state change callback function.
+*/
+int mbtk_radio_state_change_cb_reg(mbtk_ril_callback_func cb);
+
+/*
+* Set sim state change callback function.
+*/
+int mbtk_sim_state_change_cb_reg(mbtk_ril_callback_func cb);
+
+/*
+* Set signal state change callback function.
+*/
+int mbtk_signal_state_change_cb_reg(mbtk_ril_callback_func cb);
+
+
+#endif /* _MBTK_INFO_API_2_H */
+
diff --git a/mbtk/libmbtk_ril_v2/Makefile b/mbtk/libmbtk_ril_v2/Makefile
new file mode 100755
index 0000000..617a549
--- /dev/null
+++ b/mbtk/libmbtk_ril_v2/Makefile
@@ -0,0 +1,36 @@
+BUILD_ROOT = $(shell pwd)/..
+include $(BUILD_ROOT)/Make.defines
+
+LOCAL_PATH=$(BUILD_ROOT)/libmbtk_ril_v2
+
+INC_DIR +=
+
+LIB_DIR +=
+
+LIBS += -llog -lmbtk_lib -lmbtk_net
+
+CFLAGS += -shared -Wl,-shared,-Bsymbolic
+
+LOCAL_SRC_FILES = $(wildcard src/*.cpp) $(wildcard src/*.c)
+OBJS = $(patsubst %.c, %.o, $(LOCAL_SRC_FILES))
+$(info OBJS = $(OBJS))
+
+OBJS = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(LOCAL_SRC_FILES)))
+$(info OBJS = $(OBJS))
+
+dtarget := $(OUT_DIR)/lib/libmbtk_ril.so
+
+all: $(dtarget)
+
+$(dtarget):$(OBJS)
+	$(CC) $(CFLAGS) $(DEFINE) $(LIB_DIR) $(LIBS) $(OBJS) -o $@
+
+%.o:%.c
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+%.o:%.cpp
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+clean:
+	rm -f $(OBJS) $(dtarget)
+
diff --git a/mbtk/libmbtk_ril_v2/inc/mbtk_alphabet.h b/mbtk/libmbtk_ril_v2/inc/mbtk_alphabet.h
new file mode 100755
index 0000000..1ffece7
--- /dev/null
+++ b/mbtk/libmbtk_ril_v2/inc/mbtk_alphabet.h
@@ -0,0 +1,140 @@
+//
+// Created by hitmoon on 15-12-10.
+//
+
+
+struct map_node {
+    unsigned short key;
+    unsigned short value;
+};
+
+
+#define map_size(map) (sizeof(map) / sizeof(struct map_node))
+
+
+// Unicode编码到GSM编码转换
+struct map_node UCS2ToBIT7[] = {
+        {0x000C, 0x1B0A},
+        {0x0024, 0x0002},
+        {0x0040, 0x0000},
+        {0x005B, 0x1B3C},
+        {0x005C, 0x1B2F},
+        {0x005D, 0x1B3E},
+        {0x005E, 0x1B14},
+        {0x005F, 0x0011},
+        {0x007B, 0x1B28},
+        {0x007C, 0x1B40},
+        {0x007D, 0x1B29},
+        {0x007E, 0x1B3D},
+        {0x00A0, 0x001B},
+        {0x00A1, 0x0040},
+        {0x00A3, 0x0001},
+        {0x00A4, 0x0024},
+        {0x00A5, 0x0003},
+        {0x00A7, 0x005F},
+        {0x00BF, 0x0060},
+        {0x00C4, 0x005B},
+        {0x00C5, 0x000E},
+        {0x00C6, 0x001C},
+        {0x00C9, 0x001F},
+        {0x00D1, 0x005D},
+        {0x00D6, 0x005C},
+        {0x00D8, 0x000B},
+        {0x00DC, 0x005E},
+        {0x00DF, 0x001E},
+        {0x00E0, 0x007F},
+        {0x00E4, 0x007B},
+        {0x00E5, 0x000F},
+        {0x00E6, 0x001D},
+        {0x00E7, 0x0009},
+        {0x00E8, 0x0004},
+        {0x00E9, 0x0005},
+        {0x00EC, 0x0007},
+        {0x00F1, 0x007D},
+        {0x00F2, 0x0008},
+        {0x00F6, 0x007C},
+        {0x00F8, 0x000C},
+        {0x00F9, 0x0006},
+        {0x00FC, 0x007E},
+        {0x0393, 0x0013},
+        {0x0394, 0x0010},
+        {0x0398, 0x0019},
+        {0x039B, 0x0014},
+        {0x039E, 0x001A},
+        {0x03A0, 0x0016},
+        {0x03A3, 0x0018},
+        {0x03A6, 0x0012},
+        {0x03A8, 0x0017},
+        {0x03A9, 0x0015},
+        {0x20AC, 0x1B65}
+};
+
+// GSM编码到Unicode编码转换
+struct map_node BIT7ToUCS2[] = {
+        {0x0000, 0x0040},
+        {0x0001, 0x00A3},
+        {0x0002, 0x0024},
+        {0x0003, 0x00A5},
+        {0x0004, 0x00E8},
+        {0x0005, 0x00E9},
+        {0x0006, 0x00F9},
+        {0x0007, 0x00EC},
+        {0x0008, 0x00F2},
+        {0x0009, 0x00E7},
+        {0x000B, 0x00D8},
+        {0x000C, 0x00F8},
+        {0x000E, 0x00C5},
+        {0x000F, 0x00E5},
+        {0x0010, 0x0394},
+        {0x0011, 0x005F},
+        {0x0012, 0x03A6},
+        {0x0013, 0x0393},
+        {0x0014, 0x039B},
+        {0x0015, 0x03A9},
+        {0x0016, 0x03A0},
+        {0x0017, 0x03A8},
+        {0x0018, 0x03A3},
+        {0x0019, 0x0398},
+        {0x001A, 0x039E},
+        {0x001B, 0x00A0},
+        {0x001C, 0x00C6},
+        {0x001D, 0x00E6},
+        {0x001E, 0x00DF},
+        {0x001F, 0x00C9},
+        {0x0024, 0x00A4},
+        {0x0040, 0x00A1},
+        {0x005B, 0x00C4},
+        {0x005C, 0x00D6},
+        {0x005D, 0x00D1},
+        {0x005E, 0x00DC},
+        {0x005F, 0x00A7},
+        {0x0060, 0x00BF},
+        {0x007B, 0x00E4},
+        {0x007C, 0x00F6},
+        {0x007D, 0x00F1},
+        {0x007E, 0x00FC},
+        {0x007F, 0x00E0}
+};
+// GSM编码转义序列到Unicode编码转换
+struct map_node BIT7EToUCS2[] = {
+        {0x000A, 0x000C},
+        {0x0014, 0x005E},
+        {0x0028, 0x007B},
+        {0x0029, 0x007D},
+        {0x002F, 0x005C},
+        {0x003C, 0x005B},
+        {0x003D, 0x007E},
+        {0x003E, 0x005D},
+        {0x0040, 0x007C},
+        {0x0065, 0x20AC}
+};
+
+// map 中查询键值
+int32_t map_get_value(struct map_node *map, unsigned int size, unsigned short key) {
+	int i = 0;
+    for (i = 0; i < size; i++) {
+        if (map[i].key == key)
+            return map[i].value;
+    }
+    return -1;
+}
diff --git a/mbtk/libmbtk_ril_v2/inc/mbtk_ril.h b/mbtk/libmbtk_ril_v2/inc/mbtk_ril.h
new file mode 100755
index 0000000..9303e26
--- /dev/null
+++ b/mbtk/libmbtk_ril_v2/inc/mbtk_ril.h
@@ -0,0 +1,355 @@
+#ifndef MBTK_INFO_INCLUDE
+#define MBTK_INFO_INCLUDE
+#include <netinet/in.h>
+#include <pthread.h>
+
+#include "mbtk_type.h"
+#include "mbtk_list.h"
+#include "mbtk_log.h"
+#include "mbtk_utils.h"
+#include "mbtk_ril_api.h"
+
+#define RIL_SOCK_PACKET_TAG 0x5F6F7F8F
+#define RIL_SOCK_NAME "/tmp/mbtk_ril_sock"
+#define RIL_SOCK_MSG_LEN_MAX 2048
+
+// Tag(4) + Packet_Length(2)
+#define RIL_SOCK_PACK_EXTRA_LEN 6
+// RIL_SOCK_PACK_EXTRA_LEN + Index(2) + Type(2) + Id(2) + Error(2) + data_len(2)
+#define RIL_SOCK_PACK_LEN_MIN (RIL_SOCK_PACK_EXTRA_LEN + 10)
+
+#define RIL_MSG_INDEX_AUTO      (-1)         // automatically , refor to :  ril_index
+#define RIL_MSG_INDEX_INVALID   (0)       // Invalid msg index.
+
+typedef enum
+{
+    RIL_MSG_TYPE_REQ,
+    RIL_MSG_TYPE_RSP,
+    RIL_MSG_TYPE_IND
+} ril_msg_type_enum;
+
+typedef enum
+{
+    // Device Information
+    RIL_MSG_ID_DEV_BEGIN = 0,
+    // <string> IMEI
+    RIL_MSG_ID_DEV_IMEI,
+    // <string> SN
+    RIL_MSG_ID_DEV_SN,
+    // <string> MEID
+    RIL_MSG_ID_DEV_MEID,
+    // <string> VERSION
+    RIL_MSG_ID_DEV_VERSION,
+    // <string> MODEL
+    RIL_MSG_ID_DEV_MODEL,
+    // <uint8> 0:Close 1:Open
+    RIL_MSG_ID_DEV_VOLTE,
+    // <string> Temperature
+    RIL_MSG_ID_DEV_TEMP,  // Temperature
+    // <string>  23/03/20,01:58:00+32
+    RIL_MSG_ID_DEV_CELL_TIME,  // Time
+    // <uint8><uint8>
+    RIL_MSG_ID_DEV_MODEM,
+
+    RIL_MSG_ID_DEV_END,
+
+    // Sim Information
+    RIL_MSG_ID_SIM_BEGIN = 1000,
+    // <uint8> 0:NOT_EXIST 1:READY ...
+    RIL_MSG_ID_SIM_STATE,
+    // <uint8> 0: SIM 1: USIM 2: TEST SIM 3: TEST USIM 4: UNKNOWN
+    RIL_MSG_ID_SIM_TYPE,
+    // <string> IMSI
+    RIL_MSG_ID_SIM_IMSI,
+    // <string> ICCID
+    RIL_MSG_ID_SIM_ICCID,
+    // <string> Phone Number
+    RIL_MSG_ID_SIM_PN,
+    // <string> PUK
+    RIL_MSG_ID_SIM_LOCK,
+    // <uint8> <uint8> <uint8> <uint8> PIN PUK LAST TIMES
+    RIL_MSG_ID_SIM_PINPUK_TIMES,
+    // <string> PLMN
+    RIL_MSG_ID_SIM_PLMN,
+
+    RIL_MSG_ID_SIM_END,
+
+    // Network Information
+    RIL_MSG_ID_NET_BEGIN = 2000,
+    // sel_mode(uint8)type(uint8)plmn(uint32)...sel_mode(uint8)type(uint8)plmn(uint32)
+    RIL_MSG_ID_NET_AVAILABLE,
+    // <uint8> 0: automatic 1: manual
+    // or
+    // sel_mode(uint8)type(uint8)plmn(uint32)
+    RIL_MSG_ID_NET_SEL_MODE,
+    // mbtk_band_info_t
+    RIL_MSG_ID_NET_BAND,
+    // mbtk_signal_info_t
+    RIL_MSG_ID_NET_SIGNAL,
+    // mbtk_net_reg_info_t
+    RIL_MSG_ID_NET_REG,
+    // mbtk_cell_info_t[]
+    RIL_MSG_ID_NET_CELL,
+    // mbtk_apn_info_t
+    RIL_MSG_ID_NET_APN,
+    // REQ:
+    // <call_type[1]><cid[1]><timeout[1]>
+    //  call_type : mbtk_data_call_type_enum
+    //  cid : 1 - 15
+    //  timeout : second
+    // RSP:
+    //  <type[1]><ipv4><ipv6>
+    //  type : 0-IPV4   1-IPV6  2-IPV4V6
+    //  ipv4 : mbtk_ipv4_info_t
+    //  ipv6 : mbtk_ipv6_info_t
+    RIL_MSG_ID_NET_DATA_CALL,
+
+    RIL_MSG_ID_NET_END,
+
+
+    // Call Information
+    RIL_MSG_ID_CALL_BEGIN = 3000,
+    RIL_MSG_ID_CALL_STATE,
+
+    // Start call.
+    RIL_MSG_ID_CALL_START,
+    //answer call
+    RIL_MSG_ID_CALL_ANSWER,
+    //hang up all call
+    RIL_MSG_ID_CALL_HANGUP,
+    //hang up a call
+    RIL_MSG_ID_CALL_HANGUP_A,
+    //hang up waiting or background call
+    RIL_MSG_ID_CALL_HANGUP_B,
+    //hang up foreground resume background
+    RIL_MSG_ID_CALL_HANGUP_C,
+    //wait in call
+    RIL_MSG_ID_CALL_WAITIN,
+    //mute call
+    RIL_MSG_ID_CALL_MUTE,
+    //dtmf call
+    RIL_MSG_ID_CALL_DTMF,
+    RIL_MSG_ID_CALL_END,
+
+    // SMS Information
+    RIL_MSG_ID_SMS_BEGIN = 4000,
+    RIL_MSG_ID_SMS_STATE,
+    RIL_MSG_ID_SMS_CMGF,
+    RIL_MSG_ID_SMS_CPMS,
+    RIL_MSG_ID_SMS_CMGS,
+    RIL_MSG_ID_SMS_CMSS,
+    RIL_MSG_ID_SMS_CMGR,
+    RIL_MSG_ID_SMS_CMGW,
+    RIL_MSG_ID_SMS_CMGD,
+    RIL_MSG_ID_SMS_CMGL,
+    RIL_MSG_ID_SMS_CSCA,
+    RIL_MSG_ID_SMS_CSMP,
+    RIL_MSG_ID_SMS_CSCB,
+    RIL_MSG_ID_SMS_CNMI,
+
+    RIL_MSG_ID_SMS_END,
+
+    // PhoneBook Information
+    RIL_MSG_ID_PB_BEGIN = 5000,
+    RIL_MSG_ID_PB_STATE,
+
+    RIL_MSG_ID_PB_END,
+
+    // IND Information
+    RIL_MSG_ID_IND_BEGIN = 10000,
+    // NULL
+    RIL_MSG_ID_IND_SER_READY,
+    // <uint8>  State
+    RIL_MSG_ID_IND_NET_STATE_CHANGE,
+    // <uint8>  State
+    RIL_MSG_ID_IND_CALL_STATE_CHANGE,
+    // <uint8>  State
+    RIL_MSG_ID_IND_SMS_STATE_CHANGE,
+    // <uint8>  State
+    RIL_MSG_ID_IND_RADIO_STATE_CHANGE,
+    // <uint8>  State
+    RIL_MSG_ID_IND_SIM_STATE_CHANGE,
+    // <uint8>  State
+    RIL_MSG_ID_IND_PDP_STATE_CHANGE,
+    // <uint8> State
+    RIL_MSG_ID_IND_SIGNAL_STATE_CHANGE,
+
+
+    RIL_MSG_ID_IND_END,
+    RIL_MSG_ID_UNKNOWN        // Unknown information.
+} ril_msg_id_enum;
+
+typedef struct {
+    uint32 tag;     // Refor to : RIL_SOCK_PACKET_TAG
+    uint16 msg_len;
+
+    uint16 msg_index;   // Message index(Start from 1)
+            // 0 : For unknown msg id
+    uint16 msg_type;    // Refor to : ril_msg_type_enum
+    uint16 msg_id;      // Refor to : ril_msg_id_enum
+    uint16 err;     // Only for RSP(Refor to : mbtk_ril_err_enum)
+    uint16 data_len;
+    uint8 *data;
+} __attribute__((packed)) ril_msg_pack_info_t;
+
+typedef struct {
+    pthread_t pid;
+    char name[20];
+    bool is_waitting;
+    pthread_cond_t cond;
+    pthread_mutex_t mutex;
+} ril_cli_thread_info_t;
+
+typedef struct {
+    pthread_t pid;
+    bool is_async;
+    int *rsp_data_len;  // Save response data length.
+    char *rsp_data;     // Save response date.
+    int *rsp_err;       // Save response error, refor to mbtk_ril_err_enum .
+    ril_msg_pack_info_t *pack;
+} ril_msg_info_t;
+
+/*
+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
+*/
+typedef enum
+{
+    MBTK_GSM_BAND_PGSM_900 = 1,
+    MBTK_GSM_BAND_DCS_GSM_1800 = 2,
+    MBTK_GSM_BAND_PCS_GSM_1900 = 4,
+    MBTK_GSM_BAND_EGSM_900 = 8,
+    MBTK_GSM_BAND_GSM_450 = 16,
+    MBTK_GSM_BAND_GSM_480 = 32,
+    MBTK_GSM_BAND_GSM_850 = 64,
+    MBTK_GSM_BAND_BAND_LOCK_BIT = 512
+} mbtk_gsm_band_enum;
+
+/*
+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
+*/
+typedef enum
+{
+    MBTK_UMTS_BAND_1 = 1,
+    MBTK_UMTS_BAND_2 = 2,
+    MBTK_UMTS_BAND_3 = 4,
+    MBTK_UMTS_BAND_4 = 8,
+    MBTK_UMTS_BAND_5 = 16,
+    MBTK_UMTS_BAND_6 = 32,
+    MBTK_UMTS_BAND_7 = 64,
+    MBTK_UMTS_BAND_8 = 128,
+    MBTK_UMTS_BAND_9 = 256
+} mbtk_umts_band_enum;
+
+/*
+LTEbandH(TDD-LTE band)
+    32 �C TDLTE_BAND_38
+    64 �C TDLTE_BAND_39
+    128 �C TDLTE_BAND_40
+    256 �C TDLTE_BAND_41
+*/
+typedef enum
+{
+    MBTK_TDLTE_BAND_38 = 32,
+    MBTK_TDLTE_BAND_39 = 64,
+    MBTK_TDLTE_BAND_40 = 128,
+    MBTK_TDLTE_BAND_41 = 256
+} mbtk_tdlte_band_enum;
+
+/*
+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
+*/
+typedef enum
+{
+    MBTK_FDDLTE_BAND_1 = 1,
+    MBTK_FDDLTE_BAND_3 = 4,
+    MBTK_FDDLTE_BAND_4 = 8,
+    MBTK_FDDLTE_BAND_7 = 64,
+    MBTK_FDDLTE_BAND_17 = 65536,
+    MBTK_FDDLTE_BAND_20 = 524288
+} mbtk_fddlte_band_enum;
+
+typedef enum
+{
+    MBTK_LTE_EXT_BAND_65 = 1,
+    MBTK_LTE_EXT_BAND_66 = 2,
+    MBTK_LTE_EXT_BAND_67 = 4,
+    MBTK_LTE_EXT_BAND_68 = 8,
+    MBTK_LTE_EXT_BAND_69 = 16
+} mbtk_lte_ext_band_enum;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char* type2str(ril_msg_type_enum type);
+
+char* apn2str(mbtk_ip_type_enum type);
+
+/*
+IPv6 : 254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239 -> uint128
+*/
+int str_2_ipv6(const void *ip_str, void *ipv6);
+
+/*
+IPv6 : uint128 -> fe80::215:1dff:fe81:484c
+*/
+int ipv6_2_str(const void *ipv6, void *ipv6_str);
+
+char* id2str(int id);
+
+char* err2str(mbtk_ril_err_enum err);
+
+void *mbtk_memcpy(const void *src, unsigned int n);
+
+/*
+0   GSM
+1   GSM_COMPACT
+2   UTRAN
+3   GSM_EGPRS
+4   UTRAN_HSDPA
+5   UTRAN_HSUPA
+6   UTRAN_HSDPA_HSUPA
+7   EUTRAN
+8   ECGSM
+*/
+mbtk_net_type_enum mbtk_net_type_get(mbtk_radio_technology_enum radio_tech);
+
+void ril_msg_pack_free(ril_msg_pack_info_t* pack);
+
+ril_msg_pack_info_t* ril_msg_pack_creat(int msg_type, int msg_id, int msg_index, const void *data, int data_len);
+
+int ril_pack_send(int fd, ril_msg_pack_info_t *pack);
+
+ril_msg_pack_info_t** ril_pack_recv(int fd, bool is_server, mbtk_ril_err_enum *err);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* MBTK_INFO_INCLUDE */
+
+
diff --git a/mbtk/libmbtk_ril_v2/src/mbtk_pdu_sms.c b/mbtk/libmbtk_ril_v2/src/mbtk_pdu_sms.c
new file mode 100755
index 0000000..5825cb6
--- /dev/null
+++ b/mbtk/libmbtk_ril_v2/src/mbtk_pdu_sms.c
@@ -0,0 +1,1086 @@
+//

+// Created by hitmoon on 15-12-9.

+//

+

+#include <stddef.h>

+#include <stdlib.h>

+#include <stdio.h>

+#include "mbtk_pdu_sms.h"

+#include "mbtk_alphabet.h"

+

+#define SUB_STR_SIZE 512

+char temp[SUB_STR_SIZE];

+

+// some constant

+

+//长短信信息元素参考号

+enum EnumCSMIEI mCSMIEI;

+// 服务中心地址

+char *mSCA;

+// 请求状态报告

+bool mSRR;

+// 拒绝副本

+bool mRD;

+// 短信有效期

+char *mVP;

+// 长短信信息元素消息参考号

+int mCSMMR;

+

+// initialize PDU constants

+void sms_init()

+{

+    mCSMMR = 0;

+    mRD = false;

+    mSRR = false;

+    mSCA = "";

+    mVP = "";

+    mCSMIEI = BIT8MIEI;

+}

+

+

+char *sub_str(const char *str, int start, int size) {

+    memset(temp, '\0', SUB_STR_SIZE);

+    if (size > 0)

+        strncpy(temp, str + start, size);

+    else if (size < 0)

+        strcpy(temp, str + start);

+

+    return temp;

+}

+

+struct SMS_Struct PDUDecoding(const char *data) {

+

+    struct SMS_Struct sms;

+    int end_index;

+    int PDUType;

+    // 短信中心

+    sms.SCA = SCADecoding(data, &end_index);

+

+    // 协议数据单元类型

+    PDUType = strtol(sub_str(data, end_index, 2), NULL, 16);

+    end_index += 2;

+

+    sms.RP = PDUType & (1 << 7) ? true : false;   // 应答路径

+    sms.UDHI = PDUType & (1 << 6) ? true : false;  // 用户数据头标识

+    sms.SRI = PDUType & (1 << 5) ? true : false;  // 状态报告指示

+    sms.MMS = PDUType & (1 << 2) ? false : true;  // 更多信息发送

+    sms.MTI = PDUType & 3;                        // 信息类型指示

+

+    // 发送方SME的地址

+    sms.OA = OADecoding(data, end_index, &end_index);

+

+    // 协议标识

+    sms.PID = strtol(sub_str(data, end_index, 2), NULL, 16);

+    end_index += 2;

+

+    // 数据编码方案

+    int DCSType = strtol(sub_str(data, end_index, 2), NULL, 16);

+    end_index += 2;

+

+    // 文本压缩指示

+    sms.TC = DCSType & (1 << 5);

+    // 编码字符集

+    sms.DCS = (enum EnumDCS) ((DCSType >> 2) & 3);

+

+    if (DCSType & (1 << 4)) {

+        // 信息类型信息 0:立即显示 1:移动设备特定类型 2:SIM特定类型 3:终端设备特定类型

+        sms.MC = DCSType & 3;

+    }

+    else {

+        // 不含信息类型信息

+        sms.MC = -1;

+    }

+    // 服务中心时间戳(BCD编码)

+    sms.SCTS = SCTSDecoding(data, end_index);

+    end_index += 14;

+

+    // 用户数据头

+    if (sms.UDHI) {

+        sms.UDH = UDHDecoding(data, end_index + 2);

+    }

+    else {

+        sms.UDH = NULL;

+    }

+

+    // 用户数据

+    sms.UD = UserDataDecoding(data, end_index, sms.UDHI, sms.DCS);

+

+    return sms;

+}

+

+

+char *SCADecoding(const char *data, int *EndIndex) {

+    int len;

+

+    char *result;

+    char *buf;

+	int i = 0;

+

+    len = strtol(sub_str(data, 0, 2), NULL, 16);

+    if (len == 0) {

+        *EndIndex = 2;

+        return NULL;

+    }

+

+    *EndIndex = (len + 1) * 2;

+

+    result = (char *) malloc(sizeof(char) * len * 2);

+    //wmemset(result, '0', sizeof(char) * (len * 2 + 1));

+

+    buf = result;

+    len *= 2;

+

+    // 服务中心地址类型

+    if (strncmp(data + 2, "91", 2) == 0) {

+        sprintf(buf++, "+");

+    }

+

+    // 服务中心地

+

+	for (i = 4; i < *EndIndex; i += 2) {

+        sprintf(buf++, "%c", data[i + 1]);

+        sprintf(buf++, "%c", data[i]);

+    }

+

+    //  去掉填充的 'F'

+    if (result[strlen(result) - 1] == L'F') {

+        result[strlen(result) - 1] = L'\0';

+    }

+

+    return result;

+}

+

+char *OADecoding(const char *data, int index, int *EndIndex) {

+    int len;

+    char *result, *buf;

+

+    len = strtol(sub_str(data, index, 2), NULL, 16);

+

+    if (len == 0) {

+        *EndIndex = index + 2;

+        return NULL;

+    }

+

+    *EndIndex = index + 4 + len;

+

+    result = (char *) malloc(sizeof(char) * (len + 2));

+    //wmemset(result, 0, sizeof(char) * (len + 1));

+    buf = result;

+    

+    if (strncmp(data + index + 2, "91", 2) == 0) {

+        sprintf(buf++, "+");

+    }

+

+    // 电话号码

+	int i = 0;

+    for (i = 0; i < len; i += 2) {

+        sprintf(buf++, "%c", data[index + i + 5]);

+        sprintf(buf++, "%c", data[index + i + 4]);

+

+    }

+

+    if (len % 2 != 0) {

+        result[strlen(result) - 1] = '\0';

+        (*EndIndex)++;

+    }

+    return result;

+}

+

+char *SCTSDecoding(const char *data, int index) {

+

+    char *result;

+

+    result = (char *) malloc(sizeof(char) * 32);

+    sprintf(result, "20%02d-%02d-%02d %02d:%02d:%02d",

+             BCDDecoding(data, index, 0),                // 年

+             BCDDecoding(data, index + 2, 0),            // 月

+             BCDDecoding(data, index + 4, 0),            // 日

+             BCDDecoding(data, index + 6, 0),            // 时

+             BCDDecoding(data, index + 8, 0),            // 分

+             BCDDecoding(data, index + 10, 0)            // 秒

+

+    );

+    return result;

+}

+

+int BCDDecoding(const char *data, int index, bool isMSB) {

+

+    int n1, n10;

+

+    n1 = strtol(sub_str(data, index, 1), NULL, 10);

+    n10 = strtol(sub_str(data, index + 1, 1), NULL, 10);

+

+    if (isMSB) {

+        if (n10 >= 8)

+            return -((n10 - 8) * 10 + n1); // 负值

+        else

+            return n10 * 10 + n1;

+    }

+    else {

+        return n10 * 10 + n1;

+    }

+}

+

+struct UDHS *UDHDecoding(const char *data, int index) {

+

+    int len;

+    struct UDHS *result;

+

+    len = strtol(sub_str(data, index, 2), NULL, 16);

+    index += 2;

+    int i = 0;

+

+    result = (struct UDHS *) malloc(sizeof(struct UDHS));

+    result->UDH = (struct PDUUDH *) malloc(sizeof(struct PDUUDH) * len);

+    result->count = 0;

+    memset(result->UDH, 0, sizeof(struct PDUUDH) * len);

+

+    while (i < len) {

+        // 信息元素标识(Information Element Identifier

+        char IEI = strtol(sub_str(data, index, 2), NULL, 16);

+        index += 2;

+        // 信息元素数据长度(Length of Information Element)

+        int IEDL = strtol(sub_str(data, index, 2), NULL, 16);

+        index += 2;

+        // 信息元素数据(Information Element Data)

+        char *IED = (char *) malloc(sizeof(char) * (IEDL + 1));

+        int j = 0;

+		for (j = 0; j < IEDL; j++) {

+            IED[j] = strtol(sub_str(data, index, 2), NULL, 16);

+            index += 2;

+        }

+        result->UDH[result->count].IEI = IEI;

+        result->UDH[result->count].IED = IED;

+        result->count++;

+        i += IEDL + 2;

+    }

+

+    return result;

+}

+

+char *UserDataDecoding(const char *data, int index, bool UDHI, enum EnumDCS dcs) {

+    char *result = NULL;

+    char *buf;

+

+    // 用户数据区长度

+    int UDL = strtol(sub_str(data, index, 2), NULL, 16);

+    index += 2;

+

+    // 跳过用户数据头

+    int UDHL = 0;

+    if (UDHI) {

+        // 用户数据头长度

+        UDHL = strtol(sub_str(data, index, 2), NULL, 16);

+        UDHL++;

+        index += UDHL << 1;

+

+    }

+

+    // 获取用户数据

+    if (dcs == UCS2) {

+        int len = (UDL - UDHL) >> 1;

+        int utf8_len;

+

+        result = (char *) malloc(sizeof(char) * (len * 3));

+        buf = result;

+        u_int32_t code[2];

+

+		int i = 0;

+        for (i = 0; i < len; i++) {

+            code[0] = strtol(sub_str(data, (i << 2) + index, 4), NULL, 16);

+            code[1] = 0;

+            utf32toutf8((wchar_t*)code, (unsigned char*)buf, len * 3, &utf8_len);

+            buf += utf8_len;

+        }

+

+        buf[0] = '\0';

+        return result;

+    }

+    else if (dcs == BIT7) {

+        int Septets = UDL - (UDHL * 8 + 6) / 7;           // 7-Bit编码字符数

+

+        int FillBits = (UDHL * 8 + 6) / 7 * 7 - UDHL * 8; //  填充位数

+        return BIT7Decoding(BIT7Unpack(data, index, Septets, FillBits), Septets);

+    }

+    else {// 8Bit编码

+        // 获取数据长度

+        UDL -= UDHL;

+        result = (char *) malloc(sizeof(char) * (UDL + 1));

+        int i = 0;

+		for (i = 0; i < UDL; i++) {

+            result[i] = strtol(sub_str(data, (i << 1) + index, 2), NULL, 16);

+        }

+        return result;

+    }

+

+    return "Error!";

+}

+

+char *BIT7Unpack(const char *data, int index, int Septets, int FillBits) {

+    char *result;

+

+    result = (char *) malloc(sizeof(char) * (Septets + 1));

+    // 每8个7-Bit编码字符存放到7个字节

+    int PackLen = (Septets * 7 + FillBits + 7) / 8;

+    int n = 0;

+    int left = 0;

+

+//    printf("Unapck data = %s\n", data + index);

+//    printf("Septets = %d\n", Septets);

+//    printf("pack len = %d\n", PackLen);

+//    printf("fillbits = %d\n", FillBits);

+

+	int i = 0;

+    for (i = 0; i < PackLen; i++) {

+

+        int Order = (i + (7 - FillBits)) % 7;

+        int Value = strtol(sub_str(data, (i << 1) + index, 2), NULL, 16);

+        if (i != 0 || FillBits == 0) {

+            result[n++] = ((Value << Order) + left) & 0x7F;

+        }

+//        printf("left = %d, i = %d, order = %d, value = %d\n", left, i, Order, Value);

+//        printf("result[%d] = %d\n", n - 1, result[n - 1]);

+        left = Value >> (7 - Order);

+        if (Order == 6) {

+            if (n == Septets)

+                break;

+            result[n++] = left;

+            //printf("result[%d] = %d\n", n - 1, result[n - 1]);

+            left = 0;

+        }

+    }

+

+    return result;

+}

+

+char *BIT7Decoding(char *BIT7Data, unsigned int size)

+{

+    char *result, *buf;

+

+    result = (char *) malloc(sizeof(char) * (size + 1));

+    buf = result;

+

+	int i = 0;

+    for (i = 0; i < size; i++) {

+        u_int16_t key = BIT7Data[i];

+        if (isBIT7Same(key)) {

+            sprintf(buf++, "%c", key);

+        }

+        else if (map_get_value(BIT7ToUCS2, map_size(BIT7ToUCS2), key) >= 0) {

+            u_int16_t value;

+            if (key == 0x1B) { // 转义字符

+                value = map_get_value(BIT7EToUCS2, map_size(BIT7EToUCS2), BIT7Data[i + 1]);

+                if (i < size - 1 && value > 0) {

+                    sprintf(buf++, "%c", value);

+                    i++;

+                }

+                else {

+                    value = map_get_value(BIT7ToUCS2, map_size(BIT7ToUCS2), key);

+                    sprintf(buf++, "%c", value);

+                }

+            }

+            else {

+                //printf("go b\n");

+                value = map_get_value(BIT7ToUCS2, map_size(BIT7ToUCS2), key);

+                //printf("value = %u\n", value);

+                sprintf(buf++, "%c", value);

+

+            }

+        }

+        else {// 异常数据

+            sprintf(buf++, "?");

+        }

+

+    }

+    return result;

+

+}

+

+int isBIT7Same(u_int16_t UCS2) {

+	if ((UCS2 >= 0x61 && UCS2 <= 0x7A) ||

+	    (UCS2 >= 0x41 && UCS2 <= 0x5A) ||

+	    (UCS2 >= 0x25 && UCS2 <= 0x3F) ||

+	    (UCS2 >= 0x20 && UCS2 <= 0x23) ||

+	    UCS2 == 0x0A || UCS2 == 0x0D) {

+        return 1;

+    }

+    return 0;

+}

+

+struct PDUS *PDUEncoding(char *SCA, char *DA, char *UDC, struct UDHS *udhs) {

+    enum EnumDCS DCS;

+

+    sms_init();

+

+//    if (isGSMString(UDC))

+//        DCS = BIT7;

+//    else

+        DCS = UCS2;

+

+    return PDUDoEncoding(SCA, DA, UDC, udhs, DCS);

+}

+

+struct PDUS *PDUDoEncoding(char *SCA, char *DA, char *UDC, struct UDHS *udhs, enum EnumDCS DCS) {

+    // 短信拆分

+    struct UDS *uds = UDCSplit(UDC, udhs, DCS);

+    struct PDUS *pdus;

+

+    if (uds == NULL)

+        return NULL;

+    pdus = (struct PDUS *) malloc(sizeof(struct PDUS));

+    pdus->count = 0;

+    pdus->PDU = (char **) malloc(sizeof(char *) * uds->total);

+

+    if (uds->total > 1) {

+        // 长短信

+        int CSMMR = mCSMMR;

+        if (++mCSMMR > 0xFFFF)

+            mCSMMR = 0;

+        // 生成短信编码序列

+		int i = 0;

+        for (i = 0; i < uds->total; i++) {

+            // 更新用户数据头

+            struct UDHS *CSMUDH = UpdateUDH(udhs, CSMMR, uds->total, i);

+            pdus->PDU[i] = SoloPDUEncoding(SCA, DA, uds->Data[i], CSMUDH, DCS);

+            pdus->count++;

+        }

+

+    }

+    else {  // 单条短信

+        pdus->PDU[0] = SoloPDUEncoding(SCA, DA, uds->Data[0], udhs, DCS);

+        pdus->count = 1;

+    }

+

+    return pdus;

+}

+

+int isGSMString(char *Data) {

+

+    if (Data == NULL || strcmp(Data, "") == 0)

+        return 1;

+

+    if (is_acsii((unsigned char*)Data) == 0) {

+        int len;

+        len = utf8len((unsigned char *) Data); 

+

+        u_int16_t *code = (u_int16_t *) malloc(sizeof(u_int16_t) * len);

+        utf8toutf16((unsigned char *) Data, code, len, &len);

+

+        while (*code) {

+            if (!(isBIT7Same(*code) || map_get_value(UCS2ToBIT7, map_size(UCS2ToBIT7), *code) >= 0))

+                return 0;

+            code++;

+        }

+

+        return 1;

+    }

+    else

+        return 1;

+

+}

+

+struct UDS *UDCSplit(char *UDC, struct UDHS *udhs, enum EnumDCS DCS) {

+    int UDHL = getUDHL(udhs);

+    struct UDS *result;

+

+    if (DCS == BIT7) {

+        // 7-Bit编码

+        // 计算剩余房间数

+        int room = BIT7UDL - (UDHL * 8 + 6) / 7;

+        if (room < 1) {

+            if (UDC == NULL || strcmp(UDC, "") == 0) {

+                result = (struct UDS *) malloc(sizeof(struct UDS));

+                result->Data = (char **)malloc(sizeof(char *));

+                result->total = 1;

+                result->Data[0] = UDC;

+                return result;

+            }

+            else

+                return NULL;

+        }

+

+        // 不需要拆分

+        if (SeptetsLength(UDC) <= room) {

+            result = (struct UDS *) malloc(sizeof(struct UDS));

+            result->Data = (char **)malloc(sizeof(char *));

+            result->total = 1;

+            result->Data[0] = UDC;

+            return result;

+        }

+        else // 拆分短信

+        {

+            if (UDHL == 0)

+                UDHL++;

+            if (mCSMIEI == BIT8MIEI)

+                UDHL += 5;  // 1字节消息参考号

+            else

+                UDHL += 6;  // 2字节消息参考号

+            // 更新剩余房间数

+            room = BIT7UDL - (UDHL * 8 + 6) / 7;

+            if (room < 1)

+                return NULL;

+

+            int i = 0;

+            int len = strlen(UDC);

+

+            result = (struct UDS *) malloc(sizeof(struct UDS));

+            result->total = 0;

+            result->Data = (char **) malloc(MAX_SMS_NR * sizeof(char *));

+

+            while (i < len) {

+                int step = SeptetsToChars(UDC, i, room);

+                if (i + step < len) {

+                    result->Data[result->total] = (char *) malloc(sizeof(char) * (step + 1));

+                    strcpy(result->Data[result->total++], sub_str(UDC, i, step));

+                }

+                else {

+                    result->Data[result->total] = (char *) malloc(sizeof(char) * (len - i + 1));

+                    strcpy(result->Data[result->total++], sub_str(UDC, i, -1));

+                }

+

+                i += step;

+

+            }

+            return result;

+

+        }

+    }

+    else { // UCS2编码

+        // 计算剩余房间数

+        int room = (BIT8UDL - UDHL) >> 1;

+        if (room < 1) {

+            if (UDC == NULL || strcmp(UDC, "") == 0) {

+                result = (struct UDS *) malloc(sizeof(struct UDS));

+                result->Data = (char **)malloc(sizeof(char *));

+                result->total = 1;

+                result->Data[0] = UDC;

+                return result;

+            }

+            else

+                return NULL;

+        }

+        if (UDC == NULL || utf8len(UDC) <= room) {

+            result = (struct UDS *) malloc(sizeof(struct UDS));

+            result->Data = (char **)malloc(sizeof(char *));

+            result->total = 1;

+            result->Data[0] = UDC;

+            return result;

+        }

+        else // 需要拆分成多条短信

+        {

+            if (UDHL == 0)

+                UDHL++;

+            if (mCSMIEI == BIT8MIEI)

+                UDHL += 5;  // 1字节消息参考号

+            else

+                UDHL += 6;  // 2字节消息参考号

+

+            // 更新剩余房间数

+            room = (BIT8UDL - UDHL) >> 1;

+            if (room < 1)

+                return NULL;

+

+            int len = utf8len(UDC);

+

+            result = (struct UDS *) malloc(sizeof(struct UDS));

+            result->total = 0;

+            result->Data = (char **) malloc(MAX_SMS_NR * sizeof(char *));

+	    int index = 0;

+		int i = 0;

+            for (i = 0; i < len; i += room) {

+		    int real_size;

+                if (i + room < len) {

+		    real_size = utf8_get_size(UDC + index, room);

+                    result->Data[result->total] = (char*)malloc(sizeof(char) * (real_size + 1));

+                    strcpy(result->Data[result->total++],sub_str(UDC, index, real_size));

+                }

+                else {

+		    real_size = utf8_get_size(UDC + index, len - i);

+                    result->Data[result->total] = (char*)malloc(sizeof(char) * (real_size + 1));

+                    strcpy(result->Data[result->total++], sub_str(UDC, index, -1));

+                }

+		index += real_size;

+            }

+            return result;

+        }

+

+    }

+}

+

+int getUDHL(struct UDHS *udhs) {

+    if (udhs == NULL)

+        return 0;

+

+    // 加上1字节的用户数据头长度

+    int UDHL = 1;

+	int i = 0;

+    for (i = 0; i < udhs->count; i++) {

+        UDHL += strlen(udhs->UDH[i].IED) + 2;

+    }

+    return UDHL;

+}

+

+int SeptetsLength(char *source) {

+    if (source == NULL || strcmp(source, "") == 0) {

+        return 0;

+    }

+    int len = strlen(source);

+    while (*source) {

+        u_int16_t code = (u_int16_t) *source;

+        if (map_get_value(UCS2ToBIT7, map_size(UCS2ToBIT7), code) > 0xFF) {

+            len++;

+        }

+        source++;

+    }

+    return len;

+}

+

+int SeptetsToChars(char *source, int index, int septets) {

+    if (source == NULL || strcmp(source, "") == 0)

+        return 0;

+    int count = 0;

+    int i;

+

+    for (i = index; i < strlen(source); i++) {

+        u_int16_t code = (u_int16_t) source[i];

+        if (map_get_value(UCS2ToBIT7, map_size(UCS2ToBIT7), code) > 0xFF)

+            count++;

+

+        if (++count >= septets) {

+            if (count == septets)

+                i++;

+            break;

+        }

+    }

+    return i - index;

+}

+

+struct UDHS *UpdateUDH(struct UDHS *udhs, int CSMMR, int total, int index) {

+    struct UDHS *result;

+

+    result = (struct UDHS *) malloc(sizeof(struct UDHS));

+

+    if (udhs == NULL || udhs->count == 0) {

+        result->UDH = (struct PDUUDH *) malloc(sizeof(struct PDUUDH));

+        result->count = 1;

+

+    }

+    else {

+        result->UDH = (struct PDUUDH *) malloc(sizeof(struct PDUUDH) * (udhs->count + 1));

+        result->count = udhs->count + 1;

+        // 复制 UDH

+        memcpy(&result->UDH[1], udhs->UDH, sizeof(struct PDUUDH) * udhs->count);

+    }

+    // 插入第一个位置

+    if (mCSMIEI == BIT8MIEI) {

+        result->UDH[0].IED = (char *) malloc(sizeof(char) * 3);

+        result->UDH[0].count = 3;

+        result->UDH[0].IED[0] = CSMMR & 0xFF;

+        result->UDH[0].IED[1] = total;

+        result->UDH[0].IED[2] = index + 1;

+        result->UDH[0].IEI = 0;

+    }

+    else {

+        result->UDH[0].IED = (char *) malloc(sizeof(char) * 4);

+        result->UDH[0].count = 4;

+        result->UDH[0].IED[0] = (CSMMR >> 8) & 0xFF;

+        result->UDH[0].IED[1] = CSMMR & 0xFF;

+        result->UDH[0].IED[2] = total;

+        result->UDH[0].IED[3] = index + 1;

+        result->UDH[0].IEI = 8;

+    }

+

+    return result;

+}

+

+char *SoloPDUEncoding(char *SCA, char *DA, char *UC, struct UDHS *udhs, enum EnumDCS DCS) {

+    char *result;

+    char *buf, *ret;

+    int index;

+

+    result = (char *) malloc(sizeof(char) * 400);

+    buf = result;

+

+/*    //  短信中心

+	ret = SCAEncoding(SCA);

+    index = strlen(ret);

+    sprintf(buf, "%s", ret);

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

+    buf += index;

+

+*/

+    // 协议数据单元类型

+    if (udhs == NULL || udhs->count == 0) {

+        ret = PDUTypeEncoding(false);

+        sprintf(buf, "%s", ret);

+        buf += strlen(ret);

+    }

+    else {

+        ret = PDUTypeEncoding(true);

+        sprintf(buf, "%s", ret);

+        buf += strlen(ret);

+    }

+    // 消息参考值

+    ret = MREncoding();

+    sprintf(buf, "%s", ret);

+    buf += strlen(ret);

+    // 接收方SME地址

+    ret = DAEncoding(DA);

+    sprintf(buf, "%s", ret);

+    buf += strlen(ret);

+    // 协议标识

+    ret = PIDEncoding();

+    sprintf(buf, "%s", ret);

+    buf += strlen(ret);

+    // 编码方案

+    ret = DCSEncoding(UC, DCS);

+    sprintf(buf, "%s", ret);

+    buf += strlen(ret);

+    // 有效期

+    sprintf(buf, "%s", mVP);

+    buf += strlen(mVP);

+

+    // 用户数据长度及内容

+    ret = UDEncoding(UC, udhs, DCS);

+    sprintf(buf, "%s", ret);

+

+    return result;

+}

+

+char *SCAEncoding(char *SCA) {

+

+    if (SCA == NULL || strcmp(SCA, "") == 0) {

+        // 表示使用SIM卡内部的设置值,该值通过AT+CSCA指令设置

+        return "00";

+    }

+

+    char *result;

+    char *buf;

+    int len;

+    len = strlen(SCA);

+    result = (char *) malloc((len + 5) * sizeof(char));

+    buf = result;

+

+    int index = 0;

+    if (SCA[0] == '+') {

+        // 国际号码

+        sprintf(buf, "%02X", len / 2 + 1);

+        buf += 2;

+        sprintf(buf, "91");

+        buf += 2;

+        index = 1;

+    }

+    else {

+        // 国内号码

+        sprintf(buf, "%02X", len / 2 + 1);

+        buf += 2;

+        sprintf(buf, "81");

+        buf += 2;

+    }

+    // SCA地址编码

+    for (; index < len; index += 2) {

+        if (index == len - 1) {

+            // 补“F”凑成偶数个

+            sprintf(buf++, "F");

+            sprintf(buf++, "%c", SCA[index]);

+

+        }

+        else {

+            sprintf(buf++, "%c", SCA[index + 1]);

+            sprintf(buf++, "%c", SCA[index]);

+        }

+    }

+

+    return result;

+}

+

+char *PDUTypeEncoding(bool UDH) {

+    // 信息类型指示(Message Type Indicator)

+    // 01 SMS-SUBMIT(MS -> SMSC)

+    int PDUType = 0x11;    // 508TLC change

+//	int PDUType = 0x01;

+    char *result;

+    result = (char *) malloc(3 * sizeof(char));

+

+    // 用户数据头标识(User Data Header Indicator)

+    if (UDH) {

+        PDUType |= 0x40;

+    }

+    // 有效期格式(Validity Period Format)

+    if (strlen(mVP) == 2) {

+        // VP段以整型形式提供(相对的)

+        PDUType |= 0x10;

+    }

+    else if (strlen(mVP) == 14) {

+        // VP段以8位组的一半(semi-octet)形式提供(绝对的)

+        PDUType |= 0x18;

+    }

+

+    // 请求状态报告(Status Report Request)

+    if (mSRR) {

+        // 请求状态报告

+        PDUType |= 0x20;

+    }

+

+    // 拒绝复本(Reject Duplicate)

+    if (mRD) {

+        PDUType |= 0x04;

+    }

+    sprintf(result, "%02X", PDUType);

+    return result;

+}

+

+char *MREncoding() {

+    // 由手机设置

+    return "00";

+}

+

+char *DAEncoding(char *DA) {

+    if (DA == NULL || strcmp(DA, "") == 0) {

+        // 地址长度0,地址类型未知

+        return "0080";

+    }

+    char *result, *buf;

+    int len = strlen(DA);

+    int index;

+

+    result = (char *) malloc(sizeof(char) * (len + 5));

+    buf = result;

+

+    if (DA[0] == '+') {

+        // 国际号码

+        // 地址长度编码

+        sprintf(buf, "%02X", len - 1);

+        buf += 2;

+        // 地址类型

+        sprintf(buf, "91");

+        buf += 2;

+        index = 1;

+    }

+    else {

+        // 国内号码

+        // 地址长度编码

+        sprintf(buf, "%02X", len);

+        buf += 2;

+        // 地址类型

+        sprintf(buf, "81");

+        buf += 2;

+    }

+

+    for (; index < len; index += 2) {

+        // 号码部分奇偶位对调

+        if (index == len - 1) {

+            sprintf(buf++, "F");

+            sprintf(buf++, "%c", DA[index]);

+        }

+        else {

+            sprintf(buf++, "%c", DA[index + 1]);

+            sprintf(buf++, "%c", DA[index]);

+        }

+    }

+    return result;

+

+}

+

+char *PIDEncoding() {

+    return "00";

+}

+

+char *DCSEncoding(char *UD, enum EnumDCS DCS) {

+    if (DCS == BIT7) {

+        // 7-Bit编码

+        return "00";

+    }

+    else {

+        // UCS2编码

+        return "0800";

+    }

+}

+

+char *UDEncoding(char *UD, struct UDHS *udhs, enum EnumDCS DCS) {

+    int UDHL;

+

+    char *result;

+

+    // 用户数据头编码

+    char *header = UDHEncoding(udhs, &UDHL);

+

+    // 用户数据内容编码

+    int UDCL;

+    char *body;

+

+    body = UDCEncoding(UD, &UDCL, UDHL, DCS);

+

+    // 用户数据区长度

+    int UDL;

+    if (DCS == BIT7) {

+        // 7-Bit编码

+        UDL = (UDHL * 8 + 6) / 7 + UDCL;

+    }

+    else {

+        // UCS2编码或者8-Bit编码

+        UDL = UDHL + UDCL;

+    }

+

+    int len = strlen(header) + strlen(body) + 2;

+    result = (char *) malloc(sizeof(char) * (len + 1));

+    sprintf(result, "%02X%s%s", UDL, header, body);

+

+    return result;

+

+}

+

+char *UDHEncoding(struct UDHS *udhs, int *UDHL) {

+

+    *UDHL = 0;

+

+    if (udhs == NULL || udhs->count == 0)

+        return "";

+	int i = 0;

+    for (i = 0; i < udhs->count; i++) {

+        *UDHL += udhs->UDH[i].count + 2;

+    }

+

+    char *result;

+    char *buf;

+    result = (char *) malloc(sizeof(char) * ((*UDHL + 1) * 2 + 1));

+    buf = result;

+

+    sprintf(buf, "%02X", *UDHL);

+    buf += 2;

+	

+    for (i = 0; i < udhs->count; i++) {

+        // 信息元素标识1字节

+        sprintf(buf, "%02X", udhs->UDH[i].IEI);

+        buf += 2;

+        // 信息元素长度1字节

+        sprintf(buf, "%02X", udhs->UDH[i].count);

+        buf += 2;

+        // 信息元素数据

+		int j = 0;

+        for (j = 0; j < udhs->UDH[i].count; j++) {

+            sprintf(buf, "%02X", udhs->UDH[i].IED[j]);

+            buf += 2;

+        }

+

+    }

+    // 加上1字节的用户数据头长度

+    (*UDHL)++;

+    return result;

+

+}

+

+char *UDCEncoding(char *UDC, int *UDCL, int UDHL, enum EnumDCS DCS) {

+    if (UDC == NULL || strcmp(UDC, "") == 0) {

+        *UDCL = 0;

+        return "";

+    }

+

+    if (DCS == BIT7) {

+        // 7-Bit编码,需要参考用户数据头长度,已保证7-Bit边界对齐

+        return BIT7Pack(BIT7Encoding(UDC, UDCL), UDHL);

+    }

+    else {

+        // UCS2编码

+

+        int len = utf8len((unsigned char*)UDC);

+        int len2;

+        unsigned short *code;

+

+        code = (unsigned short*)malloc(sizeof(unsigned short) * len);

+        utf8toutf16((unsigned char*)UDC, code, len, &len2);

+        *UDCL = len * 2;

+        char *result = (char *) malloc(sizeof(char) * (*UDCL * 2 + 1));

+        char *buf = result;

+

+		int i = 0;

+        for (i = 0; i < len; i++) {

+            sprintf(buf, "%04X", code[i]);

+            buf += 4;

+        }

+        free(code);

+        return result;

+    }

+}

+

+struct ByteArray *BIT7Encoding(char *UDC, int *Septets) {

+    struct ByteArray *result;

+

+    int len = strlen(UDC);

+

+    result = (struct ByteArray *) malloc(sizeof(struct ByteArray));

+    result->len = 0;

+    result->array = (char *) malloc(sizeof(char) * (len * 2 + 1));

+    *Septets = 0;

+

+	int i = 0;

+    for (i = 0; i < len; i++) {

+        u_int16_t code = (u_int16_t) UDC[i];

+        if (isBIT7Same(code)) {

+            //  编码不变

+	    result->array[(*Septets)++] = code;

+        }

+        else {

+            u_int16_t value = map_get_value(UCS2ToBIT7, map_size(UCS2ToBIT7), code);

+            if (value >= 0) {

+                if (value > 0xFF) {

+                    // 转义序列

+			result->array[(*Septets)++] = value >> 8;

+			result->array[(*Septets)++] = value & 0xFF;

+                }

+                else {

+			result->array[(*Septets)++] = value;

+                }

+            }

+            else {

+                // 未知字符

+		    result->array[(*Septets)++] = (u_int16_t) '?';

+            }

+        }

+    }

+    // 重新调整大小

+    result->len = *Septets;

+

+    return result;

+}

+

+char *BIT7Pack(struct ByteArray *Bit7Array, int UDHL) {

+    // 7Bit对齐需要的填充位

+    int fillBits = (UDHL * 8 + 6) / 7 * 7 - (UDHL * 8);

+

+    // 压缩字节数

+    int len = Bit7Array->len;

+    int packLen = (len * 7 + fillBits + 7) / 8;

+    char *result;

+    char *buf;

+

+    result = (char *) malloc(sizeof(char) * (packLen * 2 + 1));

+    buf = result;

+

+    int left = 0;

+	int i = 0;

+    for (i = 0; i < len; i++) {

+        // 每8个字节压缩成7个字节

+        int32_t Value = Bit7Array->array[i];

+        int32_t index = (i + 8 - fillBits) % 8;

+        if (index == 0) {

+            left = Value;

+        }

+        else {

+            int32_t n = ((Value << (8 - index)) | left) & 0xFF;

+            sprintf(buf, "%02X", n);

+            buf += 2;

+            left = Value >> index;

+        }

+    }

+

+

+    if ((len * 7 + fillBits) % 8 != 0) {

+        // 写入剩余数据

+        sprintf(buf, "%02X", left);

+        buf += 2;

+    }

+    buf[0] = '\0';

+    return result;

+}

+

diff --git a/mbtk/libmbtk_ril_v2/src/mbtk_ril_api.c b/mbtk/libmbtk_ril_v2/src/mbtk_ril_api.c
new file mode 100755
index 0000000..b18e9d0
--- /dev/null
+++ b/mbtk/libmbtk_ril_v2/src/mbtk_ril_api.c
@@ -0,0 +1,2265 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include "mbtk_ril.h"
+#include "mbtk_list.h"
+#include "mbtk_utils.h"
+#include "mbtk_log.h"
+
+typedef struct {
+    int cli_fd;
+    bool ril_ready;
+    int exit_fd[2];
+    pthread_t read_thread_id;
+    pthread_mutex_t send_mutex;
+    list_node_t* msg_list;           // ril_msg_info_t
+    list_node_t* cli_thread_list;     // ril_cli_thread_info_t
+} ril_cli_info_t;
+
+#define EPOLL_LISTEN_MAX 100
+
+static ril_cli_info_t ril_cli;
+static int pthread_id_index = 1;
+
+static ril_cli_thread_info_t* thread_find_by_pid(pthread_t pid)
+{
+    ril_cli_thread_info_t* cli_thread = NULL;
+    list_first(ril_cli.cli_thread_list);
+    while ((cli_thread = (ril_cli_thread_info_t*)list_next(ril_cli.cli_thread_list)))
+    {
+        if(pid == cli_thread->pid) {
+            break;
+        }
+    }
+
+    if(!cli_thread) { // No found cli thread in list.
+        cli_thread = (ril_cli_thread_info_t*)malloc(sizeof(ril_cli_thread_info_t));
+        memset(cli_thread, 0, sizeof(ril_cli_thread_info_t));
+        cli_thread->pid = pid;
+        sprintf(cli_thread->name, "PID-%d", pthread_id_index++);
+        pthread_mutex_init(&cli_thread->mutex, NULL);
+        pthread_cond_init(&cli_thread->cond, NULL);
+        cli_thread->is_waitting = FALSE;
+        list_add(ril_cli.cli_thread_list, cli_thread);
+    }
+
+    return cli_thread;
+}
+
+static void ril_thread_wait(ril_cli_thread_info_t* cli_thread)
+{
+    if(!cli_thread->is_waitting) {
+        LOGD("Thread(%s) waitting...", cli_thread->name);
+        cli_thread->is_waitting = TRUE;
+        pthread_mutex_lock(&cli_thread->mutex);
+        pthread_cond_wait(&cli_thread->cond, &cli_thread->mutex);
+        pthread_mutex_unlock(&cli_thread->mutex);
+        cli_thread->is_waitting = FALSE;
+        LOGD("Thread(%s) running...", cli_thread->name);
+    } else {
+        LOGD("RSP befor SEND, not waitting...");
+        cli_thread->is_waitting = FALSE;
+    }
+}
+
+
+static void ril_thread_continue(pthread_t pid)
+{
+    ril_cli_thread_info_t* cli_thread = NULL;
+    list_first(ril_cli.cli_thread_list);
+    while ((cli_thread = (ril_cli_thread_info_t*) list_next(ril_cli.cli_thread_list)))
+    {
+        if(pid == cli_thread->pid) {
+            break;
+        }
+    }
+
+    if(cli_thread) { // Found cli thread in list.
+        if(cli_thread->is_waitting) {
+            LOGD("Thread(%s) will continue...", cli_thread->name);
+            pthread_mutex_lock(&cli_thread->mutex);
+            pthread_cond_signal(&cli_thread->cond);
+            pthread_mutex_unlock(&cli_thread->mutex);
+        } else {
+            LOGD("Thread(%s) not continue...", cli_thread->name);
+            cli_thread->is_waitting = TRUE;
+        }
+    } else {
+        LOGE("No found cli thread[Cannot occur].");
+    }
+}
+
+static int ril_ind_process(ril_msg_pack_info_t* pack)
+{
+    switch(pack->msg_id) {
+        case RIL_MSG_ID_IND_SER_READY: // rild service ready.
+        {
+            ril_cli.ril_ready = TRUE;
+            return 0;
+        }
+        case RIL_MSG_ID_IND_NET_STATE_CHANGE:
+        {
+            return 0;
+        }
+        case RIL_MSG_ID_IND_CALL_STATE_CHANGE:
+        {
+            return 0;
+        }
+        case RIL_MSG_ID_IND_SMS_STATE_CHANGE:
+        {
+            return 0;
+        }
+        case RIL_MSG_ID_IND_RADIO_STATE_CHANGE:
+        {
+            return 0;
+        }
+        case RIL_MSG_ID_IND_SIM_STATE_CHANGE:
+        {
+            return 0;
+        }
+        case RIL_MSG_ID_IND_PDP_STATE_CHANGE:
+        {
+            return 0;
+        }
+        case RIL_MSG_ID_IND_SIGNAL_STATE_CHANGE:
+        {
+            return 0;
+        }
+        default:
+        {
+            LOGE("Unknown IND : %d", pack->msg_id);
+            return -1;
+        }
+    }
+}
+
+static int ril_rsp_process(ril_msg_pack_info_t* pack)
+{
+    if(pack->msg_index == RIL_MSG_INDEX_INVALID) {
+        LOGE("Invalid message index.");
+        return -1;
+    }
+
+    pthread_mutex_lock(&ril_cli.send_mutex);
+    ril_msg_info_t* msg = NULL;
+    list_first(ril_cli.msg_list);
+    while ((msg = (ril_msg_info_t*) list_next(ril_cli.msg_list)))
+    {
+        if(pack->msg_index == msg->pack->msg_index) {
+            break;
+        }
+    }
+
+    if(NULL == msg) { // No found message in msg list.
+        LOGW("Unknown msg : Index - %d, Type - %s, ID - %s, Result - %s ,Length - %d",
+            pack->msg_index, type2str(pack->msg_type), id2str(pack->msg_id), err2str(pack->err),
+            pack->data_len);
+        pthread_mutex_unlock(&ril_cli.send_mutex);
+        return -1;
+    } else {
+        int result = 0;
+        LOGD("Msg : Index - %d, Type - %s, ID - %s, Result - %s ,Length - %d", pack->msg_index,
+            type2str(pack->msg_type),
+            id2str(pack->msg_id),
+            err2str(pack->err),
+            pack->data_len);
+        if(msg->pack->msg_id != pack->msg_id) {
+            LOGE("msg id not match : %d , %d", msg->pack->msg_id ,pack->msg_id);
+            result = -1;
+            *(msg->rsp_err) = MBTK_RIL_ERR_FORMAT;
+            goto rm_msg_from_list;
+        }
+
+        if(msg->rsp_data && pack->data && pack->data_len > 0) {
+            memcpy(msg->rsp_data, pack->data, pack->data_len);
+        }
+
+        *(msg->rsp_data_len) = pack->data_len;
+        *(msg->rsp_err) = pack->err;
+
+        if(!msg->is_async) {
+            ril_thread_continue(msg->pid);
+        }
+
+rm_msg_from_list:
+        if(list_remove(ril_cli.msg_list, msg)) {
+            ril_msg_pack_free(msg->pack);
+            free(msg);
+        }
+        pthread_mutex_unlock(&ril_cli.send_mutex);
+        return result;
+    }
+}
+
+static int ril_pack_process(ril_msg_pack_info_t* pack)
+{
+    if(pack->msg_type == RIL_MSG_TYPE_IND) { // IND message.
+        return ril_ind_process(pack);
+    } else if(pack->msg_type == RIL_MSG_TYPE_RSP) {// Response message.
+        return ril_rsp_process(pack);
+    } else {
+        LOGE("Pack must be RSP or IND.");
+        return -1;
+    }
+}
+
+static void* ril_read_run(void* arg)
+{
+    int epoll_fd = epoll_create(5);
+    if(epoll_fd < 0)
+    {
+        LOGE("epoll_create() fail[%d].", errno);
+        return NULL;
+    }
+
+    uint32 event = EPOLLIN | EPOLLET;
+    struct epoll_event ev_cli, ev_exit;
+    ev_cli.data.fd = ril_cli.cli_fd;
+    ev_cli.events = event; //EPOLLIN | EPOLLERR | EPOLLET;
+    epoll_ctl(epoll_fd,EPOLL_CTL_ADD, ril_cli.cli_fd, &ev_cli);
+
+    ev_exit.data.fd = ril_cli.exit_fd[0];
+    ev_exit.events = event; //EPOLLIN | EPOLLERR | EPOLLET;
+    epoll_ctl(epoll_fd,EPOLL_CTL_ADD, ril_cli.exit_fd[0], &ev_exit);
+
+    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)
+        {
+            int i;
+            for(i = 0; i < nready; i++)
+            {
+                LOGD("fd[%d] event = %x",epoll_events[i].data.fd, epoll_events[i].events);
+                if(epoll_events[i].events & EPOLLHUP)   // Closed by server.
+                {
+                    LOGD("Closed by server.");
+                    goto read_thread_exit;
+                }
+                else if(epoll_events[i].events & EPOLLIN)
+                {
+                    if(ril_cli.cli_fd == epoll_events[i].data.fd)  // Server data arrive.
+                    {
+                        // Read and process every message.
+                        mbtk_ril_err_enum err = MBTK_RIL_ERR_SUCCESS;
+                        ril_msg_pack_info_t **pack = ril_pack_recv(ril_cli.cli_fd, false, &err);
+
+                        // Parse packet error,send error response to client.
+                        if(pack == NULL)
+                        {
+                            if(err != MBTK_RIL_ERR_SUCCESS)
+                            {
+                                LOGE("RSP packet error[%s].", err2str(err));
+                            }
+                        }
+                        else
+                        {
+                            ril_msg_pack_info_t** pack_ptr = pack;
+                            while(*pack_ptr)
+                            {
+                                ril_pack_process(*pack_ptr);
+                                ril_msg_pack_free(*pack_ptr);
+                                pack_ptr++;
+                            }
+                            free(pack);
+                        }
+                    }
+                    else if(ril_cli.exit_fd[0] == epoll_events[i].data.fd) //
+                    {
+                        char buff[100] = {0};
+                        int len = read(ril_cli.exit_fd[0], buff, 100);
+                        if(len > 0)
+                        {
+                            LOGI("CMD : %s", buff);
+                            if(strcmp(buff, "EXIT") == 0)
+                            {
+                                goto read_thread_exit;
+                            }
+                            else
+                            {
+                                LOGE("Unkonw cmd : %s", buff);
+                            }
+                        }
+                        else
+                        {
+                            LOGE("sock_read() fail.");
+                        }
+                    }
+                    else
+                    {
+                        LOGE("Unknown socket : %d", epoll_events[i].data.fd);
+                    }
+                }
+                else
+                {
+                    LOGE("Unknown event : %x", epoll_events[i].events);
+                }
+            }
+        }
+        else
+        {
+            LOGE("epoll_wait() fail[%d].", errno);
+        }
+    }
+
+read_thread_exit:
+    LOGD("info_read thread exit.");
+    return NULL;
+}
+
+/*
+* Return recv data length.
+* -1 : fail.
+*/
+static mbtk_ril_err_enum ril_req_process(ril_msg_id_enum  id,
+                             const void         *req,
+                             int                req_len,
+                             void               *rsp,
+                             bool is_async)
+{
+    ril_msg_pack_info_t* pack = ril_msg_pack_creat(RIL_MSG_TYPE_REQ, id, RIL_MSG_INDEX_AUTO, req, req_len);
+    if(pack == NULL)
+    {
+        return MBTK_RIL_ERR_MEMORY;
+    }
+
+    ril_msg_info_t *msg_info = (ril_msg_info_t*)malloc(sizeof(ril_msg_info_t));
+    if(msg_info == NULL)
+    {
+        ril_msg_pack_free(pack);
+        return MBTK_RIL_ERR_MEMORY;
+    }
+
+    int rsp_data_len = 0;
+    int rsp_err = MBTK_RIL_ERR_SUCCESS;
+
+    pthread_mutex_lock(&ril_cli.send_mutex);
+    // Add to msg list.
+    msg_info->pid = pthread_self();
+    msg_info->pack = pack;
+    msg_info->rsp_data_len = &rsp_data_len;
+    msg_info->rsp_err = &rsp_err;
+    if(!is_async) { // Waitting for response for sync request.
+        msg_info->rsp_data = rsp;   // Save response data.
+    } else {
+        msg_info->rsp_data = NULL;
+    }
+    msg_info->is_async = is_async;
+    list_add(ril_cli.msg_list, msg_info);
+    pthread_mutex_unlock(&ril_cli.send_mutex);
+
+    ril_cli_thread_info_t* cli_thread = thread_find_by_pid(msg_info->pid);
+    // Send pack to server success.
+    if(ril_pack_send(ril_cli.cli_fd, pack) >= RIL_SOCK_PACK_LEN_MIN) {
+        if(!is_async) { // Waitting for response for sync request.
+            ril_thread_wait(cli_thread);
+        }
+
+        LOGD("REQ(%s) success.", id2str(id));
+        return rsp_err;
+    } else {
+        if(list_remove(ril_cli.msg_list, msg_info)) {
+            ril_msg_pack_free(msg_info->pack);
+            free(msg_info);
+        }
+        return MBTK_RIL_ERR_SEND_PACK;
+    }
+}
+
+static void msg_list_free_cb(void *data)
+{
+    if(data) {
+        ril_msg_info_t *msg = (ril_msg_info_t*)data;
+        if(msg->pack) {
+            free(msg->pack);
+        }
+        free(msg);
+    }
+}
+
+static void cli_thread_list_free_cb(void *data)
+{
+    if(data) {
+        ril_cli_thread_info_t *cli_thread = (ril_cli_thread_info_t*)data;
+        pthread_mutex_destroy(&cli_thread->mutex);
+        pthread_cond_destroy(&cli_thread->cond);
+        free(cli_thread);
+    }
+}
+
+mbtk_ril_err_enum mbtk_ril_init()
+{
+    if(ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_INITED;
+    }
+
+    ril_cli.cli_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+    if(ril_cli.cli_fd < 0)
+    {
+        LOGE("socket() fail[%d].", errno);
+        return MBTK_RIL_ERR_UNKNOWN;
+    }
+
+    // Set O_NONBLOCK
+    int flags = fcntl(ril_cli.cli_fd, F_GETFL, 0);
+    if (flags < 0)
+    {
+        LOGE("Get flags error:%d", errno);
+        goto error;
+    }
+    flags |= O_NONBLOCK;
+    if (fcntl(ril_cli.cli_fd, F_SETFL, flags) < 0)
+    {
+        LOGE("Set flags error:%d", errno);
+        goto error;
+    }
+
+    struct sockaddr_un cli_addr;
+    memset(&cli_addr, 0, sizeof(cli_addr));
+    cli_addr.sun_family = AF_LOCAL;
+    strcpy(cli_addr.sun_path, RIL_SOCK_NAME);
+    if(connect(ril_cli.cli_fd, (struct sockaddr *)&cli_addr, sizeof(cli_addr)))
+    {
+        LOGE("connect() fail[%d].", errno);
+        goto error;
+    }
+
+    if(pipe(ril_cli.exit_fd))
+    {
+        LOGE("pipe() fail[%d].", errno);
+        goto error;
+    }
+
+#if 1
+    pthread_attr_t thread_attr;
+    pthread_attr_init(&thread_attr);
+    if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
+    {
+        LOGE("pthread_attr_setdetachstate() fail.");
+        goto error;
+    }
+
+    if(pthread_create(&ril_cli.read_thread_id, &thread_attr, ril_read_run, NULL))
+    {
+        LOGE("pthread_create() fail.");
+        goto error;
+    }
+    pthread_attr_destroy(&thread_attr);
+#else
+    if(pthread_create(&read_thread_id, NULL, ril_read_run, NULL))
+    {
+        LOGE("pthread_create() fail.");
+        goto error;
+    }
+#endif
+
+    pthread_mutex_init(&ril_cli.send_mutex, NULL);
+    ril_cli.msg_list = list_create(msg_list_free_cb);
+    if(ril_cli.msg_list == NULL) {
+        LOGE("list_create(msg_list) fail.");
+        goto error;
+    }
+
+    ril_cli.cli_thread_list = list_create(cli_thread_list_free_cb);
+    if(ril_cli.cli_thread_list == NULL) {
+        LOGE("list_create(cli_thread_list) fail.");
+        goto error;
+    }
+
+    ril_cli.ril_ready = FALSE;
+
+    // Waitting mbtk_rild ready...
+    while(!ril_cli.ril_ready) {
+        usleep(100000);
+    }
+
+    LOGD("RIL server ready...");
+
+    return MBTK_RIL_ERR_SUCCESS;
+error:
+    if(ril_cli.cli_fd > 0)
+    {
+        close(ril_cli.cli_fd);
+        ril_cli.cli_fd = -1;
+    }
+    if(ril_cli.exit_fd[0] > 0)
+    {
+        close(ril_cli.exit_fd[0]);
+        ril_cli.exit_fd[0] = -1;
+    }
+    if(ril_cli.exit_fd[1] > 0)
+    {
+        close(ril_cli.exit_fd[1]);
+        ril_cli.exit_fd[1] = -1;
+    }
+
+    return MBTK_RIL_ERR_UNKNOWN;
+}
+
+mbtk_ril_err_enum mbtk_ril_deinit()
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(ril_cli.exit_fd[1] > 0)
+    {
+        if(write(ril_cli.exit_fd[1], "EXIT", 4) != 4) {
+            return MBTK_RIL_ERR_UNKNOWN;
+        }
+    }
+
+    // Wait read_thread exit.
+    pthread_join(ril_cli.read_thread_id,NULL);
+
+    if(ril_cli.exit_fd[0] > 0)
+    {
+        close(ril_cli.exit_fd[0]);
+        ril_cli.exit_fd[0] = -1;
+    }
+
+    if(ril_cli.exit_fd[1] > 0)
+    {
+        close(ril_cli.exit_fd[1]);
+        ril_cli.exit_fd[1] = -1;
+    }
+
+    if(ril_cli.cli_fd > 0)
+    {
+        close(ril_cli.cli_fd);
+        ril_cli.cli_fd = -1;
+    }
+
+    pthread_mutex_destroy(&ril_cli.send_mutex);
+    if(ril_cli.msg_list) {
+        list_free(ril_cli.msg_list);
+    }
+    if(ril_cli.cli_thread_list) {
+        list_free(ril_cli.cli_thread_list);
+    }
+
+    ril_cli.ril_ready = FALSE;
+
+    return MBTK_RIL_ERR_SUCCESS;
+}
+
+/*
+* Get platform version.
+*/
+mbtk_ril_err_enum mbtk_version_get(void *version)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(version == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_DEV_VERSION, NULL, 0, version, FALSE);
+}
+
+/*
+* Get platform version.
+*/
+mbtk_ril_err_enum mbtk_model_get(void *model)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(model == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_DEV_MODEL, NULL, 0, model, FALSE);
+}
+
+/*
+* Get platform IMEI.
+*/
+mbtk_ril_err_enum mbtk_imei_get(void *imei)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(imei == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_DEV_IMEI, NULL, 0, imei, FALSE);
+}
+
+
+/*
+* Get platform SN.
+*/
+mbtk_ril_err_enum mbtk_sn_get(void *sn)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(sn == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_DEV_SN, NULL, 0, sn, FALSE);
+}
+
+
+/*
+* Get platform MEID.
+*/
+mbtk_ril_err_enum mbtk_meid_get(void *meid)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(meid == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_DEV_MEID, NULL, 0, meid, FALSE);
+}
+
+
+/*
+* Return VoLTE state.
+*/
+mbtk_ril_err_enum mbtk_volte_state_get(int *volte_state)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(volte_state == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_DEV_VOLTE, NULL, 0, volte_state, FALSE);
+}
+
+/*
+* Set VoLTE state.
+*
+* volte_state:
+* 0 : Close VoLTE.
+* 1 : Open VoLTE.
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_volte_state_set(int volte_state)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(volte_state != 0 && volte_state != 1)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_DEV_VOLTE, &volte_state, 1, NULL, FALSE);
+}
+
+/*
+* Return radio state.
+*/
+mbtk_ril_err_enum mbtk_radio_state_get(mbtk_radio_state_enum *radio_state)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(radio_state == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    uint8 result;
+    mbtk_ril_err_enum err = ril_req_process(RIL_MSG_ID_DEV_MODEM, NULL, 0, &result, FALSE);
+    *radio_state = (mbtk_radio_state_enum)result;
+    return err;
+}
+
+/*
+* Set radio state.
+*
+* Refor to : mbtk_radio_state_enum
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_radio_state_set(mbtk_radio_state_enum radio_state, bool reset_modem)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(radio_state == MBTK_RADIO_STATE_UNKNOWN)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    uint8 buff[2];
+    buff[0] = (uint8)radio_state;
+    buff[1] = reset_modem ? 1 : 0;
+
+    return ril_req_process(RIL_MSG_ID_DEV_MODEM, buff, 2, NULL, FALSE);
+}
+
+/*
+* Get system temperature.
+*
+* type[IN]:
+*   0: Soc temperature.
+*   1: RF temperature.
+* temp[OUT]:
+*   temperature in celsius.
+*/
+mbtk_ril_err_enum mbtk_temp_get(mbtk_temp_type_enum type, int* temp)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(temp == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    int16 result;
+    uint8 temp_temp = (uint8)type;
+    mbtk_ril_err_enum err = ril_req_process(RIL_MSG_ID_DEV_TEMP, &temp_temp, 1, &result, FALSE);
+    *temp = (int16)result;
+    return err;
+}
+
+
+/*
+* Get time type.
+* "23/05/24,06:09:32+32" -> "23/05/24 06:09:32 +32 00"
+*/
+mbtk_ril_err_enum mbtk_cell_time_get(char* time_str)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(time_str == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    char buff[RIL_SOCK_MSG_LEN_MAX] = {0};
+    mbtk_ril_err_enum err = ril_req_process(RIL_MSG_ID_DEV_CELL_TIME, NULL, 0, &buff, FALSE);
+    if(MBTK_RIL_ERR_SUCCESS == err)
+    {
+        memcpy(time_str,buff,strlen(buff));
+
+        char *temp = strstr(time_str, ",");
+        if(temp)
+        {
+            *temp = ' '; // ',' -> ' '
+
+            temp = strstr(time_str, "+");
+            if(temp == NULL)
+            {
+                temp = strstr(time_str, "-");
+            }
+
+            if(temp)
+            {
+                // Copy +XX or -XX
+                char *last_ptr = temp + strlen(temp) + 1;
+                while(last_ptr > temp)
+                {
+                    *last_ptr = *(last_ptr - 1);
+                    last_ptr--;
+                }
+
+                *last_ptr = ' ';
+
+                memcpy(temp + strlen(temp), " 00", 3);
+
+                LOGD("%s -> %s", buff, time_str);
+                return MBTK_RIL_ERR_SUCCESS;
+            }
+            else
+            {
+                LOGE("Time error:%s",buff);
+                return MBTK_RIL_ERR_TIME_FORMAT;
+            }
+        }
+        else
+        {
+            LOGE("Time error:%s",buff);
+            return MBTK_RIL_ERR_TIME_FORMAT;
+        }
+    }
+    else
+    {
+        return err;
+    }
+}
+
+/*
+* Get sim state.
+*/
+mbtk_ril_err_enum mbtk_sim_state_get(mbtk_sim_state_enum *sim_state)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(sim_state == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    uint8 result;
+    mbtk_ril_err_enum err = ril_req_process(RIL_MSG_ID_SIM_STATE, NULL, 0, &result, FALSE);
+    *sim_state = (mbtk_sim_state_enum)result;
+    return err;
+}
+
+/*
+* Get sim card type.
+*/
+mbtk_ril_err_enum mbtk_sim_type_get(mbtk_sim_card_type_enum *sim_card_type)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(sim_card_type == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    uint8 result;
+    mbtk_ril_err_enum err = ril_req_process(RIL_MSG_ID_SIM_TYPE, NULL, 0, &result, FALSE);
+    *sim_card_type = (mbtk_sim_card_type_enum)result;
+    return err;
+}
+
+/*
+* Get platform IMSI.
+*/
+mbtk_ril_err_enum mbtk_imsi_get(void *imsi)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(imsi == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SIM_IMSI, NULL, 0, imsi, FALSE);
+}
+
+/*
+* Get platform ICCID.
+*/
+mbtk_ril_err_enum mbtk_iccid_get(void *iccid)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(iccid == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SIM_ICCID, NULL, 0, iccid, FALSE);
+}
+
+/*
+* Get current phone number.
+*/
+mbtk_ril_err_enum mbtk_phone_number_get(void *phone_number)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(phone_number == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SIM_PN, NULL, 0, phone_number, FALSE);
+}
+
+/*
+* Get platform ICCID.
+*/
+mbtk_ril_err_enum mbtk_sim_lock_get(int *lock_state)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(lock_state == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    uint8 result;
+    mbtk_ril_err_enum err = ril_req_process(RIL_MSG_ID_SIM_LOCK, NULL, 0, &result, FALSE);
+    *lock_state = result;
+    return err;
+}
+
+
+/*
+* Get platform ICCID.
+*/
+mbtk_ril_err_enum mbtk_sim_lock_set(mbtk_sim_lock_info_t *lock_info)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(lock_info == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SIM_LOCK, lock_info, sizeof(mbtk_sim_lock_info_t), NULL, FALSE);
+}
+
+/*
+* Get PIN’s number of remaining retry
+*/
+mbtk_ril_err_enum mbtk_sim_lock_retry_times_get(mbtk_pin_puk_last_times_t *retry_times)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(retry_times == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SIM_PINPUK_TIMES, NULL, 0, retry_times, FALSE);
+}
+
+/*
+* Get plmn list
+*/
+mbtk_ril_err_enum mbtk_plmn_list_get(mbtk_plmn_info *plmn_list)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(plmn_list == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SIM_PLMN, NULL, 0, plmn_list, FALSE);
+}
+
+/*
+* Get available network.
+*/
+mbtk_ril_err_enum mbtk_available_net_get(mbtk_net_info_array_t *net_array)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(net_array == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_AVAILABLE, NULL, 0, net_array, FALSE);
+}
+
+/*
+* Set network select mode. (+COPS=...)
+*/
+mbtk_ril_err_enum mbtk_net_sel_mode_set(const mbtk_net_info_t *net)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(net == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_SEL_MODE, net, sizeof(mbtk_net_info_t), NULL, FALSE);
+}
+
+/*
+* Get network select mode. (+COPS?)
+*/
+mbtk_ril_err_enum mbtk_net_sel_mode_get(mbtk_net_info_t *net)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(net == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_SEL_MODE, NULL, 0, net, FALSE);
+}
+
+/*
+* Get platform support bands.
+*/
+mbtk_ril_err_enum mbtk_support_band_get(mbtk_band_info_t *band)
+{
+    uint8 type = 0; // Get support bands.
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(band == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_BAND, &type, sizeof(uint8), band, FALSE);
+}
+
+/*
+* Get platform current bands.
+*/
+mbtk_ril_err_enum mbtk_current_band_get(mbtk_band_info_t *band)
+{
+    uint8 type = 1; // Get current bands.
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(band == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_BAND, &type, sizeof(uint8), band, FALSE);
+}
+
+/*
+* Set platform current bands.
+*/
+mbtk_ril_err_enum mbtk_current_band_set(const mbtk_band_info_t *band)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(band == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_BAND, band, sizeof(mbtk_band_info_t), NULL, FALSE);
+}
+
+/*
+* Get current cell infomation.
+*/
+mbtk_ril_err_enum mbtk_cell_get(mbtk_cell_info_array_t *cell_array)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(cell_array == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_CELL, NULL, 0, cell_array, FALSE);
+}
+/*
+* Set cell info.
+*
+* at*CELL=<mode>,<act>,< band>,<freq>,<cellId>
+* at*cell=2,3,,40936,429   //
+* at*cell=0  //
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_cell_set(const mbtk_cell_info_t *cell_info)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(cell_info == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_CELL, cell_info, sizeof(mbtk_cell_info_t), NULL, FALSE);
+}
+
+/*
+* Get current network signal.
+*/
+mbtk_ril_err_enum mbtk_net_signal_get(mbtk_signal_info_t *signal)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(signal == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_SIGNAL, NULL, 0, signal, FALSE);
+}
+
+/*
+* Get current network register information.
+*/
+mbtk_ril_err_enum mbtk_net_reg_get(mbtk_net_reg_info_t *reg)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(reg == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_REG, NULL, 0, reg, FALSE);
+}
+
+/*
+* Get all APN informations.
+*/
+mbtk_ril_err_enum mbtk_apn_get(mbtk_apn_info_array_t *apns)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(apns == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_APN, NULL, 0, apns, FALSE);
+}
+
+
+/*
+* Set current APN informations.
+*/
+mbtk_ril_err_enum mbtk_apn_set(const mbtk_apn_info_t *apn)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(apn == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_APN, apn, sizeof(mbtk_apn_info_t), NULL, FALSE);
+}
+
+/*
+* Start data call.
+*/
+mbtk_ril_err_enum mbtk_data_call_start(mbtk_ril_cid_enum cid, bool auto_boot_call,
+            bool def_route, int retry_interval, int timeout, mbtk_ip_info_t *rsp_info)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    mbtk_data_call_info_t info;
+    memset(&info, 0, sizeof(mbtk_data_call_info_t));
+    info.type = MBTK_DATA_CALL_START;
+    info.auto_boot_call = (uint8)auto_boot_call;
+    info.def_route = (uint8)def_route;
+    info.retry_interval = (uint16)retry_interval;
+    if(timeout > 0) {
+        info.timeout = (uint16)timeout;
+    }
+
+    return ril_req_process(RIL_MSG_ID_NET_DATA_CALL, &info, sizeof(mbtk_data_call_info_t), rsp_info, FALSE);
+}
+
+/*
+* Stop data call.
+*/
+mbtk_ril_err_enum mbtk_data_call_stop(mbtk_ril_cid_enum cid, int timeout)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    mbtk_data_call_info_t info;
+    memset(&info, 0, sizeof(mbtk_data_call_info_t));
+    info.type = MBTK_DATA_CALL_STOP;
+    if(timeout > 0) {
+        info.timeout = (uint16)timeout;
+    }
+    return ril_req_process(RIL_MSG_ID_NET_DATA_CALL, &info, sizeof(mbtk_data_call_info_t), NULL, FALSE);
+}
+
+/*
+* Get data call state.
+*/
+mbtk_ril_err_enum mbtk_data_call_state_get(int cid, mbtk_ip_info_t *ip)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(ip == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    mbtk_data_call_info_t info;
+    memset(&info, 0, sizeof(mbtk_data_call_info_t));
+    info.type = MBTK_DATA_CALL_STATE;
+
+    return ril_req_process(RIL_MSG_ID_NET_DATA_CALL, &info, sizeof(mbtk_data_call_info_t), ip, FALSE);
+}
+
+/*
+* Return sms cmgf.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgf_get(int *sms_state)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(sms_state == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    uint8 state;
+    mbtk_ril_err_enum err = ril_req_process(RIL_MSG_ID_SMS_CMGF, NULL, 0, &state, FALSE);
+    *sms_state = state;
+    return err;
+}
+
+/*
+* Set sms cmgf.
+*
+* volte_state:
+* 0 : PDU mode.
+* 1 :  text mode.
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgf_set(int mode)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CMGF, &mode, sizeof(uint8), NULL, FALSE);
+}
+
+/*
+* Set sms cmgs.
+*
+if PDU mode (+CMGF=0):
++CMGS=<length><CR>
+PDU is given<ctrl-Z/ESC>
+
+if text mode (+CMGF=1):
++CMGS=<da>[,<toda>]<CR>
+text is entered<ctrl-Z/ESC>
+
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgs_set(char * cmgs, char *resp)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(cmgs == NULL || resp == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CMGS, cmgs, strlen(cmgs), resp, FALSE);
+}
+
+/*
+* Set sms cmgw.
+*
+if text mode (+CMGF=1):
++CMGW=<oa/da>[,<tooa/toda>[,<stat>]]
+<CR>
+text is entered<ctrl-Z/ESC>
+if PDU mode (+CMGF=0):
++CMGW=<length>[,<stat>]<CR>PDU is
+given<ctrl-Z/ESC>
+
+*/
+mbtk_ril_err_enum mbtk_sms_cmgw_set(char * cmgw, char *resp)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(cmgw == NULL || resp == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CMGW, cmgw, strlen(cmgw), resp, FALSE);
+}
+
+/*
+* Set sms cmgd.
+*
+* +CMGD=<index>[,<delflag>]
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgd_set(char * cmdg)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(cmdg == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CMGD, cmdg, strlen(cmdg), NULL, FALSE);
+}
+
+/*
+* Get sms cmgd.
+*
+* +CMGD: (XXX,XXX)(0-4)
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgd_get(char * cmdg)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(cmdg == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CMGD, NULL, 0, cmdg, FALSE);
+}
+
+
+/*
+* Set sms cmgl.
+*
+* AT+CMGL[=<stat>]
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgl_set(char * cmgl, char *resp)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(cmgl == NULL || resp == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CMGL, cmgl, strlen(cmgl), resp, FALSE);
+}
+
+/*
+* Return sms csca.
+*/
+mbtk_ril_err_enum mbtk_sms_csca_get(char *buf)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(buf == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CSCA, NULL, 0, buf, FALSE);
+}
+
+/*
+* Set sms csca.
+*
+* AT+CSCA=<number> [,<type>]
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_csca_set(char * csca)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(csca == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CSCA, csca, strlen(csca), NULL, FALSE);
+}
+
+/*
+* Set sms csmp.
+*
+* AT+CSMP=[<fo>[,<vp>[,<pid>[,<dcs>]]]]
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_csmp_set(char * csmp)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(csmp == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CSMP, csmp, strlen(csmp), NULL, FALSE);
+}
+
+/*
+* Set sms cscb.
+*
+* AT+CSCB=<[<mode>[,<mids>[,<dcss>]]]>
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cscb_set(char * cscb)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(cscb == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CSCB, cscb, strlen(cscb), NULL, FALSE);
+}
+
+/*
+* Set sms cnmi.
+*
+at+cnmi=1,2
+
+OK
+if sending fails:
++CMS ERROR: <err>
+*/
+mbtk_ril_err_enum mbtk_sms_cnmi_set()
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CNMI, NULL, 0, NULL, FALSE);
+}
+
+/*
+* Set sms cmss.
+*
++CMSS=<index>[,<da>[,<toda>]]
+
+if sending successful:
++CMSS: <mr>
+OK
+if sending fails:
++CMS ERROR: <err>
+*/
+mbtk_ril_err_enum mbtk_sms_cmss_set(char * cmss, char *resp)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(cmss == NULL || resp == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CMSS, cmss, strlen(cmss), resp, FALSE);
+}
+
+/*
+* Return sms cmgf.
+*/
+mbtk_ril_err_enum mbtk_sms_cpms_get(char * mem)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(mem == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CPMS, NULL, 0, mem, FALSE);
+}
+
+
+/*
+* Set sms cpms.
+*
+* AT+CPMS=<mem1>[,<mem2>[,<mem3>]]
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cpms_set(char * mem, char* resp)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(mem == NULL || resp == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CPMS, mem, strlen(mem), resp, FALSE);
+}
+
+/*
+* Set sms cm.
+*
+* +CMGR=<index>
+
+if PDU mode (+CMGF=0) ��command successful:
++CMGR: <stat>,[<alpha>],<length><CR><LF><pdu>
+OK
+if text mode (+CMGF=1), command successful and SMS-DELIVER:
++CMGR:<stat>,<oa>,[<alpha>],<scts>[,<tooa>,<fo>,<pid>,<dcs
+>, <sca>,<tosca>,<length>]<CR><LF><data>
+OK
+if text mode (+CMGF=1), command successful and SMS-SUBMIT:
++CMGR:
+<stat>,<da>,[<alpha>][,<toda>,<fo>,<pid>,<dcs>,[<vp>],
+<sca>,<tosca>,<length>]<CR><LF><data>
+OK
+otherwise:
++CMS ERROR: <err>
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_sms_cmgr_set(int index, char *resp)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(resp == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_SMS_CMGR, &index, sizeof(uint8), resp, FALSE);
+}
+
+
+#if 0
+
+/*
+* Set sim power state.
+* power:
+* 0: Sim power off.
+* 1: Sim power on.
+*/
+int mbtk_sim_power_set(int power)
+{
+    if(power != 0 && power != 1)
+    {
+        return -1;
+    }
+
+    //  /sys/devices/virtual/usim_event/usim0/send_event
+    char cmd[100] = {0};
+    sprintf(cmd, "echo %d > /sys/devices/virtual/usim_event/usim0/send_event", power ? 0 : 1);
+    system(cmd);
+
+    return 0;
+}
+
+/*
+* System power.
+* type:
+* 0: Reboot system.
+* 1: Poweroff system.
+* 2: Halt system.
+*/
+int mbtk_system_reboot(int type)
+{
+    if(type != 0 && type != 1 && type != 2)
+    {
+        return -1;
+    }
+
+    switch(type)
+    {
+        case 0:
+        {
+            system("reboot");
+            break;
+        }
+        case 1:
+        {
+            system("poweroff");
+            break;
+        }
+        case 2:
+        {
+            system("halt");
+            break;
+        }
+        default:
+        {
+            break;
+        }
+    }
+
+    return 0;
+}
+
+/*
+* Get time type.
+*/
+int mbtk_time_get(mbtk_info_handle_t* handle, int *time_type)
+{
+    uint8 state;
+    if(handle == NULL || time_type == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+    if(info_item_process(handle, MBTK_INFO_ID_DEV_TIME_REQ, NULL, 0, &state) > 0)
+    {
+        LOG("Time type : %d", state);
+        *time_type = state;
+        return 0;
+    }
+    else
+    {
+        return handle->info_err;
+    }
+}
+
+/*
+*Get Absolute time
+*"23/05/24 06:09:32 +32 00"
+*/
+int mbtk_get_abs_time(char *time_str, time_t *time_out)
+{
+    struct tm tm_;
+
+    char *ptr = strstr(time_str + 10, " ");
+    *ptr = '\0';
+
+    LOGD("time : \"%s\"", time_str);
+#if 1
+    if(strptime(time_str, "%y/%m/%d %T", &tm_) == NULL)
+    {
+        LOGE("strptime() fail.");
+        return -1;
+    }
+#else
+    int year, month, day, hour, minute,second,time_zone;
+    if(strstr(time_str, "+"))
+    {
+        sscanf(time_str, "%d/%d/%d %d:%d:%d +%d",&year,&month,&day,&hour,&minute,&second,&time_zone);
+    }
+    else if(strstr(time_str, "-"))
+    {
+        sscanf(time_str, "%d/%d/%d %d:%d:%d -%d",&year,&month,&day,&hour,&minute,&second,&time_zone);
+    }
+    else
+    {
+        LOGE("Time format error:%s", time_str);
+        return -1;
+    }
+
+    // 1970+
+    if(year < 70)   // 20xx
+    {
+        tm_.tm_year  = 2000 + year;
+    }
+    else     // 19xx
+    {
+        tm_.tm_year  = 1900 + year;
+    }
+    tm_.tm_mon   = month - 1;
+    tm_.tm_mday  = day;
+    tm_.tm_hour  = hour;
+    tm_.tm_min   = minute;
+    tm_.tm_sec   = second;
+    tm_.tm_isdst = 0;
+#endif
+
+    time_t timeStamp = mktime(&tm_);
+    LOGD("tm_.tm_year = %d,tm_.tm_mon = %d,tm_.tm_mday = %d,tm_.tm_hour = %d,tm_.tm_min = %d,tm_.tm_sec = %d,tm_.tm_isdst = %d",tm_.tm_year,tm_.tm_mon,tm_.tm_mday,tm_.tm_hour,tm_.tm_min,tm_.tm_sec,tm_.tm_isdst);
+    LOGD("time = %ld,%x", timeStamp,timeStamp);
+    *time_out = timeStamp;
+
+    return 0;
+}
+
+/*
+* Set time.
+*
+* time_type:
+* 0: Cell time
+* 1: NTP time
+* 2: User time
+* time_str: "YYYY-MM-DD HH:MM:SS"
+*/
+int mbtk_time_set(mbtk_info_handle_t* handle, mbtk_time_type_enum time_type, char* time_str)
+{
+    if(handle == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+    uint8 buffer[100] = {0};
+    buffer[0] = (uint8)time_type;
+    if(time_type == MBTK_TIME_TYPE_USER)
+    {
+        if(!str_empty(time_str))
+        {
+            memcpy(buffer + sizeof(uint8), time_str, strlen(time_str));
+            return info_item_process(handle, MBTK_INFO_ID_DEV_TIME_REQ,
+                                     buffer, sizeof(uint8) + strlen(time_str), NULL) ? handle->info_err : 0;
+        }
+        else
+        {
+            return -1;
+        }
+    }
+    else
+    {
+        return info_item_process(handle, MBTK_INFO_ID_DEV_TIME_REQ,
+                                 buffer, sizeof(uint8), NULL) ? handle->info_err : 0;
+    }
+}
+
+
+#endif
+
+/*
+* call_start
+*
+*/
+mbtk_ril_err_enum mbtk_call_start(char* phone_number)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(phone_number == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_CALL_START, phone_number, strlen(phone_number), NULL, FALSE);
+}
+
+/*
+* Answer the phone call.
+*
+*/
+mbtk_ril_err_enum mbtk_call_answer()
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    return ril_req_process(RIL_MSG_ID_CALL_ANSWER, NULL, 0, NULL, FALSE);
+}
+
+/*
+* Hang up all call.
+*
+*/
+mbtk_ril_err_enum mbtk_call_hang()
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    return ril_req_process(RIL_MSG_ID_CALL_HANGUP, NULL, 0, NULL, FALSE);
+}
+
+/*
+* Hang up a call.
+*
+*/
+mbtk_ril_err_enum mbtk_a_call_hang(int phone_id)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    return ril_req_process(RIL_MSG_ID_CALL_HANGUP_A, &phone_id, sizeof(uint8), NULL, FALSE);
+}
+
+/*
+* Hang up waiting or background call.
+*
+*/
+mbtk_ril_err_enum mbtk_waiting_or_background_call_hang()
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    return ril_req_process(RIL_MSG_ID_CALL_HANGUP_B, NULL, 0, NULL, FALSE);
+}
+
+/*
+* Hang up foreground resume background call.
+*
+*/
+mbtk_ril_err_enum mbtk_foreground_resume_background_call_hang()
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    return ril_req_process(RIL_MSG_ID_CALL_HANGUP_C, NULL, 0, NULL, FALSE);
+}
+
+/*
+* Get current call phone number.
+*/
+mbtk_ril_err_enum mbtk_call_reg_get(mbtk_call_info_t *reg)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(reg == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_CALL_WAITIN, NULL, 0, reg, FALSE);
+}
+
+/*
+* Return mute state.
+*/
+mbtk_ril_err_enum mbtk_mute_state_get(int *mute_state)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(mute_state == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_CALL_MUTE, NULL, 0, mute_state, FALSE);
+}
+
+/*
+* Set mute state.
+*
+* mute_state:
+* 0 : of mute.
+* 1 : on mute.
+*
+* Restarting takes effect after execution.
+*/
+mbtk_ril_err_enum mbtk_mute_state_set(int mute_state)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    return ril_req_process(RIL_MSG_ID_CALL_MUTE, &mute_state, sizeof(uint8), NULL, FALSE);
+}
+
+/*
+* Set DTMF character.
+*
+*/
+mbtk_ril_err_enum mbtk_dtmf_send(mbtk_call_dtmf_info_t *dtmf_character)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(dtmf_character == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_CALL_DTMF, dtmf_character, sizeof(mbtk_call_dtmf_info_t), NULL, FALSE);
+}
+
+
+#if 0
+/*
+* Set wakeup state.
+*
+* wakeup_state:(0~31)
+* 0 : means resume all
+* 1~31 means suspend
+* Control the active reporting of some platform modems to reduce wakeup
+*/
+
+int mbtk_wakeup_state_set(mbtk_info_handle_t* handle, uint32 wakeup_state)
+{
+    return info_item_process(handle, MBTK_INFO_ID_WAKEUP_STA_REQ, (uint32*)&wakeup_state, sizeof(uint32), NULL) ? handle->info_err : 0;
+}
+
+/*
+* oos get.
+*/
+int mbtk_oos_get(mbtk_info_handle_t* handle, mbtk_oos_info *oos_info)
+{
+    if(info_item_process(handle, MBTK_INFO_ID_OOS_STA_REQ, NULL, 0, oos_info) > 0)
+    {
+        return 0;
+    }
+    else
+    {
+        return handle->info_err;
+    }
+}
+
+/*
+* oos set .
+*/
+int mbtk_oos_set(mbtk_info_handle_t* handle, mbtk_oos_info *oos_info)
+{
+    if(handle == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+
+    return info_item_process(handle, MBTK_INFO_ID_OOS_STA_REQ, oos_info, sizeof(mbtk_oos_info), NULL) ? handle->info_err : 0;
+}
+
+
+#endif
+
+#if 0
+/*
+* Set pdp state change callback function.
+*/
+int mbtk_pdp_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+{
+    if(handle == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+    if(info_item_process(handle, MBTK_INFO_ID_IND_PDP_STATE_CHANGE, NULL, 0, NULL) < 0)
+    {
+        return handle->info_err;
+    }
+    else
+    {
+        handle->pdp_state_cb = cb;
+        return 0;
+    }
+}
+
+/*
+* Set network state change callback function.
+*/
+int mbtk_net_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+{
+    if(handle == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+    if(info_item_process(handle, MBTK_INFO_ID_IND_NET_STATE_CHANGE, NULL, 0, NULL) < 0)
+    {
+        return handle->info_err;
+    }
+    else
+    {
+        handle->net_state_cb = cb;
+        return 0;
+    }
+}
+
+/*
+* Set call state change callback function.
+*/
+int mbtk_call_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+{
+    if(handle == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+    if(info_item_process(handle, MBTK_INFO_ID_IND_CALL_STATE_CHANGE, NULL, 0, NULL) < 0)
+    {
+        return handle->info_err;
+    }
+    else
+    {
+        handle->call_state_cb = cb;
+        return 0;
+    }
+}
+
+/*
+* Set sms state change callback function.
+*/
+int mbtk_sms_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+{
+    if(handle == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+    if(info_item_process(handle, MBTK_INFO_ID_IND_SMS_STATE_CHANGE, NULL, 0, NULL) < 0)
+    {
+        return handle->info_err;
+    }
+    else
+    {
+        handle->sms_state_cb = cb;
+        return 0;
+    }
+}
+
+/*
+* Set radio state change callback function.
+*/
+int mbtk_radio_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+{
+    if(handle == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+    if(info_item_process(handle, MBTK_INFO_ID_IND_RADIO_STATE_CHANGE, NULL, 0, NULL) < 0)
+    {
+        return handle->info_err;
+    }
+    else
+    {
+        handle->radio_state_cb = cb;
+        return 0;
+    }
+}
+
+/*
+* Set sim state change callback function.
+*/
+int mbtk_sim_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+{
+    if(handle == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+    if(info_item_process(handle, MBTK_INFO_ID_IND_SIM_STATE_CHANGE, NULL, 0, NULL) < 0)
+    {
+        return handle->info_err;
+    }
+    else
+    {
+        handle->sim_state_cb = cb;
+        return 0;
+    }
+}
+
+/*
+* Set signal state change callback function.
+*/
+int mbtk_signal_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+{
+    if(handle == NULL)
+    {
+        LOGE("ARG error.");
+        return -1;
+    }
+    if(info_item_process(handle, MBTK_INFO_ID_IND_SIGNAL_STATE_CHANGE, NULL, 0, NULL) < 0)
+    {
+        return handle->info_err;
+    }
+    else
+    {
+        handle->signal_state_cb = cb;
+        return 0;
+    }
+}
+#endif
diff --git a/mbtk/libmbtk_ril_v2/src/ril_utils.c b/mbtk/libmbtk_ril_v2/src/ril_utils.c
new file mode 100755
index 0000000..f71b2dd
--- /dev/null
+++ b/mbtk/libmbtk_ril_v2/src/ril_utils.c
@@ -0,0 +1,556 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <string.h>
+
+#include "mbtk_ril.h"
+#include "mbtk_list.h"
+#include "mbtk_utils.h"
+
+static uint16 ril_index = 1;
+
+static int sock_read(int fd, uint8 *msg, int data_len)
+{
+    memset(msg, 0, data_len);
+    int len = 0;
+    int read_len = 0;
+    while(1)
+    {
+        len = read(fd, msg + read_len, data_len - read_len);
+        if(len > 0)
+        {
+            read_len += len;
+        }
+        else if(len == 0)
+        {
+            LOG("read() end.");
+            break;
+        }
+        else
+        {
+            if(EAGAIN == errno)
+            {
+                LOG("Read end, lenght = %d", read_len);
+            }
+            else
+            {
+                LOG("read() error[%d].", errno);
+            }
+            break;
+        }
+    }
+
+    if(read_len > 0)
+    {
+        log_hex("DATA_RECV", msg, read_len);
+        return read_len;
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+static int sock_write(int fd, uint8 *msg, int data_len)
+{
+    int len = 0;
+    int write_len = 0;
+    while(write_len < data_len)
+    {
+        len = write(fd, msg + write_len, data_len - write_len);
+        if(len > 0)
+        {
+            write_len += len;
+        }
+        else if(len == 0)
+        {
+            LOG("write() end.");
+            break;
+        }
+        else
+        {
+            LOG("write() error[%d].", errno);
+            break;
+        }
+    }
+
+    if(write_len > 0)
+    {
+        // log_hex("DATA_SEND", msg, write_len);
+        return write_len;
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+static int pack_num_check(const void* data, int data_len)
+{
+    int count = 0;
+    int pack_len;
+    const uint8* ptr = (const uint8*)data;
+    while(ptr < (const uint8*)data + data_len)
+    {
+        if(RIL_SOCK_PACKET_TAG != byte_2_uint32(ptr, false))
+        {
+            LOG("pack_num_check() - TAG error.");
+            break;
+        }
+        ptr += sizeof(uint32);
+
+        pack_len = byte_2_uint16(ptr, false);
+        if(pack_len < RIL_SOCK_PACK_LEN_MIN - RIL_SOCK_PACK_EXTRA_LEN)
+        {
+            LOG("pack_num_check() - Packet length error.");
+            break;
+        }
+        ptr += sizeof(uint16);
+        ptr += pack_len;
+
+        count++;
+    }
+
+    return count;
+}
+
+char* type2str(ril_msg_type_enum type)
+{
+    switch(type)
+    {
+        case RIL_MSG_TYPE_REQ:
+            return "REQ";
+        case RIL_MSG_TYPE_RSP:
+            return "RSP";
+        case RIL_MSG_TYPE_IND:
+            return "IND";
+        default:
+        {
+            return "UNKNOWN";
+        }
+    }
+}
+
+char* apn2str(mbtk_ip_type_enum type)
+{
+    switch(type)
+    {
+        case MBTK_IP_TYPE_IP:
+            return "IP";
+        case MBTK_IP_TYPE_IPV6:
+            return "IPV6";
+        case MBTK_IP_TYPE_IPV4V6:
+            return "IPV4V6";
+        case MBTK_IP_TYPE_PPP:
+            return "PPP";
+        default:
+        {
+            return "UNKNOWN";
+        }
+    }
+}
+
+/*
+IPv6 : 254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239 -> uint128
+*/
+int str_2_ipv6(const void *ip_str, void *ipv6)
+{
+    const uint8 *ptr = (const uint8*)ip_str;
+    uint8 *ipv6_ptr = (uint8*)ipv6;
+    ipv6_ptr[0] = (uint8)atoi(ptr);
+    int i = 1;
+    while(i < 16) {
+        ptr = (const uint8*)strstr(ptr, ".");
+        if(ptr == NULL)
+            return -1;
+        ptr++;
+        ipv6_ptr[i] = (uint8)atoi(ptr);
+        i++;
+    }
+
+    return 0;
+}
+
+/*
+IPv6 : uint128 -> fe80::215:1dff:fe81:484c
+*/
+int ipv6_2_str(const void *ipv6, void *ipv6_str)
+{
+    const uint8 *ptr = (const uint8*)ipv6;
+    uint8 *ipv6_ptr = (uint8*)ipv6_str;
+    int i = 0;
+    int index = 0;
+    while(i < 16) {
+        index += sprintf(ipv6_ptr + index, "%02x%02x", ptr[i], ptr[i + 1]);
+        index += sprintf(ipv6_ptr + index, ":");
+        i += 2;
+    }
+
+    ipv6_ptr[index - 1] = '\0'; // Delete last ':'
+
+    return 0;
+}
+
+
+
+char* id2str(int id)
+{
+    switch(id)
+    {
+        // <string> IMEI
+        case RIL_MSG_ID_DEV_IMEI:
+            return "IMEI";
+        // <string> SN
+        case RIL_MSG_ID_DEV_SN:
+            return "SN";
+        // <string> MEID
+        case RIL_MSG_ID_DEV_MEID:
+            return "MEID";
+        // <string> VERSION
+        case RIL_MSG_ID_DEV_VERSION:
+            return "VERSION";
+        case RIL_MSG_ID_DEV_MODEL:
+            return "MODEL";
+        // <uint8> 0:Close 1:Open
+        case RIL_MSG_ID_DEV_VOLTE:
+            return "VOLTE";
+        // <string> Temperature
+        case RIL_MSG_ID_DEV_TEMP:  // Temperature
+            return "TEMPERATURE";
+        case RIL_MSG_ID_DEV_CELL_TIME:
+            return "CELL_TIME";
+        case RIL_MSG_ID_DEV_MODEM:
+            return "MODEM";
+
+        // Sim Information
+
+        // <uint8> 0:NOT_EXIST 1:READY ...
+        case RIL_MSG_ID_SIM_STATE:
+            return "SIM_STATE";
+        case RIL_MSG_ID_SIM_TYPE:
+            return "SIM_TYPE";
+        // <string> IMSI
+        case RIL_MSG_ID_SIM_IMSI:
+            return "IMSI";
+        // <string> ICCID
+        case RIL_MSG_ID_SIM_ICCID:
+            return "ICCID";
+        // <string> Phone Number
+        case RIL_MSG_ID_SIM_PN:
+            return "PHONE_NUMBER";
+        case RIL_MSG_ID_SIM_LOCK:
+            return "SIM_LOCK";
+        case RIL_MSG_ID_SIM_PINPUK_TIMES:
+            return "SIM_PINPUK_TIMES";
+        case RIL_MSG_ID_SIM_PLMN:
+            return "SIM_PLMN";
+        case RIL_MSG_ID_NET_AVAILABLE:
+            return "NET_AVAILABLE";
+        case RIL_MSG_ID_NET_SEL_MODE:
+            return "NET_SEL_MODE";
+        case RIL_MSG_ID_NET_BAND:
+            return "NET_BNAD";
+        // <uint16>[4]  rssi,rscp,rsrp,snr
+        case RIL_MSG_ID_NET_SIGNAL:
+            return "SIGNAL";
+        case RIL_MSG_ID_NET_REG:
+            return "NET_REG";
+        // <string> cmnet/ctnet/3gnet/...
+        case RIL_MSG_ID_NET_APN:
+            return "APN";
+        // Lock net/cell/frequency
+        case RIL_MSG_ID_NET_CELL:
+            return "NET_CELL";
+        case RIL_MSG_ID_NET_DATA_CALL:
+            return "DATA_CALL";
+        // Call Information
+        case RIL_MSG_ID_CALL_STATE:
+            return "CALL_STATE";
+        // SMS Information
+        case RIL_MSG_ID_SMS_STATE:
+            return "SMS_STATE";
+        // PhoneBook Information
+        case RIL_MSG_ID_PB_STATE:
+            return "PB_STATE";
+        // IND Information
+         // <uint8>  State
+        case RIL_MSG_ID_IND_SER_READY:
+            return "IND_SER_READY";
+        // <uint8>  State
+        case RIL_MSG_ID_IND_NET_STATE_CHANGE:
+            return "IND_NET_STATE";
+        // <uint8>  State
+        case RIL_MSG_ID_IND_CALL_STATE_CHANGE:
+            return "IND_CALL_STATE";
+        // <uint8>  State
+        case RIL_MSG_ID_IND_SMS_STATE_CHANGE:
+            return "IND_SMS_STATE";
+        // <uint8>  State
+        case RIL_MSG_ID_IND_RADIO_STATE_CHANGE:
+            return "IND_RADIO_STATE";
+        // <uint8>  State
+        case RIL_MSG_ID_IND_SIM_STATE_CHANGE:
+            return "IND_SIM_STATE";
+        // <uint8>  State
+        case RIL_MSG_ID_IND_PDP_STATE_CHANGE:
+            return "IND_PDP_STATE";
+        // <uint8>  State
+        case RIL_MSG_ID_IND_SIGNAL_STATE_CHANGE:
+            return "IND_SIGNAL_STATE";
+        default:
+        {
+            return "UNKNOWN";
+        }
+    }
+}
+
+char* err2str(mbtk_ril_err_enum err)
+{
+    switch(err)
+    {
+        case MBTK_RIL_ERR_SUCCESS:
+            return "SUCCESS";
+        case MBTK_RIL_ERR_FORMAT:
+            return "ERR_FORMAT";
+        case MBTK_RIL_ERR_REQ_UNKNOWN:
+            return "ERR_REQ_UNKNOWN";
+        case MBTK_RIL_ERR_REQ_PARAMETER:
+            return "ERR_REQ_PARAMETER";
+        case MBTK_RIL_ERR_UNSUPPORTED:
+            return "ERR_UNSUPPORTED";
+        case MBTK_RIL_ERR_MEMORY:
+            return "ERR_MEMORY";
+        case MBTK_RIL_ERR_IND_FULL:
+            return "ERR_IND_FULL";
+        case MBTK_RIL_ERR_IND_UNKNOWN:
+            return "ERR_IND_UNKNOWN";
+        default:
+        {
+            if(err >= MBTK_RIL_ERR_CME) {
+                return "CME ERROR";
+            }
+
+            return "UNKNOWN";
+        }
+    }
+}
+
+void *mbtk_memcpy(const void *src, unsigned int n)
+{
+    void *dest = malloc(n);
+    if(dest) {
+        return memcpy(dest, src, n);
+    } else {
+        return NULL;
+    }
+}
+
+/*
+0   GSM
+1   GSM_COMPACT
+2   UTRAN
+3   GSM_EGPRS
+4   UTRAN_HSDPA
+5   UTRAN_HSUPA
+6   UTRAN_HSDPA_HSUPA
+7   EUTRAN
+8   ECGSM
+*/
+mbtk_net_type_enum mbtk_net_type_get(mbtk_radio_technology_enum radio_tech)
+{
+    switch(radio_tech)
+    {
+        case MBTK_RADIO_TECH_GSM:
+        case MBTK_RADIO_TECH_GSM_COMPACT:
+        case MBTK_RADIO_TECH_GSM_EGPRS:
+        case MBTK_RADIO_TECH_UTRAN_HSPA:
+        {
+            return MBTK_NET_TYPE_GSM;
+        }
+        case MBTK_RADIO_TECH_UTRAN:
+        case MBTK_RADIO_TECH_UTRAN_HSDPA:
+        case MBTK_RADIO_TECH_UTRAN_HSUPA:
+        case MBTK_RADIO_TECH_UTRAN_HSDPA_HSUPA:
+        {
+            return MBTK_NET_TYPE_UMTS;
+        }
+        case MBTK_RADIO_TECH_E_UTRAN:
+        {
+            return MBTK_NET_TYPE_LTE;
+        }
+        default:
+        {
+            return MBTK_NET_TYPE_UNKNOWN;
+        }
+    }
+}
+
+void ril_msg_pack_free(ril_msg_pack_info_t* pack)
+{
+    if(pack) {
+        LOGV("Free msg pack - %s", id2str(pack->msg_id));
+        if(pack->data) {
+            free(pack->data);
+        }
+        free(pack);
+    }
+}
+
+ril_msg_pack_info_t* ril_msg_pack_creat(int msg_type, int msg_id, int msg_index, const void *data, int data_len)
+{
+    ril_msg_pack_info_t *pack = (ril_msg_pack_info_t *)malloc(sizeof(ril_msg_pack_info_t));
+    if(!pack)
+    {
+        LOGE("malloc() error[%d]", errno);
+        return NULL;
+    }
+
+    pack->tag = RIL_SOCK_PACKET_TAG;
+
+    if(msg_index < 0) {
+        pack->msg_index = ril_index++;
+    } else {
+        pack->msg_index = msg_index;
+    }
+    pack->msg_type = (uint16)msg_type;
+    pack->msg_id = (uint16)msg_id;
+    pack->err = (uint16)0;
+    if(data && data_len > 0) {
+        pack->msg_len = data_len + RIL_SOCK_PACK_LEN_MIN - RIL_SOCK_PACK_EXTRA_LEN;
+        pack->data_len = (uint16)data_len;
+        pack->data = (uint8*)malloc(data_len);
+        if(pack->data == NULL) {
+            LOGE("malloc(%d) fail.", data_len);
+            free(pack);
+            return NULL;
+        }
+        memcpy(pack->data, data, data_len);
+    } else {
+        pack->msg_len = RIL_SOCK_PACK_LEN_MIN - RIL_SOCK_PACK_EXTRA_LEN;
+        pack->data_len = (uint16)0;
+        pack->data = NULL;
+    }
+
+    return pack;
+}
+
+int ril_pack_send(int fd, ril_msg_pack_info_t *pack)
+{
+    if(!pack)
+    {
+        LOG("Packet is NULL.");
+        return -1;
+    }
+
+    uint8 buff[RIL_SOCK_MSG_LEN_MAX] = {0};
+    if(pack->data && pack->data_len > 0) {
+        memcpy(buff, pack, RIL_SOCK_PACK_LEN_MIN);
+        memcpy(buff + RIL_SOCK_PACK_LEN_MIN, pack->data, pack->data_len);
+        return sock_write(fd, buff, RIL_SOCK_PACK_LEN_MIN + pack->data_len);
+    } else {
+        memcpy(buff, pack, RIL_SOCK_PACK_LEN_MIN);
+        return sock_write(fd, buff, RIL_SOCK_PACK_LEN_MIN);
+    }
+}
+
+ril_msg_pack_info_t** ril_pack_recv(int fd, bool is_server, mbtk_ril_err_enum *err)
+{
+    uint8 msg[RIL_SOCK_MSG_LEN_MAX + 1];
+    *err = MBTK_RIL_ERR_SUCCESS;
+    int len = sock_read(fd, msg, RIL_SOCK_MSG_LEN_MAX + 1);
+    if(len < RIL_SOCK_PACK_LEN_MIN)
+    {
+        if(len > 0)
+        {
+            *err = MBTK_RIL_ERR_FORMAT;
+            LOGE("Insufficient packet data.");
+        }
+        return NULL;
+    }
+
+    int pack_count = pack_num_check(msg, len);
+    LOGD("Packet number : %d", pack_count);
+    if(pack_count < 1)
+    {
+        *err = MBTK_RIL_ERR_FORMAT;
+        LOGE("Packet not found.");
+        return NULL;
+    }
+    uint8 *ptr = msg;
+    ril_msg_pack_info_t** packs = (ril_msg_pack_info_t**)malloc(sizeof(ril_msg_pack_info_t*) * (pack_count + 1));
+    int i = 0;
+    while(i < pack_count)
+    {
+        packs[i] = (ril_msg_pack_info_t*)malloc(sizeof(ril_msg_pack_info_t));
+        if(packs[i] == NULL){
+            *err = MBTK_RIL_ERR_MEMORY;
+            goto error;
+        }
+        memcpy(packs[i], ptr, RIL_SOCK_PACK_LEN_MIN);
+
+        // TAG
+        if(RIL_SOCK_PACKET_TAG != packs[i]->tag)
+        {
+            *err = MBTK_RIL_ERR_FORMAT;
+            LOGE("Packet TAG error.");
+            goto error;
+        }
+
+        if(is_server)
+        {
+            // For server,"info_type" must by REQ or IND(Register IND).
+            if(packs[i]->msg_type != RIL_MSG_TYPE_REQ && packs[i]->msg_type != RIL_MSG_TYPE_IND)
+            {
+                *err = MBTK_RIL_ERR_FORMAT;
+                LOGE("Packet Type error : %d", packs[i]->msg_type);
+                goto error;
+            }
+        }
+        else
+        {
+            // For client,"info_type" must by RSP or IND.
+            if(packs[i]->msg_type != RIL_MSG_TYPE_RSP && packs[i]->msg_type != RIL_MSG_TYPE_IND)
+            {
+                *err = MBTK_RIL_ERR_FORMAT;
+                LOG("Packet Type error.");
+                goto error;
+            }
+        }
+
+        ptr += RIL_SOCK_PACK_LEN_MIN;
+        if(packs[i]->data_len > 0) {
+            packs[i]->data = (uint8*)malloc(packs[i]->data_len);
+            if(packs[i]->data == NULL) {
+                *err = MBTK_RIL_ERR_MEMORY;
+                goto error;
+            }
+            memcpy(packs[i]->data, ptr, packs[i]->data_len);
+            ptr += packs[i]->data_len;
+        } else {
+            packs[i]->data = NULL;
+        }
+
+        i++;
+    }
+    packs[i] = NULL;
+
+    return packs;
+
+error:
+    LOGD("mbtk_ril_pack_recv error, will free().");
+    if(packs)
+    {
+        ril_msg_pack_info_t** pack_ptr = packs;
+        while(*pack_ptr)
+        {
+            ril_msg_pack_free(*pack_ptr);
+            pack_ptr++;
+        }
+
+        free(packs);
+    }
+    return NULL;
+}
+
diff --git a/mbtk/mbtk_rild_v2/Makefile b/mbtk/mbtk_rild_v2/Makefile
new file mode 100755
index 0000000..5df9e1c
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/Makefile
@@ -0,0 +1,47 @@
+BUILD_ROOT = $(shell pwd)/..
+include $(BUILD_ROOT)/Make.defines
+
+LOCAL_PATH=$(BUILD_ROOT)/mbtk_rild_v2
+
+INC_DIR += \
+		-I$(LOCAL_PATH)/inc \
+		-I$(BUILD_ROOT)/libmbtk_ril_v2/inc
+
+LIB_DIR +=
+
+LIBS += -lmbtk_lib -lmbtk_net -lmbtk_ril -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
+
+LOCAL_SRC_FILES = $(wildcard src/*.c) $(wildcard src/*.cpp)
+OBJS = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(LOCAL_SRC_FILES)))
+$(info OBJS = $(OBJS))
+
+dtarget := $(OUT_DIR)/bin/mbtk_rild
+
+all: $(dtarget)
+
+$(dtarget): $(OBJS)
+	@echo "  BIN     $@"
+	$(CC) $(CFLAGS) $(LIB_DIR) $(LIBS) $(OBJS) -o $@
+
+%.o:%.c
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+%.o:%.cpp
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+clean:
+	rm -f $(OBJS) $(dtarget)
+
diff --git a/mbtk/mbtk_rild_v2/inc/at_tok.h b/mbtk/mbtk_rild_v2/inc/at_tok.h
new file mode 100755
index 0000000..a9725c0
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/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_rild_v2/inc/atchannel.h b/mbtk/mbtk_rild_v2/inc/atchannel.h
new file mode 100755
index 0000000..b97cb27
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/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_rild_v2/inc/ril_info.h b/mbtk/mbtk_rild_v2/inc/ril_info.h
new file mode 100755
index 0000000..896a73c
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/inc/ril_info.h
@@ -0,0 +1,124 @@
+/*
+* ril_info.h
+*
+* MBTK Ril information header.
+*
+* Author : lb
+* Date   : 2024/8/6 10:53:08
+*/
+#ifndef _RIL_INFO_H
+#define _RIL_INFO_H
+#include <stdio.h>
+
+#include "mbtk_type.h"
+#include "mbtk_ril_api.h"
+#include "mbtk_log.h"
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_list.h"
+#include "mbtk_device.h"
+#include "mbtk_queue.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_DEF_ROUTE_CID  "persist.mbtk.def_route_cid"
+
+typedef struct
+{
+    int fd;
+
+    uint32 ind_num;
+    uint16 ind_register[IND_REGISTER_MAX];
+} sock_cli_info_t;
+
+typedef struct
+{
+    sock_cli_info_t *cli_info;
+    void* pack;     // Refro to : ril_msg_pack_info_t
+} ril_msg_queue_info_t;
+
+typedef struct {
+    mbtk_radio_state_enum radio_state;
+    mbtk_sim_state_enum sim_state;
+    int sock_listen_fd;
+    int epoll_fd;
+    bool at_process;
+
+    list_node_t *sock_client_list;      // Refor to : sock_cli_info_t
+    mbtk_queue_node_t msg_queue;        // Refor to : ril_msg_queue_info_t
+    pthread_cond_t msg_cond;
+    pthread_mutex_t msg_mutex;
+} ril_info_t;
+
+typedef struct {
+    bool band_set_success;
+    mbtk_modem_band_area_enum band_area;
+    mbtk_band_info_t band_support;
+} ril_band_info_t;
+
+typedef enum {
+    RIL_URC_MSG_RADIO_STATE,
+    RIL_URC_MSG_CGEV,
+    RIL_URC_MSG_NET_CS_REG_STATE,
+    RIL_URC_MSG_NET_PS_REG_STATE,
+    RIL_URC_MSG_CALL_STATE,
+    RIL_URC_MSG_SIM_STATE,
+    RIL_URC_MSG_PDP_STATE,
+    RIL_URC_MSG_SMS_STATE,
+    RIL_URC_MSG_SET_BAND,
+    RIL_URC_MSG_GET_SIM_STATE,     //check sim status
+    RIL_URC_MSG_NET_STATE_LOG      // Save Network state into file.
+} ril_urc_msg_id_enum;
+
+/*
+0: unknown
+1: available
+2: current
+3: forbidden
+*/
+typedef enum
+{
+    MBTK_NET_AVIL_STATE_UNKNOWN = 0,
+    MBTK_NET_AVIL_STATE_AVAILABLE,
+    MBTK_NET_AVIL_STATE_CURRENT,
+    MBTK_NET_AVIL_STATE_FORBIDDEN
+} mbtk_net_avil_state_enum;
+
+typedef enum {
+    RIL_DATA_CALL_STATE_STOP,
+    RIL_DATA_CALL_STATE_STARTED,
+    RIL_DATA_CALL_STATE_STARTING,       // Data dialing in progress
+    RIL_DATA_CALL_STATE_STOPPING        // Ending data dialing
+} ril_data_call_state_enum;
+
+typedef struct {
+    ril_urc_msg_id_enum msg;
+
+    void *data;
+    int data_len;
+} ril_urc_msg_info_t;
+
+typedef struct {
+    mbtk_ril_cid_enum cid_for_def_route;
+
+    int num;
+    mbtk_apn_info_t apns[MBTK_APN_CID_MAX];
+} ril_apn_info_array_t;
+
+extern ril_info_t ril_info;
+
+
+mbtk_radio_state_enum ril_radio_state_get();
+mbtk_ril_err_enum ril_radio_state_set(mbtk_radio_state_enum state, bool reset);
+
+mbtk_sim_state_enum ril_sim_state_get();
+
+void apn_auto_conf_from_prop();
+
+bool is_ipv4(const char *ip);
+
+#endif /* _RIL_INFO_H */
diff --git a/mbtk/mbtk_rild_v2/src/at_tok.c b/mbtk/mbtk_rild_v2/src/at_tok.c
new file mode 100755
index 0000000..531afff
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/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_rild_v2/src/atchannel.c b/mbtk/mbtk_rild_v2/src/atchannel.c
new file mode 100755
index 0000000..bf0384c
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/src/atchannel.c
@@ -0,0 +1,1337 @@
+/* //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();
+    }
+}
+
+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;
+        }
+
+        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, NULL);
+    if (ret < 0)
+    {
+        LOGE("AT thread create fail.");
+        return -1;
+    }
+
+    pthread_t uart_tid_reader;
+    ret = pthread_create(&uart_tid_reader, &attr, readerUrcLoop, NULL);
+    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_rild_v2/src/main.c b/mbtk/mbtk_rild_v2/src/main.c
new file mode 100755
index 0000000..45a30f6
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/src/main.c
@@ -0,0 +1,2209 @@
+#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 <signal.h>

+#include <sys/epoll.h>

+#include <pthread.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 "ril_info.h"

+#include "mbtk_ntp.h"

+#include "mbtk_net_control.h"

+#include "mbtk_ril.h"

+#include "mbtk_str.h"

+#include "mbtk_queue.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"

+#define MBTK_BOOT_NET_READY "/etc/init.d/mbtk_boot_net_ready"

+#define MBTK_RILD_PID_FILE "/var/run/mbtk_rild.pid"

+#define MBTK_RILD_FILE_NET_READY "/tmp/mbtk_rild.net_ready"

+#define MBTK_RILD_FILE_SER_READY "/tmp/mbtk_rild.ser_ready"

+

+static bool ril_net_ready = FALSE;  // Only one time.

+static bool ril_server_ready = FALSE;  // Only one time.

+ril_band_info_t band_info;

+ril_info_t ril_info;

+

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

+// int mbtk_signal_log(char *data);

+int InProduction_Mode(void);

+mbtk_ril_err_enum dev_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack);

+mbtk_ril_err_enum call_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack);

+mbtk_ril_err_enum sim_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack);

+mbtk_ril_err_enum net_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack);

+mbtk_ril_err_enum pb_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack);

+mbtk_ril_err_enum sms_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack);

+

+/* 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();

+}

+

+static void sock_cli_free_func(void *data)
+{
+    if (data)
+    {
+        sock_cli_info_t *info = (sock_cli_info_t*) data;

+        LOGD("Free Socket client[fd = %d].", info->fd);

+        free(info);
+    }
+}

+

+/*

+* Will exec mbtk_boot_server_ready and mbtk_boot_net_ready if is_first_boot is true.

+*/

+static int net_ready_set()

+{

+    int ret = -1;

+    int fd = open(MBTK_RILD_FILE_NET_READY, O_CREAT | O_WRONLY | O_TRUNC, 0644);

+    if(fd > 0) {

+        if(write(fd, "1", 1) == 1) {

+            ret = 0;

+            ril_net_ready = TRUE;

+        }

+        close(fd);

+    } else {

+        LOGE("Open %s fail:%d", MBTK_RILD_FILE_NET_READY, errno);

+    }

+

+    return ret;

+}

+

+/*

+* Will exec mbtk_boot_server_ready and mbtk_boot_net_ready if is_first_boot is true.

+*/

+static int ser_ready_set()

+{

+    int ret = -1;

+    int fd = open(MBTK_RILD_FILE_SER_READY, O_CREAT | O_WRONLY | O_TRUNC, 0644);

+    if(fd > 0) {

+        if(write(fd, "1", 1) == 1) {

+            ret = 0;

+            ril_server_ready = TRUE;

+        }

+        close(fd);

+    } else {

+        LOGE("Open %s fail:%d", MBTK_RILD_FILE_SER_READY, errno);

+    }

+

+    return ret;

+}

+

+/*

+* Will exec mbtk_boot_server_ready and mbtk_boot_net_ready if is_first_boot is true.

+*/

+static void ready_state_update()

+{

+    int fd = open(MBTK_RILD_FILE_NET_READY, O_RDONLY, 0644);

+    char buff[10];

+    if(fd > 0) {

+        if(read(fd, buff, sizeof(buff)) > 0) {

+            ril_net_ready = TRUE;

+        } else {

+            ril_net_ready = FALSE;

+        }

+

+        close(fd);

+    } else {

+        ril_net_ready = FALSE;

+        LOGE("Open %s fail:%d", MBTK_RILD_FILE_NET_READY, errno);

+    }

+

+    fd = open(MBTK_RILD_FILE_SER_READY, O_RDONLY, 0644);

+    if(fd > 0) {

+        if(read(fd, buff, sizeof(buff)) > 0) {

+            ril_server_ready = TRUE;

+        } else {

+            ril_server_ready = FALSE;

+        }

+

+        close(fd);

+    } else {

+        ril_server_ready = FALSE;

+        LOGE("Open %s fail:%d", MBTK_RILD_FILE_SER_READY, errno);

+    }

+}

+

+static void mbtk_net_ready()

+{

+    // /etc/init.d/mbtk_boot_net_ready

+    if(!ril_net_ready) {

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

+            LOGD("Exec : %s", MBTK_BOOT_NET_READY);

+            system(MBTK_BOOT_NET_READY);

+        } else {

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

+        }

+        net_ready_set();

+    } else {

+        LOGD("No exec : %s", MBTK_BOOT_NET_READY);

+    }

+}

+

+static void mbtk_ril_ready()

+{

+    // /etc/init.d/mbtk_boot_server_ready

+    if(!ril_server_ready) {

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

+            LOGD("Exec : %s", MBTK_BOOT_SERVER_READY);

+            system(MBTK_BOOT_SERVER_READY);

+        } else {

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

+        }

+        ser_ready_set();

+    } else {

+        LOGD("No exec : %s", MBTK_BOOT_SERVER_READY);

+    }

+}

+

+static sock_cli_info_t* cli_find(int fd)

+{
+    sock_cli_info_t *result = NULL;

+    list_first(ril_info.sock_client_list);

+    while ((result = (sock_cli_info_t*) list_next(ril_info.sock_client_list)))

+    {
+        if (result->fd == fd)
+            return result;
+    }
+
+    return NULL;
+}

+

+static void cli_close(sock_cli_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(ril_info.epoll_fd, EPOLL_CTL_DEL, client->fd, &ev);

+
+    close(client->fd);
+
+    if(list_remove(ril_info.sock_client_list, client))

+    {
+        sock_cli_free_func(client);
+    }
+}
+
+static void ril_error_pack_send(int fd, int ril_id, int msg_index, int err)

+{
+    ril_msg_pack_info_t* pack = ril_msg_pack_creat(RIL_MSG_TYPE_RSP, ril_id, msg_index, NULL, 0);

+    if(pack)
+    {

+        pack->err = (uint16)err;

+        ril_pack_send(fd, pack);

+        ril_msg_pack_free(pack);

+    }
+    else
+    {
+        LOGW("ril_msg_pack_creat() fail.");

+    }
+}
+
+void ril_rsp_pack_send(int fd, int ril_id, int msg_index, const void* data, int data_len)

+{
+    ril_msg_pack_info_t* pack = ril_msg_pack_creat(RIL_MSG_TYPE_RSP, ril_id, msg_index, data, data_len);

+    if(pack)
+    {
+        pack->err = (uint16)MBTK_RIL_ERR_SUCCESS;

+#if 0

+        if(data != NULL && data_len > 0)
+        {
+            pack->data_len = (uint16)data_len;
+            pack->data = (uint8*)mbtk_memcpy(data, data_len);

+        }

+#endif

+        ril_pack_send(fd, pack);

+        ril_msg_pack_free(pack);

+    }
+    else
+    {
+        LOGW("ril_msg_pack_creat() fail.");

+    }
+}

+

+void ril_ind_pack_send(int fd, int msg_id, const void* data, int data_len)

+{
+    ril_msg_pack_info_t* pack = ril_msg_pack_creat(RIL_MSG_TYPE_IND, msg_id, RIL_MSG_INDEX_INVALID, data, data_len);

+    if(pack)
+    {
+        pack->err = (uint16)0;

+#if 0

+        if(data != NULL && data_len > 0)
+        {
+            pack->data_len = (uint16)data_len;
+            pack->data = (uint8*)mbtk_memcpy(data, data_len);

+        }

+#endif

+        ril_pack_send(fd, pack);

+        ril_msg_pack_free(pack);

+    }
+    else
+    {
+        LOGW("ril_msg_pack_creat() fail.");

+    }
+}

+

+

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

+{

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

+#if 0

+    // MBTK_AT_READY

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

+    {

+

+    }

+    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 = data[1] + 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 DEACT ")) { // +CGEV: EPS PDN DEACT <cid>

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

+                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 = data[1] + 100;

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

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

+                    {

+

+                    }

+

+                    data_pdp = data[1] + 200;

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

+					data[1] = 0;

+                }

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

+        static bool net_led_gms_wcdma = FALSE;

+        static bool net_led_lte = FALSE;

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

+            tmp_s++;

+        uint8 data[2];

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

+

+        if(strStartsWith(s, "+CGREG:"))

+        {

+           data[1] = 0;  // GMS/WCDMA

+           if(data[0] == 1)

+           {

+               net_led_gms_wcdma = TRUE;

+           }

+           else

+           {

+               net_led_gms_wcdma = FALSE;

+           }

+

+        }

+        else

+        {

+           data[1] = 1;  // LTE

+           if(data[0] == 1)

+           {

+               net_led_lte = TRUE;

+           }

+           else

+           {

+               net_led_lte = FALSE;

+           }

+        }

+

+        if(FALSE == net_led_gms_wcdma && FALSE == net_led_lte)

+        {

+           //mbtk_net_led_set(MBTK_NET_LED_SEARCH_NETWORK);

+        }

+        else

+        {

+           //mbtk_net_led_set(MBTK_NET_LED_NET_CONNECT);

+           mbtk_net_ready();

+        }

+

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

+        urc_msg_distribute(true, INFO_URC_MSG_NET_STATE_LOG, NULL, 0);

+    }

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

+        urc_msg_distribute(true, INFO_URC_MSG_NET_STATE_LOG, NULL, 0);

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

+

+        if(reg.call_wait == MBTK_DISCONNECTED)

+        {

+            //mbtk_net_led_set(MBTK_NET_LED_CALL_DISCONNECT);

+        }

+

+        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:"))

+    {

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

+        {

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

+

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

+            net_info.sim_state = MBTK_SIM_READY;

+        }

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

+        {

+            sim_info_reg.sim = 2;

+            net_info.sim_state = MBTK_SIM_PIN;

+        }

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

+        {

+            sim_info_reg.sim = 3;

+            net_info.sim_state = MBTK_SIM_PUK;

+        }

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

+        {

+            sim_info_reg.sim = 4;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+            sim_info_reg.sim = 5;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+            sim_info_reg.sim = 6;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+            sim_info_reg.sim = 7;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+            sim_info_reg.sim = 8;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+            sim_info_reg.sim = 9;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+            sim_info_reg.sim = 10;

+            net_info.sim_state = MBTK_SIM_NETWORK_PERSONALIZATION;

+        }

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

+        {

+            sim_info_reg.sim = 11;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+            sim_info_reg.sim = 12;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+            sim_info_reg.sim = 13;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+            sim_info_reg.sim = 14;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+            sim_info_reg.sim = 15;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+            sim_info_reg.sim = 16;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+            sim_info_reg.sim = 17;

+            net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+        {

+             sim_info_reg.sim = 18;

+             net_info.sim_state = MBTK_SIM_ABSENT;

+        }

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

+    }

+#endif

+}

+

+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_at_ready_process()
+{
+    ril_info.radio_state = ril_radio_state_get();

+    if (ril_info.radio_state != MBTK_RADIO_STATE_FULL_FUNC)

+    {
+        ril_radio_state_set(MBTK_RADIO_STATE_FULL_FUNC, FALSE);

+    }

+
+    if(ril_info.radio_state == MBTK_RADIO_STATE_FULL_FUNC)

+    {

+        at_send_command("AT+CEREG=2", NULL);
+    }
+
+    ril_info.sim_state = ril_sim_state_get();

+    if(ril_info.sim_state == MBTK_SIM_STATE_READY)

+    {
+        LOGD("SIM READY!");
+        at_send_command("AT+COPS=3", NULL);
+

+        // Set APN from prop.

+        apn_auto_conf_from_prop();

+    }
+    else
+    {
+        LOGE("SIM NOT READY!");
+    }

+}

+

+static void ind_regisger(sock_cli_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++;
+        LOGD("Register IND : %s", id2str(ind));

+    }
+    else
+    {
+        LOGW("IND had exist.");

+    }
+}

+

+// Process AT URC data
+static int send_pack_to_queue(sock_cli_info_t* cli_info, void* pack)

+{
+    if(ril_info.msg_queue.count >= PACK_PROCESS_QUEUE_MAX)

+    {
+        LOGE("Packet process queue is full");

+        return -1;
+    }
+
+    ril_msg_queue_info_t *item = (ril_msg_queue_info_t*)malloc(sizeof(ril_msg_queue_info_t));

+    if(!item)
+    {
+        LOGE("malloc() fail[%d].", errno);

+        return -1;
+    }
+    item->cli_info = cli_info;
+    item->pack = pack;
+    mbtk_queue_put(&ril_info.msg_queue, item);

+
+    // If thread is waitting,continue it.
+    pthread_mutex_lock(&ril_info.msg_mutex);

+    pthread_cond_signal(&ril_info.msg_cond);

+    pthread_mutex_unlock(&ril_info.msg_mutex);

+
+    return 0;
+}

+

+

+static void pack_distribute(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack)

+{
+    // Register IND Message.
+    if(pack->msg_type == RIL_MSG_TYPE_IND)

+    {
+        mbtk_ril_err_enum err = MBTK_RIL_ERR_SUCCESS;

+        if(cli_info->ind_num >= IND_REGISTER_MAX)
+        {
+            LOGE("IND if full.");

+            err = MBTK_RIL_ERR_IND_FULL;

+        }
+        else
+        {
+            ind_regisger(cli_info, pack->msg_id);

+        }
+
+        ril_error_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, err);

+
+        ril_msg_pack_free(pack);

+    }
+    else     // Request Information.
+    {
+        LOGD("Start process REQ(%s), Length : %d", id2str(pack->msg_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);
+    }
+}

+

+// Return MBTK_INFO_ERR_SUCCESS,will call pack_error_send() to send RSP.
+// Otherwise, do not call pack_error_send().
+static mbtk_ril_err_enum pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack)

+{
+    if(pack->msg_id > RIL_MSG_ID_DEV_BEGIN && pack->msg_id < RIL_MSG_ID_DEV_END) {

+        return dev_pack_req_process(cli_info, pack);

+    } else if(pack->msg_id > RIL_MSG_ID_SIM_BEGIN && pack->msg_id < RIL_MSG_ID_SIM_END) {

+        return sim_pack_req_process(cli_info, pack);

+    } else if(pack->msg_id > RIL_MSG_ID_NET_BEGIN && pack->msg_id < RIL_MSG_ID_NET_END) {

+        return net_pack_req_process(cli_info, pack);

+    } else if(pack->msg_id > RIL_MSG_ID_CALL_BEGIN && pack->msg_id < RIL_MSG_ID_CALL_END) {

+        return call_pack_req_process(cli_info, pack);

+    } else if(pack->msg_id > RIL_MSG_ID_SMS_BEGIN && pack->msg_id < RIL_MSG_ID_SMS_END) {

+        return sms_pack_req_process(cli_info, pack);

+    } else if(pack->msg_id > RIL_MSG_ID_PB_BEGIN && pack->msg_id < RIL_MSG_ID_PB_END) {

+        return pb_pack_req_process(cli_info, pack);

+    } else {

+        LOGW("Unknown msg id : %d", pack->msg_id);

+        return MBTK_RIL_ERR_FORMAT;

+    }

+}

+

+static void urc_msg_process(ril_urc_msg_info_t *msg)

+{
+    uint8 *data = NULL;
+    if(msg->data) {
+        data = (uint8*)msg->data;
+    }
+    switch(msg->msg) {
+        case RIL_URC_MSG_RADIO_STATE:

+        {
+            break;
+        }
+        default:
+        {
+            LOGE("Unknown URC : %d", msg->msg);
+            break;
+        }
+    }
+}

+

+// Read client conn/msg and push into ril_info.msg_queue.

+static void* ril_read_pthread(void* arg)

+{
+    UNUSED(arg);
+    ril_info.epoll_fd = epoll_create(SOCK_CLIENT_MAX + 1);

+    if(ril_info.epoll_fd < 0)

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

+        return NULL;
+    }
+
+    uint32 event = EPOLLIN | EPOLLET;
+    struct epoll_event ev;
+    ev.data.fd = ril_info.sock_listen_fd;

+    ev.events = event; //EPOLLIN | EPOLLERR | EPOLLET;
+    epoll_ctl(ril_info.epoll_fd, EPOLL_CTL_ADD, ril_info.sock_listen_fd, &ev);

+
+    int nready = -1;
+    struct epoll_event epoll_events[EPOLL_LISTEN_MAX];
+    while(1)
+    {
+        nready = epoll_wait(ril_info.epoll_fd, epoll_events, EPOLL_LISTEN_MAX, -1);

+        if(nready > 0)
+        {
+            sock_cli_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 == ril_info.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(ril_info.epoll_fd, EPOLL_CTL_ADD, client_fd, &ev);

+
+                            sock_cli_info_t *info = (sock_cli_info_t*)malloc(sizeof(sock_cli_info_t));

+                            if(info)
+                            {
+                                memset(info, 0, sizeof(sock_cli_info_t));

+                                info->fd = client_fd;

+                                list_add(ril_info.sock_client_list, info);

+                                LOG("Add New Client FD Into List.");

+

+                                // Send msg RIL_MSG_ID_IND_SER_READY to client.

+                                ril_ind_pack_send(client_fd, RIL_MSG_ID_IND_SER_READY, NULL, 0);

+                            }
+                            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_ril_err_enum err = MBTK_RIL_ERR_SUCCESS;

+                        ril_msg_pack_info_t** pack = ril_pack_recv(cli_info->fd, true, &err);

+
+                        // Parse packet error,send error response to client.
+                        if(pack == NULL)
+                        {
+                            ril_error_pack_send(cli_info->fd, RIL_MSG_ID_UNKNOWN, RIL_MSG_INDEX_INVALID, err);

+                        }
+                        else
+                        {
+                            ril_msg_pack_info_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);
+                        }
+                    }
+                    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* ril_process_thread(void* arg)

+{
+    UNUSED(arg);
+    ril_msg_queue_info_t* item = NULL;

+
+    pthread_mutex_lock(&ril_info.msg_mutex);

+    while(TRUE)
+    {
+        if(mbtk_queue_empty(&ril_info.msg_queue))

+        {
+            LOG("Packet process wait...");
+            pthread_cond_wait(&ril_info.msg_cond, &ril_info.msg_mutex);

+            LOG("Packet process continue...");
+        }
+        else
+        {
+            LOG("Packet process queue not empty,continue...");
+        }
+
+        // Process all information request.
+        mbtk_ril_err_enum err;

+        while((item = (ril_msg_queue_info_t*)mbtk_queue_get(&ril_info.msg_queue)) != NULL)

+        {
+            if(item->cli_info) { // REQ form client.
+                ril_msg_pack_info_t *pack = (ril_msg_pack_info_t*)item->pack;

+                LOGD("Process REQ %s.", id2str(pack->msg_id));

+                ril_info.at_process = true;

+                err = pack_req_process(item->cli_info, pack);
+                if(err != MBTK_RIL_ERR_SUCCESS)

+                {
+                    ril_error_pack_send(item->cli_info->fd, pack->msg_id, pack->msg_index, err);

+                }
+                ril_info.at_process = false;

+                ril_msg_pack_free(pack);

+                free(item);
+            } else { // REQ from myself.
+                ril_urc_msg_info_t *urc = (ril_urc_msg_info_t*)item->pack;

+                LOGD("Process URC %d.", urc->msg);

+                urc_msg_process(urc);
+                if(urc->data)

+                    free(urc->data);
+                free(urc);
+            }
+        }
+    }
+    pthread_mutex_unlock(&ril_info.msg_mutex);

+    return NULL;
+}

+

+/*
+AT*BAND=15,78,147,482,134742231
+
+OK
+*/
+static void* band_config_thread()
+{
+    mbtk_device_info_modem_t info_modem;
+    memset(&band_info.band_support, 0, sizeof(mbtk_band_info_t));

+    memset(&info_modem, 0, sizeof(mbtk_device_info_modem_t));
+    band_info.band_set_success = FALSE;

+    if(mbtk_dev_info_read(MBTK_DEVICE_INFO_ITEM_MODEM, &(info_modem), sizeof(mbtk_device_info_modem_t))) {
+        LOGD("mbtk_dev_info_read(MODEM) fail, use default band.");
+        band_info.band_area = MBTK_MODEM_BAND_AREA_ALL;

+        band_info.band_support.net_pref = MBTK_NET_PREF_UNUSE;

+        band_info.band_support.gsm_band = MBTK_BAND_ALL_GSM_DEFAULT;

+        band_info.band_support.umts_band = MBTK_BAND_ALL_WCDMA_DEFAULT;

+        band_info.band_support.tdlte_band = MBTK_BAND_ALL_TDLTE_DEFAULT;

+        band_info.band_support.fddlte_band = MBTK_BAND_ALL_FDDLTE_DEFAULT;

+        band_info.band_support.lte_ext_band = MBTK_BAND_ALL_EXT_LTE_DEFAULT;

+    } else {
+        band_info.band_area = info_modem.band_area;

+        band_info.band_support.net_pref = MBTK_NET_PREF_UNUSE;

+        band_info.band_support.gsm_band = info_modem.band_gsm;

+        band_info.band_support.umts_band = info_modem.band_wcdma;

+        band_info.band_support.tdlte_band = info_modem.band_tdlte;

+        band_info.band_support.fddlte_band = info_modem.band_fddlte;

+        band_info.band_support.lte_ext_band = info_modem.band_lte_ext;

+    }
+
+    bool is_first = TRUE;
+    while(!band_info.band_set_success) {

+        // Set band.

+#if 0

+        info_urc_msg_t *urc = (info_urc_msg_t*)malloc(sizeof(info_urc_msg_t));
+        if(!urc)
+        {
+            LOG("malloc() fail[%d].", errno);
+            break;
+        } else {
+            urc->msg = INFO_URC_MSG_SET_BAND;
+            urc->data = NULL;
+            urc->data_len = 0;
+            send_pack_to_queue(NULL, urc);
+
+            if(is_first) {
+                is_first = FALSE;
+            } else {
+                LOGE("*BAND exec error, will retry in 5s.");
+            }
+            sleep(5);
+        }

+#else

+        sleep(5);

+#endif

+    }
+
+    LOGD("Set Band thread exit.");
+    return NULL;
+}
+

+

+int ril_server_start()

+{
+    signal(SIGPIPE, SIG_IGN);

+

+    memset(&ril_info, 0, sizeof(ril_info_t));

+    memset(&band_info, 0, sizeof(ril_band_info_t));

+    memset(&band_info.band_support, 0xFF, sizeof(mbtk_band_info_t));

+
+    //check cfun and sim card status
+    ril_at_ready_process();
+
+    //any AT instruction that is not sent through pack_process_thread needs to precede the thread
+    //thread create
+    if(ril_info.sock_listen_fd > 0)

+    {
+        LOGE("Information Server Has Started.");

+        return -1;
+    }
+
+    struct sockaddr_un server_addr;
+    ril_info.sock_listen_fd = socket(AF_LOCAL, SOCK_STREAM, 0);

+    if(ril_info.sock_listen_fd < 0)

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

+        return -1;
+    }
+
+    // Set O_NONBLOCK
+    int flags = fcntl(ril_info.sock_listen_fd, F_GETFL, 0);

+    if (flags < 0)
+    {
+        LOGE("Get flags error:%d", errno);

+        goto error;
+    }
+    flags |= O_NONBLOCK;
+    if (fcntl(ril_info.sock_listen_fd, F_SETFL, flags) < 0)

+    {
+        LOGE("Set flags error:%d", errno);

+        goto error;
+    }
+
+    unlink(RIL_SOCK_NAME);

+    memset(&server_addr, 0, sizeof(struct sockaddr_un));
+    server_addr.sun_family = AF_LOCAL;
+    strcpy(server_addr.sun_path, RIL_SOCK_NAME);

+    if(bind(ril_info.sock_listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)))

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

+        goto error;
+    }
+
+    if(listen(ril_info.sock_listen_fd, SOCK_CLIENT_MAX))

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

+        goto error;
+    }
+
+    ril_info.sock_client_list = list_create(sock_cli_free_func);

+    if(ril_info.sock_client_list == NULL)

+    {
+        LOGE("list_create() fail.");

+        goto error;
+    }

+

+    mbtk_queue_init(&ril_info.msg_queue);

+    pthread_mutex_init(&ril_info.msg_mutex, NULL);

+    pthread_cond_init(&ril_info.msg_cond, NULL);

+
+    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))
+    {
+        LOGE("pthread_attr_setdetachstate() fail.");

+        goto error;
+    }
+
+    if(pthread_create(&info_pid, &thread_attr, ril_read_pthread, NULL))

+    {
+        LOGE("pthread_create() fail.");

+        goto error;
+    }
+
+    if(pthread_create(&pack_pid, &thread_attr, ril_process_thread, NULL))

+    {
+        LOGE("pthread_create() fail.");

+        goto error;
+    }
+
+    // Set Band
+    // AT*BAND=15,78,147,482,134742231
+    char buff[10];
+    memset(buff, 0, 10);
+    property_get("persist.mbtk.band_config", buff, "");
+    if(strlen(buff) == 0) {
+        pthread_t band_pid;
+        if(pthread_create(&band_pid, &thread_attr, band_config_thread, NULL))
+        {
+            LOGE("pthread_create() fail.");

+        }
+    }
+
+    pthread_attr_destroy(&thread_attr);
+
+    LOGD("MBTK Ril Server Start...");

+
+    return 0;
+error:

+    if(ril_info.sock_client_list) {

+        list_free(ril_info.sock_client_list);

+        ril_info.sock_client_list = NULL;

+    }

+

+    if(ril_info.sock_listen_fd > 0) {

+        close(ril_info.sock_listen_fd);

+        ril_info.sock_listen_fd = -1;

+    }

+    return -1;
+}

+

+

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

+{

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

+

+#ifdef MBTK_DUMP_SUPPORT

+    mbtk_debug_open(NULL, TRUE);

+#endif

+

+// Using Killall,the file lock may be not release.

+#if 0

+    if(app_already_running(MBTK_RILD_PID_FILE)) {

+        LOGW("daemon already running.");

+        exit(1);

+    }

+#endif

+

+    LOGI("mbtk_rild start.");

+

+    if(InProduction_Mode()) {

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

+        exit(0);

+    }

+

+    ready_state_update();

+

+    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(at_handshake())

+    {

+        LOGE("AT handshake fail.");

+        return -1;

+    }

+

+    LOGD("AT OK.");

+

+    if(ril_server_start())

+    {

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

+        return -1;

+    }

+

+    mbtk_ril_ready();

+

+    while(1)

+    {

+        sleep(24 * 60 * 60);

+    }

+

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

+    return 0;

+}

diff --git a/mbtk/mbtk_rild_v2/src/ril_call.c b/mbtk/mbtk_rild_v2/src/ril_call.c
new file mode 100755
index 0000000..6264972
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/src/ril_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_ril.h"
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_utils.h"
+#include "ril_info.h"
+
+void ril_rsp_pack_send(int fd, int ril_id, int msg_index, 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_ril_err_enum call_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack)
+{
+    mbtk_ril_err_enum err = MBTK_RIL_ERR_SUCCESS;
+    int cme_err = MBTK_RIL_ERR_CME_NON;
+    switch(pack->msg_id)
+    {
+        case RIL_MSG_ID_CALL_START: // <string> phone number
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set
+            {
+                char *pn = (char*)(pack->data);
+                if(req_call_start(pn, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("ATD fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_CALL_ANSWER:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+               if(req_answer_call(&cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Answer call fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Answer call fail. NO DATA\n");
+            }
+            break;
+        }
+        case RIL_MSG_ID_CALL_HANGUP:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                if(req_hangup_call(&cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Hang up call fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Hang up call fail.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_CALL_HANGUP_A:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_RIL_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_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Hang up a call fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_CALL_HANGUP_B:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                if(req_hangup_waiting_or_background_call(&cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Hang up waiting_or_background call fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            else
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Hang up waiting_or_background call fail.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_CALL_HANGUP_C:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                if(req_hangup_foreground_resume_background_call(&cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Hang up waiting_or_background call fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            else
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Hang up waiting_or_background call fail.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_CALL_WAITIN:
+        {
+            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_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Wait incoing call fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &reg, sizeof(mbtk_call_info_t));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Wait incoing call fail.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_CALL_MUTE:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                int state;
+                if(req_mute_get(&state, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get mute state fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &state, sizeof(uint8));
+                }
+            }
+            else     // Set mute state.
+            {
+                uint8 on = *(pack->data);
+                if(pack->data_len != sizeof(uint8) || (on != 0 && on != 1))
+                {
+                    err = MBTK_RIL_ERR_REQ_PARAMETER;
+                    LOG("Set mute parameter error.");
+                    break;
+                }
+
+                if(req_mute_set(on, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set mute state fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_CALL_DTMF:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_RIL_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_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Wait incoing call fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        default:
+        {
+            err = MBTK_RIL_ERR_REQ_UNKNOWN;
+            LOG("Unknown request : %s", id2str(pack->msg_id));
+            break;
+        }
+    }
+
+    return err;
+}
+
+
+
diff --git a/mbtk/mbtk_rild_v2/src/ril_data_call.c b/mbtk/mbtk_rild_v2/src/ril_data_call.c
new file mode 100755
index 0000000..a0f3eeb
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/src/ril_data_call.c
@@ -0,0 +1,41 @@
+#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_ril.h"
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_utils.h"
+#include "ril_info.h"
+
+/*
+IPv4 : 10.255.74.26
+IPv6 : 254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239
+*/
+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;
+    }
+}
+
+
diff --git a/mbtk/mbtk_rild_v2/src/ril_dev.c b/mbtk/mbtk_rild_v2/src/ril_dev.c
new file mode 100755
index 0000000..0fe2d2f
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/src/ril_dev.c
@@ -0,0 +1,705 @@
+#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_ril.h"
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_utils.h"
+#include "ril_info.h"
+
+void ril_rsp_pack_send(int fd, int ril_id, int msg_index, const void* data, int data_len);
+
+/*
+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;
+}
+
+/*
+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(mbtk_temp_type_enum type, int16 *temp, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = -1;
+    int tmp_int;
+    if(type == MBTK_TEMP_TYPE_SOC) { // 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 == MBTK_TEMP_TYPE_RF) { // RF
+        err = at_tok_nextint(&line, &tmp_int);
+        if (err < 0)
+        {
+            goto exit;
+        }
+        *temp = (int16)tmp_int;
+    } else {
+        tmp_int = tmp_int / 1000;
+        *temp = (int16)tmp_int;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CCLK?
++CCLK: "23/03/20,01:58:00+32"
+
+OK
+
+*/
+static int req_cell_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;
+}
+
+/*
+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
+*/
+mbtk_radio_state_enum ril_radio_state_get()
+{
+    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 done;
+    }
+
+    line = p_response->p_intermediates->line;
+
+    err = at_tok_start(&line);
+    if (err < 0) goto done;
+
+    err = at_tok_nextint(&line, &ret);
+    if (err < 0) goto done;
+
+    at_response_free(p_response);
+
+    ril_info.radio_state = (mbtk_radio_state_enum)ret;
+
+    return ril_info.radio_state;
+done:
+    at_response_free(p_response);
+    return MBTK_RADIO_STATE_UNKNOWN;
+}
+
+mbtk_ril_err_enum ril_radio_state_set(mbtk_radio_state_enum state, bool reset)
+{
+    int err;
+    ATResponse *p_response = NULL;
+    mbtk_ril_err_enum ret = MBTK_RIL_ERR_UNKNOWN;
+
+    if(state == ril_info.radio_state) {
+        LOGE("Radio state is same.");
+        //return MBTK_RIL_ERR_PARAMETER;
+        return MBTK_RIL_ERR_SUCCESS;
+    }
+
+    LOGI("Set radio state - %d", state);
+
+    char cmd[64] = {0};
+    if(reset) {
+        snprintf(cmd, sizeof(cmd), "AT+CFUN=%d,1", state);
+    } else {
+        snprintf(cmd, sizeof(cmd), "AT+CFUN=%d", state);
+    }
+    err = at_send_command(cmd, &p_response);
+    if (err || !p_response->success) {
+        goto done;
+    }
+
+    if(state == MBTK_RADIO_STATE_FULL_FUNC) { // +CFUN=1
+        if(ril_radio_state_get() == MBTK_RADIO_STATE_FULL_FUNC) { // success
+            ril_info.radio_state = MBTK_RADIO_STATE_FULL_FUNC;
+            ret = MBTK_RIL_ERR_SUCCESS;
+            LOGD("Radio open success.");
+        } else {
+            LOGW("Radio open fail.");
+        }
+    } else {
+        ril_info.radio_state = state;
+        ret = MBTK_RIL_ERR_SUCCESS;
+        LOGD("Set radio state to %d success.", state);
+    }
+
+done:
+    at_response_free(p_response);
+    return ret;
+}
+
+
+//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_ril_err_enum dev_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack)
+{
+    mbtk_ril_err_enum err = MBTK_RIL_ERR_SUCCESS;
+    int cme_err = MBTK_RIL_ERR_CME_NON;
+    switch(pack->msg_id)
+    {
+        case RIL_MSG_ID_DEV_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_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get IMEI fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, imei, strlen(imei));
+                }
+            }
+            else     // Set IMEI(Unsupport).
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set IMEI.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_DEV_SN:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                char sn[20] = {0};
+                if(req_sn_get(sn, &cme_err) || strlen(sn) == 0 || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get SN fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, sn, strlen(sn));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set SN.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_DEV_MEID:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Support only for CDMA.");
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set MEID.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_DEV_VERSION:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                char version[50] = {0};
+                if(req_version_get(version, &cme_err) || strlen(version) == 0 || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get Version fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, version, strlen(version));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set Version.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_DEV_MODEL:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                char model[50] = {0};
+                if(req_model_get(model, &cme_err) || strlen(model) == 0 || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get Version fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, model, strlen(model));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set Model.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_DEV_VOLTE: // <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_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get VoLTE state fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &state, sizeof(uint8));
+                }
+            }
+            else     // Set VoLTE state.
+            {
+                if(pack->data == NULL || pack->data_len != sizeof(uint8)
+                    || (*(pack->data) != 0 && *(pack->data) != 1))
+                {
+                    err = MBTK_RIL_ERR_REQ_PARAMETER;
+                    LOG("Set VOLTE parameter error.");
+                    break;
+                }
+
+                uint8 on = *(pack->data);
+                if(req_volte_set(on, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set VoLTE state fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+
+                    // Restart is required to take effect.
+                    // LOG("Will reboot system...");
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_DEV_TEMP:
+        {
+            if(pack->data && pack->data_len == sizeof(uint8)) {
+                int16 temp;
+                mbtk_temp_type_enum type = (mbtk_temp_type_enum)(*(pack->data));
+                if(req_temp_get(type, &temp, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get temperature fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &temp, sizeof(int16));
+                }
+            } else {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set Temperature.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_DEV_CELL_TIME:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get Time
+            {
+                char time[100] = {0};
+                if(req_cell_time_get(time, &cme_err) || strlen(time) == 0 || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get cell time fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, time, strlen(time));
+                }
+            }
+            else     // Set Time
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set cell time.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_DEV_MODEM:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_radio_state_enum radio_state = ril_radio_state_get();
+                if(radio_state == MBTK_RADIO_STATE_UNKNOWN)
+                {
+                    err = MBTK_RIL_ERR_UNKNOWN;
+                    LOG("Get Version fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &radio_state, sizeof(uint8));
+                }
+            }
+            else     // Set
+            {
+                // <func><reset>
+                if(pack->data && pack->data_len == 2) {
+                    mbtk_radio_state_enum radio_state = (mbtk_radio_state_enum)(*(pack->data));
+                    bool reset = *(pack->data + 1);
+                    err = ril_radio_state_set(radio_state, reset);
+                    if(MBTK_RIL_ERR_SUCCESS == err) {
+                        ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                    }
+                } else {
+                    err = MBTK_RIL_ERR_FORMAT;
+                }
+            }
+            break;
+        }
+        default:
+        {
+            err = MBTK_RIL_ERR_REQ_UNKNOWN;
+            LOG("Unknown request : %s", id2str(pack->msg_id));
+            break;
+        }
+    }
+
+    return err;
+}
+
+
+
+
diff --git a/mbtk/mbtk_rild_v2/src/ril_net.c b/mbtk/mbtk_rild_v2/src/ril_net.c
new file mode 100755
index 0000000..3f02965
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/src/ril_net.c
@@ -0,0 +1,1856 @@
+#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 <arpa/inet.h>
+
+#include "mbtk_type.h"
+#include "mbtk_ril.h"
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_utils.h"
+#include "ril_info.h"
+#include "mbtk_str.h"
+
+extern ril_band_info_t band_info;
+void ril_rsp_pack_send(int fd, int ril_id, int msg_index, const void* data, int data_len);
+static int req_apn_get(mbtk_apn_info_array_t *apns, int *cme_err);
+static int req_apn_set(mbtk_apn_info_t *apn, int *cme_err);
+static void apn_prop_get(ril_apn_info_array_t *apns);
+
+void apn_auto_conf_from_prop()
+{
+    ril_apn_info_array_t apns;
+    int i = 0;
+    memset(&apns, 0, sizeof(ril_apn_info_array_t));
+    apn_prop_get(&apns);
+    while(i < apns.num) {
+        int cme_err = MBTK_RIL_ERR_CME_NON;
+        if(req_apn_set(&(apns.apns[i]), &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+        {
+            LOGD("Set APN fail.");
+        }
+        else
+        {
+            LOGD("Set APN - %d success.", apns.apns[i].cid);
+        }
+        i++;
+    }
+}
+
+static bool apn_conf_support(mbtk_ril_cid_enum cid)
+{
+    if(cid == MBTK_RIL_CID_DEF) {
+        /*
+        uci show wan_default.default.enable
+        wan_default.default.enable='1'
+
+        uci get wan_default.default.enable
+        1
+        */
+        char buff[128] = {0};
+        if(mbtk_cmd_line("uci get wan_default.default.enable", buff, sizeof(buff)) && strlen(buff) > 0) {
+            return buff[0] == '1' ? FALSE : TRUE;
+        }
+    }
+    return TRUE;
+}
+
+static int apn_cid_reset(mbtk_apn_info_t *apn)
+{
+    // Delete apn
+    if(str_empty(apn->apn)) {
+        if(apn->cid == MBTK_RIL_CID_NUL)
+            return -1;
+
+        if(!apn_conf_support(MBTK_RIL_CID_DEF) && apn->cid == MBTK_RIL_CID_DEF)
+            return -1;
+
+        mbtk_apn_info_array_t apns;
+        int cme_err = MBTK_RIL_ERR_CME_NON;
+        memset(&apns, 0, sizeof(mbtk_apn_info_array_t));
+        if(req_apn_get(&apns, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+        {
+            LOGW("Get APN fail.");
+            return 0;
+        }
+        else
+        {
+            int index = 0;
+            while(index < apns.num) {
+                if(apns.apns[index].cid == apn->cid)
+                    return 0;
+                index++;
+            }
+            return -1;
+        }
+    } else {
+        if(apn->cid == MBTK_RIL_CID_NUL) {
+            int start_cid;
+            bool asr_auto_call_open = !apn_conf_support(MBTK_RIL_CID_DEF);
+            mbtk_apn_info_array_t apns;
+            int cme_err = MBTK_RIL_ERR_CME_NON;
+            if(asr_auto_call_open) {
+                start_cid = MBTK_RIL_CID_2;
+            } else {
+                start_cid = MBTK_APN_CID_MIN;
+            }
+            memset(&apns, 0, sizeof(mbtk_apn_info_array_t));
+            if(req_apn_get(&apns, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+            {
+                LOGW("Get APN fail.");
+                apn->cid = start_cid;
+            }
+            else
+            {
+                for(; start_cid <= MBTK_APN_CID_MAX; start_cid++) {
+                    int index = 0;
+                    while(index < apns.num) {
+                        if(apns.apns[index].cid == start_cid)
+                            break;
+                        index++;
+                    }
+
+                    if(index == apns.num) { // Found not used cid : start_cid.
+                        LOGD("Change CID : %d -> %d", apn->cid, start_cid);
+                        apn->cid = start_cid;
+                        return 0;
+                    }
+                }
+
+                if(start_cid > MBTK_APN_CID_MAX) {
+                    LOGE("APN full.");
+                    return -1;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+static void apn_prop_get(ril_apn_info_array_t *apns)
+{
+    char prop_name[20] = {0};
+    char prop_data[300] = {0};
+    int cid;
+    memset(apns, 0, sizeof(ril_apn_info_array_t));
+    bool asr_auto_call_open = !apn_conf_support(MBTK_RIL_CID_DEF);
+
+    // If auto data call is open,the default route is CID 1.
+    if(asr_auto_call_open) {
+        apns->cid_for_def_route = MBTK_RIL_CID_DEF;
+        cid = MBTK_RIL_CID_2;
+    } else {
+        if(property_get(MBTK_DEF_ROUTE_CID, prop_data, "") > 0 && !str_empty(prop_data)) {
+            apns->cid_for_def_route = (mbtk_ril_cid_enum)atoi(prop_data);
+        }
+        cid = MBTK_APN_CID_MIN;
+    }
+    for(; cid <= MBTK_APN_CID_MAX; cid++) {
+        memset(prop_name, 0, 20);
+        memset(prop_data, 0, 300);
+
+        sprintf(prop_name, "%s_%d",MBTK_APN_PROP,cid);
+        // ip_type,auth,auto_data_call,apn,user,pass
+        if(property_get(prop_name, prop_data, "") > 0 && !str_empty(prop_data)) {
+            apns->apns[apns->num].cid = (mbtk_ril_cid_enum)cid;
+            char *ptr_1 = prop_data;
+            apns->apns[apns->num].ip_type = (mbtk_ip_type_enum)atoi(ptr_1);
+            ptr_1 = strstr(ptr_1, ",");
+            if(!ptr_1) {
+                continue;
+            }
+            ptr_1++; // Jump ',' to auth
+
+            apns->apns[apns->num].auth = (mbtk_apn_auth_type_enum)atoi(ptr_1);
+            ptr_1 = strstr(ptr_1, ",");
+            if(!ptr_1) {
+                continue;
+            }
+            ptr_1++; // Jump ',' to auto_data_call
+
+            apns->apns[apns->num].auto_boot_call = (uint8)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;
+            }
+            if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+                memcpy(apns->apns[apns->num].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(apns->apns[apns->num].user, ptr_2, ptr_1 - ptr_2); // user
+            }
+
+            ptr_1++; // Jump ',' to pass
+            if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+                memcpy(apns->apns[apns->num].pass, ptr_1, strlen(ptr_1)); // pass
+            }
+
+            apns->num++;
+        }
+    }
+}
+
+static int apn_prop_get_by_cid(mbtk_ril_cid_enum cid, mbtk_apn_info_t *apn)
+{
+    char prop_name[20] = {0};
+    char prop_data[300] = {0};
+    memset(apn, 0, sizeof(mbtk_apn_info_t));
+
+    sprintf(prop_name, "%s_%d",MBTK_APN_PROP,cid);
+    // ip_type,auth,auto_data_call,apn,user,pass
+    if(property_get(prop_name, prop_data, "") > 0 && !str_empty(prop_data)) {
+        apn->cid = cid;
+        apn->auto_save = (uint8)1;
+        char *ptr_1 = prop_data;
+        apn->ip_type = (mbtk_ip_type_enum)atoi(ptr_1);
+        ptr_1 = strstr(ptr_1, ",");
+        if(!ptr_1) {
+            return -1;
+        }
+        ptr_1++; // Jump ',' to auth
+
+        apn->auth = (mbtk_apn_auth_type_enum)atoi(ptr_1);
+        ptr_1 = strstr(ptr_1, ",");
+        if(!ptr_1) {
+            return -1;
+        }
+        ptr_1++; // Jump ',' to auto_data_call
+
+        apn->auto_boot_call = (uint8)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;
+        }
+        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+            memcpy(apn->apn, ptr_1, ptr_2 - ptr_1); // apn
+        }
+
+        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
+        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+            memcpy(apn->pass, ptr_1, strlen(ptr_1)); // pass
+        }
+        return 0;
+    }
+    return -1;
+}
+
+static int apn_prop_set(mbtk_apn_info_t *apn)
+{
+    char prop_name[20] = {0};
+    char prop_data[300] = {0};
+    int ret = -1;
+    if(apn->auto_save) {
+        sprintf(prop_name, "%s_%d", MBTK_APN_PROP, apn->cid);
+        // Delete apn
+        if(!str_empty(apn->apn)) {
+            snprintf(prop_data, 300, "%d,%d,%d,%s,%s,%s", apn->ip_type, apn->auth, apn->auto_boot_call,
+                apn->apn,
+                str_empty(apn->user) ? "NULL" : apn->user,
+                str_empty(apn->pass) ? "NULL" : apn->pass);
+        }
+
+        ret = property_set(prop_name, prop_data);
+    }
+
+    if(apn->def_route) {
+        memset(prop_data, 0, sizeof(prop_data));
+        prop_data[0] = '0' + apn->cid;
+        ret = property_set(MBTK_DEF_ROUTE_CID, prop_data);
+    }
+    return ret;
+}
+
+static int apn_prop_reset(mbtk_data_call_info_t *data_info)
+{
+    mbtk_apn_info_t apn;
+    if(apn_prop_get_by_cid(data_info->cid, &apn)) {
+        return -1;
+    } else {
+        apn.auto_boot_call = data_info->auto_boot_call;
+        apn.def_route = data_info->def_route;
+        return apn_prop_set(&apn);
+    }
+}
+
+
+/*
+AT+COPS=?
+
++COPS: (2, "CHN-CT", "CT", "46011", 7),(3, "CHN-UNICOM", "UNICOM", "46001", 7),(3, "CHINA MOBILE", "CMCC", "46000", 0),(3, "CHINA MOBILE", "CMCC", "46000", 7),(3, "China Broadnet", "CBN", "46015", 7),,(0,1,2,3,4),(0,1,2)
+
+OK
+*/
+static int req_available_net_get(mbtk_net_info_array_t* nets, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command_singleline("AT+COPS=?", "+COPS:", &response);
+
+    if (err < 0 || response->success == 0 || !response->p_intermediates){
+        if(cme_err) {
+            *cme_err = at_get_cme_error(response);
+        }
+        goto exit;
+    }
+    char *line_ptr = response->p_intermediates->line;
+    if(line_ptr == NULL) {
+        LOG("line is NULL");
+        err = -1;
+        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' || *line_ptr == '3') {
+            nets->net_info[nets->num].net_state = (uint8)atoi(line_ptr); // net_state
+
+            line_ptr = strstr(line_ptr, ",");
+            if(line_ptr == NULL) {
+                err = -1;
+                goto exit;
+            }
+            line_ptr++;
+
+            line_ptr = strstr(line_ptr, ",");
+            if(line_ptr == NULL) {
+                err = -1;
+                goto exit;
+            }
+            line_ptr++;
+
+            line_ptr = strstr(line_ptr, ",");
+            if(line_ptr == NULL) {
+                err = -1;
+                goto exit;
+            }
+
+            while(*line_ptr != '\0' && (*line_ptr == ',' || *line_ptr == ' ' || *line_ptr == '"'))
+                line_ptr++;
+
+            // set sel_mode to 0
+            nets->net_info[nets->num].net_sel_mode = (uint8)0;
+            // Point to "46000"
+            //LOG("PLMN:%s",line_ptr);
+            //sleep(1);
+            //uint32_2_byte((uint32)atoi(line_ptr), buff_ptr + 3, false); // plmn
+            nets->net_info[nets->num].plmn = (uint32)atoi(line_ptr);
+
+            line_ptr = strstr(line_ptr, ",");
+            if(line_ptr == NULL) {
+                err = -1;
+                goto exit;
+            }
+
+            while(*line_ptr != '\0' && (*line_ptr == ',' || *line_ptr == ' '))
+                line_ptr++;
+
+            // Point to "7"
+            if(*line_ptr == '\0') {
+                err = -1;
+                goto exit;
+            }
+            //LOG("Type:%s",line_ptr);
+            //sleep(1);
+            nets->net_info[nets->num].net_type = (uint8)atoi(line_ptr); // net_type
+
+            nets->num++;
+        }
+
+        line_ptr = strstr(line_ptr, "(");
+    }
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+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) {
+        if(cme_err) {
+            *cme_err = at_get_cme_error(response);
+        }
+        goto exit;
+    }
+
+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[100] = {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 {
+        log_hex("BAND_SUPPORT", &band_info.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_info.band_support.gsm_band;
+        }
+        if(band->umts_band == 0) {
+            band->umts_band = band_info.band_support.umts_band;
+        }
+        if(band->tdlte_band == 0) {
+            band->tdlte_band = band_info.band_support.tdlte_band;
+        }
+        if(band->fddlte_band == 0) {
+            band->fddlte_band = band_info.band_support.fddlte_band;
+        }
+
+        if((band->gsm_band & band_info.band_support.gsm_band) != band->gsm_band) {
+            LOG("GSM band error.");
+            goto exit;
+        }
+
+        if((band->umts_band & band_info.band_support.umts_band) != band->umts_band) {
+            LOG("UMTS band error.");
+            goto exit;
+        }
+
+        if((band->tdlte_band & band_info.band_support.tdlte_band) != band->tdlte_band) {
+            LOG("TDLTE band error.");
+            goto exit;
+        }
+
+        if((band->fddlte_band & band_info.band_support.fddlte_band) != band->fddlte_band) {
+            LOG("FDDLTE band error.");
+            goto exit;
+        }
+
+        if((band->lte_ext_band & band_info.band_support.lte_ext_band) != band->lte_ext_band) {
+            LOG("EXT_LTE 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){
+                if(cme_err) {
+                    *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);
+        }
+
+        if(band->lte_ext_band > 0) {
+            sprintf(cmd, "AT*BAND=%d,%d,%d,%d,%d,,,,%d", band->net_pref, band->gsm_band, band->umts_band, band->tdlte_band, band->fddlte_band, band->lte_ext_band);
+        } else {
+            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){
+        if(cme_err) {
+            *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;
+
+    log_hex("BAND_SUPPORT", &band_info.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){
+        if(cme_err) {
+            *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;
+
+    // roamingConfig
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    // srvDomain
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    // bandPriorityFlag
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    //
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    // ltebandExt
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    band->lte_ext_band = (uint32)tmp_int;
+
+    log_hex("BAND", band, sizeof(mbtk_band_info_t));
+
+exit:
+    at_response_free(response);
+    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;
+
+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){
+        if(cme_err) {
+            *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){
+        if(cme_err) {
+            *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){
+        if(cme_err) {
+            *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","ctnet","10.142.64.116 254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.1",0,0,0,2,0,0
+
++CGDCONT: 8,"IPV4V6","IMS","254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.1",0,0,0,2,1,1
+
+OK
+
+*/
+static int req_apn_get(mbtk_apn_info_array_t *apns, 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){
+        if(cme_err) {
+            *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>
+    */
+    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) {
+            apns->apns[apns->num].cid = (mbtk_ril_cid_enum)tmp_int;
+
+            err = at_tok_nextstr(&line, &tmp_str);// ip type
+            if (err < 0)
+            {
+                goto exit;
+            }
+            if(!strcasecmp(tmp_str, "IP")) {
+                apns->apns[apns->num].ip_type = MBTK_IP_TYPE_IP;
+            } else if(!strcasecmp(tmp_str, "IPV6")) {
+                apns->apns[apns->num].ip_type = MBTK_IP_TYPE_IPV6;
+            } else if(!strcasecmp(tmp_str, "IPV4V6")) {
+                apns->apns[apns->num].ip_type = MBTK_IP_TYPE_IPV4V6;
+            } else {
+                apns->apns[apns->num].ip_type = MBTK_IP_TYPE_PPP;
+            }
+
+            err = at_tok_nextstr(&line, &tmp_str); // apn
+            if (err < 0)
+            {
+                goto exit;
+            }
+            if(!str_empty(tmp_str)) {
+                memcpy(apns->apns[apns->num].apn, tmp_str, strlen(tmp_str));
+            }
+
+            apns->num++;
+        }
+
+        lines_ptr = lines_ptr->p_next;
+    }
+
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CGDCONT=1,"IPV4V6","cmnet"
+OK
+
+AT*AUTHReq=1,1,marvell,123456
+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;
+
+    // Delete apn
+    if(str_empty(apn->apn)) {
+        sprintf(cmd, "AT+CGDCONT=%d", apn->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;
+        }
+    } else {
+        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);
+        }
+
+        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(apn->auth == MBTK_APN_AUTH_PROTO_NONE)
+                cmd_auth = 0;
+            else if(apn->auth == MBTK_APN_AUTH_PROTO_PAP)
+                cmd_auth = 1;
+            else if(apn->auth == MBTK_APN_AUTH_PROTO_CHAP)
+                cmd_auth = 2;
+            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){
+                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(mbtk_ril_cid_enum cid, bool def_route,
+                int retry_interval, int timeout, mbtk_ip_info_t *ip_info, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[400] = {0};
+    int err = 0;
+
+    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(mbtk_ril_cid_enum cid, int timeout, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[400] = {0};
+    int err = 0;
+
+    sprintf(cmd, "AT+CGACT=0,%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+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(mbtk_ril_cid_enum cid, mbtk_ip_info_t *ip_info, 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, &(ip_info->ipv4.IPAddr)) < 0) {
+                LOGE("inet_pton() fail.");
+                err = -1;
+                goto exit;
+            }
+
+            ip_info->ipv4.valid = true;
+            //log_hex("IPv4", &(ipv4->IPAddr), sizeof(struct in_addr));
+        } else {
+            if(str_2_ipv6(tmp_ptr, &(ip_info->ipv6.IPV6Addr))) {
+                LOGE("str_2_ipv6() fail.");
+                err = -1;
+                goto exit;
+            }
+
+            ip_info->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, &(ip_info->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, &(ip_info->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, &(ip_info->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, &(ip_info->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, &(ip_info->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, &(ip_info->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;
+}
+
+
+//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_ril_err_enum net_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack)
+{
+    mbtk_ril_err_enum err = MBTK_RIL_ERR_SUCCESS;
+    int cme_err = MBTK_RIL_ERR_CME_NON;
+    switch(pack->msg_id)
+    {
+        case RIL_MSG_ID_NET_AVAILABLE:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_net_info_array_t net_array;
+                memset(&net_array, 0, sizeof(mbtk_net_info_array_t));
+                if(req_available_net_get(&net_array, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOGD("Get Available Net fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &net_array, sizeof(mbtk_net_info_array_t));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOGW("Unsupport set available net.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_NET_SEL_MODE:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                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_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOGD("Get Net sel mode fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &info, sizeof(mbtk_net_info_t));
+                }
+            }
+            else     // Set
+            {
+                mbtk_net_info_t *info = (mbtk_net_info_t*)pack->data;
+                if(req_net_sel_mode_set(info, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOGD("Set Net sel mode fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_NET_BAND:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_RIL_ERR_REQ_PARAMETER;
+                LOG("No data found.");
+            }
+            else     // Set
+            {
+                if(pack->data_len == sizeof(uint8)) {
+                    if(*(pack->data)) { // Get current bands.
+                        mbtk_band_info_t band;
+                        memset(&band, 0x0, sizeof(mbtk_band_info_t));
+                        if(req_band_get(&band, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                        {
+                            if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                                err = MBTK_RIL_ERR_CME + cme_err;
+                            } else {
+                                err = MBTK_RIL_ERR_UNKNOWN;
+                            }
+                            LOG("Get net band fail.");
+                        }
+                        else
+                        {
+                            ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &band, sizeof(mbtk_band_info_t));
+                        }
+                    } else { // Get support bands.
+                        ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &band_info.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_RIL_ERR_REQ_PARAMETER;
+                        LOG("Set net band error.");
+                        break;
+                    }
+
+                    if(req_band_set(band, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                            err = MBTK_RIL_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_RIL_ERR_UNKNOWN;
+                        }
+                        LOG("Set net band fail.");
+                    }
+                    else
+                    {
+                        ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                    }
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_NET_SIGNAL:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_signal_info_t signal;
+                memset(&signal, 0, sizeof(mbtk_signal_info_t));
+                if(req_net_signal_get(&signal, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOGD("Get net signal fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &signal, sizeof(mbtk_signal_info_t));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOGW("Unsupport set net signal.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_NET_REG:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_net_reg_info_t net_reg;
+                memset(&net_reg, 0, sizeof(mbtk_net_reg_info_t));
+                if(req_net_reg_get(&net_reg, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOGD("Get Net reg info fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &net_reg, sizeof(mbtk_net_reg_info_t));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOGW("Unsupport set net reg info.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_NET_CELL:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_net_info_array_t net_array;
+                memset(&net_array, 0, sizeof(mbtk_net_info_array_t));
+                if(req_available_net_get(&net_array, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOGD("Get Available Net fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &net_array, sizeof(mbtk_net_info_array_t));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOGW("Unsupport set available net.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_NET_APN:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_apn_info_array_t apns;
+                memset(&apns, 0, sizeof(mbtk_apn_info_array_t));
+                if(req_apn_get(&apns, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOGD("Get APN fail.");
+                }
+                else
+                {
+                    LOGD("size - %d", sizeof(mbtk_apn_info_array_t));
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &apns, sizeof(mbtk_apn_info_array_t));
+                }
+            }
+            else     // Set
+            {
+                mbtk_apn_info_t *apn = (mbtk_apn_info_t*)pack->data;
+                if(apn_cid_reset(apn)) {
+                    err = MBTK_RIL_ERR_CID;
+                } else {
+                    if(apn_conf_support(apn->cid)) {
+                        if(req_apn_set(apn, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                        {
+                            if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                                err = MBTK_RIL_ERR_CME + cme_err;
+                            } else {
+                                err = MBTK_RIL_ERR_UNKNOWN;
+                            }
+                            LOGD("Set APN fail.");
+                        }
+                        else
+                        {
+                            if(apn_prop_set(apn)) {
+                                LOGE("Save APN fail.");
+                            }
+                            ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                        }
+                    } else {
+                        err = MBTK_RIL_ERR_UNSUPPORTED;
+                        LOGD("Can not set APN for CID : %d", apn->cid);
+                    }
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_NET_DATA_CALL:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set
+            {
+                mbtk_data_call_info_t *call_info = (mbtk_data_call_info_t*)pack->data;
+                if(call_info->type == MBTK_DATA_CALL_START) {
+                    mbtk_ip_info_t ip_info;
+                    memset(&ip_info, 0, sizeof(ip_info));
+                    if(apn_prop_reset(call_info)) {
+                        err = MBTK_RIL_ERR_REQ_UNKNOWN;
+                        LOG("apn_prop_reset() fail.");
+                    } else {
+                        if(req_data_call_start(call_info->cid, call_info->def_route,
+                                call_info->retry_interval, call_info->timeout, &ip_info, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                        {
+                            if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                                err = MBTK_RIL_ERR_CME + cme_err;
+                            } else {
+                                err = MBTK_RIL_ERR_UNKNOWN;
+                            }
+                            LOGD("Start data call fail.");
+                        }
+                        else
+                        {
+                            ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &ip_info, sizeof(mbtk_ip_info_t));
+                        }
+                    }
+                } else if(call_info->type == MBTK_DATA_CALL_STOP) {
+                    if(req_data_call_stop(call_info->cid, call_info->timeout, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                            err = MBTK_RIL_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_RIL_ERR_UNKNOWN;
+                        }
+                        LOGD("Stop data call fail.");
+                    }
+                    else
+                    {
+                        ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                    }
+                } else {
+                    mbtk_ip_info_t ip_info;
+                    memset(&ip_info, 0, sizeof(ip_info));
+                    if(req_data_call_state_get(call_info->cid ,&ip_info, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                    {
+                        if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                            err = MBTK_RIL_ERR_CME + cme_err;
+                        } else {
+                            err = MBTK_RIL_ERR_UNKNOWN;
+                        }
+                        LOGD("Get data call state fail.");
+                    }
+                    else
+                    {
+                        ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &ip_info, sizeof(mbtk_ip_info_t));
+                    }
+                }
+            }
+            break;
+        }
+        default:
+        {
+            err = MBTK_RIL_ERR_REQ_UNKNOWN;
+            LOG("Unknown request : %s", id2str(pack->msg_id));
+            break;
+        }
+    }
+
+    return err;
+}
+
+
+
+
+
+
diff --git a/mbtk/mbtk_rild_v2/src/ril_pb.c b/mbtk/mbtk_rild_v2/src/ril_pb.c
new file mode 100755
index 0000000..088aa46
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/src/ril_pb.c
@@ -0,0 +1,57 @@
+#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_ril.h"
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_utils.h"
+#include "ril_info.h"
+
+void ril_rsp_pack_send(int fd, int ril_id, int msg_index, 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_ril_err_enum pb_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack)
+{
+    mbtk_ril_err_enum err = MBTK_RIL_ERR_SUCCESS;
+    int cme_err = MBTK_RIL_ERR_CME_NON;
+    switch(pack->msg_id)
+    {
+        case RIL_MSG_ID_PB_STATE:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set
+            {
+
+            }
+            break;
+        }
+        default:
+        {
+            err = MBTK_RIL_ERR_REQ_UNKNOWN;
+            LOG("Unknown request : %s", id2str(pack->msg_id));
+            break;
+        }
+    }
+
+    return err;
+}
+
+
+
+
+
diff --git a/mbtk/mbtk_rild_v2/src/ril_sim.c b/mbtk/mbtk_rild_v2/src/ril_sim.c
new file mode 100755
index 0000000..ebc09f2
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/src/ril_sim.c
@@ -0,0 +1,847 @@
+#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_ril.h"
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_utils.h"
+#include "ril_info.h"
+
+void ril_rsp_pack_send(int fd, int ril_id, int msg_index, const void* data, int data_len);
+
+/** Returns SIM_NOT_READY on error */
+mbtk_sim_state_enum ril_sim_state_get()
+{
+    ATResponse *p_response = NULL;
+    int err;
+    mbtk_sim_state_enum ret = MBTK_SIM_STATE_UNKNOWN;
+    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_STATE_NOT_READY;
+        goto done;
+    }
+
+    switch (at_get_cme_error(p_response))
+    {
+        case CME_SUCCESS:
+            break;
+
+        case CME_SIM_NOT_INSERTED:
+            ret = MBTK_SIM_STATE_ABSENT;
+            goto done;
+
+        default:
+            ret = MBTK_SIM_STATE_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_STATE_NOT_READY;
+        goto done;
+    }
+
+    err = at_tok_nextstr(&cpinLine, &cpinResult);
+
+    if (err < 0)
+    {
+        ret = MBTK_SIM_STATE_NOT_READY;
+        goto done;
+    }
+
+    if (0 == strcmp (cpinResult, "SIM PIN"))
+    {
+        ret = MBTK_SIM_STATE_SIM_PIN;
+    }
+    else if (0 == strcmp (cpinResult, "SIM PUK"))
+    {
+        ret = MBTK_SIM_STATE_SIM_PUK;
+    }
+    else if (0 == strcmp (cpinResult, "PH-SIMLOCK PIN"))
+    {
+        ret = MBTK_SIM_STATE_PH_SIMLOCK_PIN;
+    }
+    else if (0 == strcmp (cpinResult, "PH-SIMLOCK PIN"))
+    {
+        ret = MBTK_SIM_STATE_PH_SIMLOCK_PUK;
+    }
+    else if (0 == strcmp (cpinResult, "PH-FSIM PIN"))
+    {
+        ret = MBTK_SIM_STATE_PH_FSIM_PIN;
+    }
+    else if (0 == strcmp (cpinResult, "PH-FSIM PUK"))
+    {
+        ret = MBTK_SIM_STATE_PH_FSIM_PUK;
+    }
+    else if (0 == strcmp (cpinResult, "SIM PIN2"))
+    {
+        ret = MBTK_SIM_STATE_SIM_PIN2;
+    }
+    else if (0 == strcmp (cpinResult, "SIM PUK2"))
+    {
+        ret = MBTK_SIM_STATE_SIM_PUK2;
+    }
+    else if (0 == strcmp (cpinResult, "PH-NET PIN"))
+    {
+        ret = MBTK_SIM_STATE_PH_NET_PIN;
+    }
+    else if (0 == strcmp (cpinResult, "PH-NET PUK"))
+    {
+        ret = MBTK_SIM_STATE_PH_NET_PUK;
+    }
+    else if (0 == strcmp (cpinResult, "PH-NETSUB PIN"))
+    {
+        ret = MBTK_SIM_STATE_PH_NETSUB_PIN;
+    }
+    else if (0 == strcmp (cpinResult, "PH-NETSUB PUK"))
+    {
+        ret = MBTK_SIM_STATE_PH_NETSUB_PUK;
+    }
+    else if (0 == strcmp (cpinResult, "PH-SP PIN"))
+    {
+        ret = MBTK_SIM_STATE_PH_SP_PIN;
+    }
+    else if (0 == strcmp (cpinResult, "PH-SP PUK"))
+    {
+        ret = MBTK_SIM_STATE_PH_SP_PUK;
+    }
+    else if (0 == strcmp (cpinResult, "PH-CORP PIN"))
+    {
+        ret = MBTK_SIM_STATE_PH_CORP_PIN;
+    }
+    else if (0 == strcmp (cpinResult, "PH-CORP PUK"))
+    {
+        ret = MBTK_SIM_STATE_PH_CORP_PUK;
+    }
+    else if (0 == strcmp (cpinResult, "READY"))
+    {
+        ret = MBTK_SIM_STATE_READY;
+    } else {
+        ret = MBTK_SIM_STATE_ABSENT;
+    }
+
+done:
+    at_response_free(p_response);
+    p_response = NULL;
+    cpinResult = NULL;
+    ril_info.sim_state = ret;
+    return ret;
+}
+
+/*
+AT*EUICC?
+*EUICC: 1
+
+OK
+*/
+static int req_sim_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+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;
+}
+
+static int req_sim_lock_state_get(int *state, 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;
+    }
+    err = at_tok_nextint(&line, state);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+*
+AT+CLCK=SC,0,1234
++CLCK: 0
+
+OK
+
+AT+CLCK=SC,1,1234
++CLCK: 1
+
+OK
+
+*
+*/
+static int req_sim_lock_switch(bool enable, uint8* pin, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[64]={0};
+    snprintf(cmd, sizeof(cmd), "AT+CLCK=SC,%d,%s", enable ? 1 : 0, pin);
+    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;
+    }
+
+    int ret;
+    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_nextint(&line, &ret);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    if(enable) {
+        if(ret != 1) {
+            LOGW("+CLCK not 1.");
+            err = -1;
+            goto exit;
+        }
+    } else {
+        if(ret != 0) {
+            LOGW("+CLCK not 0.");
+            err = -1;
+            goto exit;
+        }
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+static int req_sim_pin_change(uint8* old_pin, uint8 *new_pin, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[128]={0};
+    int err = 0;
+    int state;
+    if(req_sim_lock_state_get(&state, cme_err) || *cme_err != MBTK_RIL_ERR_CME_NON)
+    {
+        return -1;
+    }
+
+    if(state == 0) { // Sim lock not open.
+        return req_sim_lock_switch(TRUE, new_pin, cme_err);
+    } else {// Change password.
+        snprintf(cmd, sizeof(cmd), "AT+CPWD=SC,%s,%s", old_pin, new_pin);
+        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;
+}
+
+static int req_sim_pin_verify(uint8* pin, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[64]={0};
+    sprintf(cmd, "AT+CPIN=%s", pin);
+    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;
+}
+
+static int req_sim_puk_verify(uint8* puk, uint8* pin, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[64]={0};
+    sprintf(cmd, "AT+CPIN=%s,%s", puk, pin);
+    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;
+}
+
+static int req_sim_lock_set(mbtk_sim_lock_info_t *lock_info, int *cme_err)
+{
+    switch(lock_info->type)
+    {
+        case MBTK_SIM_LOCK_TYPE_DISABLE:
+        {
+            return req_sim_lock_switch(FALSE, lock_info->pin1, cme_err);
+        }
+        case MBTK_SIM_LOCK_TYPE_ENABLE:
+        {
+            return req_sim_lock_switch(TRUE, lock_info->pin1, cme_err);
+        }
+        case MBTK_SIM_LOCK_TYPE_CHANGE:
+        {
+            return req_sim_pin_change(lock_info->pin1, lock_info->pin2, cme_err);
+        }
+        case MBTK_SIM_LOCK_TYPE_VERIFY_PIN:
+        {
+            return req_sim_pin_verify(lock_info->pin1, cme_err);
+        }
+        case MBTK_SIM_LOCK_TYPE_VERIFY_PUK:
+        {
+            return req_sim_puk_verify(lock_info->puk, lock_info->pin1, cme_err);
+        }
+        default:
+        {
+            LOGE("Unknown type : %d", lock_info->type);
+            break;
+        }
+    }
+
+    return -1;
+}
+
+/*
+AT+EPIN?
++EPIN: 3,0,10,0
+
+OK
+*/
+static int req_pin_puk_last_times_get(mbtk_pin_puk_last_times_t *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_t 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+CPOL?
+*EUICC: 1
+
+OK
+*/
+static int req_plmn_get(mbtk_plmn_info *info, 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;
+            }
+            info->count = count;
+
+            err = at_tok_nextint(&line, &mccmnc_type);
+            if (err < 0)
+            {
+                goto exit;
+            }
+            info->plmn[count-1].format = mccmnc_type;
+
+            err = at_tok_nextstr(&line, &mccmnc_name);
+            if (err < 0)
+            {
+                goto exit;
+            }
+            memcpy(info->plmn[count-1].name, mccmnc_name, strlen(mccmnc_name));
+            mccmnc_name = NULL;
+        }
+        lines_ptr = lines_ptr->p_next;
+    }
+
+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_ril_err_enum sim_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack)
+{
+    mbtk_ril_err_enum err = MBTK_RIL_ERR_SUCCESS;
+    int cme_err = MBTK_RIL_ERR_CME_NON;
+    switch(pack->msg_id)
+    {
+        case RIL_MSG_ID_SIM_STATE:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_sim_state_enum state = ril_sim_state_get();
+                if(state == MBTK_SIM_STATE_UNKNOWN)
+                {
+                    err = MBTK_RIL_ERR_UNKNOWN;
+                    LOG("Get sim state fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &state, sizeof(uint8));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set sim state.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_SIM_TYPE:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                uint8 sim_card_type;
+                if(req_sim_type_get(&sim_card_type, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get IMSI fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &sim_card_type, sizeof(uint8));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set sim type.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_SIM_IMSI:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                char imsi[20] = {0};
+                if(req_imsi_get(imsi, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get IMSI fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, imsi, strlen(imsi));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set IMSI.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_SIM_PN:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                char pn[50] = {0};
+                if(req_phone_number_get(pn, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get PN fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, pn, strlen(pn));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set PN.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_SIM_ICCID:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                char iccid[50] = {0};
+                if(req_iccid_get(iccid, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get ICCID fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, iccid, strlen(iccid));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set ICCID.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_SIM_LOCK:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                int state;
+                if(req_sim_lock_state_get(&state, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get sim lock state fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &state, sizeof(uint8));
+                }
+            }
+            else     // Set
+            {
+                mbtk_sim_lock_info_t *lock_info = (mbtk_sim_lock_info_t*)pack->data;
+                if(req_sim_lock_set(lock_info, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set sim lock fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_SIM_PINPUK_TIMES:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_pin_puk_last_times_t last_times;
+                if(req_pin_puk_last_times_get(&last_times, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get PIN/PUK Last times fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &last_times, sizeof(mbtk_pin_puk_last_times_t));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set PIN/PUK Last times.");
+            }
+            break;
+        }
+        case RIL_MSG_ID_SIM_PLMN:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_plmn_info info;
+                memset(&info, 0, sizeof(mbtk_plmn_info));
+                if(req_plmn_get(&info, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get PLMN list fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &info, sizeof(mbtk_plmn_info));
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+                LOG("Unsupport set PLMN list.");
+            }
+            break;
+        }
+        default:
+        {
+            err = MBTK_RIL_ERR_REQ_UNKNOWN;
+            LOG("Unknown request : %s", id2str(pack->msg_id));
+            break;
+        }
+    }
+
+    return err;
+}
+
diff --git a/mbtk/mbtk_rild_v2/src/ril_sms.c b/mbtk/mbtk_rild_v2/src/ril_sms.c
new file mode 100755
index 0000000..081ad01
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/src/ril_sms.c
@@ -0,0 +1,1203 @@
+#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_ril.h"
+#include "atchannel.h"
+#include "at_tok.h"
+#include "mbtk_utils.h"
+#include "ril_info.h"
+
+void ril_rsp_pack_send(int fd, int ril_id, int msg_index, 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[20] = {0};
+    char *ptr = cmgs;
+    int err = 0;
+	int data_len = 0;
+
+	char *src = strstr(cmgs, ",");
+	if(src != NULL)
+	{
+	    //LOG("[XIAORUI]req_cmgs_set()----------------src=%s",src);
+	    //LOG("[XIAORUI]req_cmgs_set()----------------ptr=%s",ptr);
+		memcpy(pnum, ptr,  src - ptr);
+		//LOG("[XIAORUI]req_cmgs_set()----------------pnum=%s",pnum);
+		src++;
+		int data_len = 0;
+        data_len = len - (src - ptr);
+		memcpy(data, src, data_len);
+		//LOG("[XIAORUI]req_cmgs_set()----------------data %s",data);
+	}
+
+	sprintf(cmd, "AT+CMGS=%s", pnum);
+	LOG("cmd:%s,data:%s---------", 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+CMGD=?
+
++CMGD: (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37),(0-4)
+
+OK
+
+*/
+static int req_cmgd_get(char *reg, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT+CMGD=?", "+CMGD:", &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;
+
+    const char* start = strchr(line, '(');
+    const char* end = strchr(line, ')');
+
+    if (start && end && end > start)
+    {
+        int len_t = end - start - 1;
+        char substr_t[len_t + 1];
+
+        strncpy(substr_t, start + 1, len_t);
+        substr_t[len_t] = '\0';
+        strncpy(reg, substr_t, len_t);
+    }
+    else
+    {
+        strcpy(reg, "");
+    }
+
+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_ril_err_enum sms_pack_req_process(sock_cli_info_t* cli_info, ril_msg_pack_info_t* pack)
+{
+    mbtk_ril_err_enum err = MBTK_RIL_ERR_SUCCESS;
+    int cme_err = MBTK_RIL_ERR_CME_NON;
+    switch(pack->msg_id)
+    {
+        case RIL_MSG_ID_SMS_CMGF:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                int state;
+                if(req_cmgf_get(&state, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get SMS CMGF fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &state, sizeof(uint8));
+                }
+            }
+            else     // Set VoLTE state.
+            {
+                uint8 mode = *(pack->data);
+                if(pack->data_len != sizeof(uint8) || (mode != 0 && mode != 1))
+                {
+                    err = MBTK_RIL_ERR_REQ_PARAMETER;
+                    LOG("Set SMS CMGF parameter error.");
+                    break;
+                }
+
+                if(req_cmgf_set(mode, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_SMS_CNMI:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // SET at+cnmi=1,2.
+            {
+                int state;
+                if(req_cnmi_set(&cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("set sms cnmi fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+			break;
+		}
+        case RIL_MSG_ID_SMS_CPMS:
+        {
+            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_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get SMS CMGF fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, reg, strlen(reg));
+                }
+            }
+            else     // Set VoLTE state.
+            {
+                char *mem = (char*)(pack->data);
+				int len = pack->data_len;
+                char reg[100] = {0};
+                LOGD("mem:%s, len:%d", pack->data, pack->data_len);
+
+                if(req_cpms_set(mem, reg, len, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    LOGD("cpms_set success, reg:%s", reg);
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, reg, strlen(reg));
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_SMS_CMGS:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+				char *cmgs = (char*)pack->data;
+				int len = pack->data_len;
+				char reg[50] ={0};
+                LOGD("mbtk_sms,cmgs:%s,len:%d", cmgs, len);
+
+                if(req_cmgs_set(cmgs,reg,len, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, reg, strlen(reg));
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_SMS_CMSS:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+				char *cmss = (char*)pack->data;
+				int len = pack->data_len;
+                char reg[128] = {0};
+                LOGD("mbtk_sms,cmgs:%s, len:%d", cmss, len);
+
+                if(req_cmss_set(cmss,reg, len, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    LOGD("req_cmss_set success, reg:%s", reg);
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_SMS_CMGR:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+                uint8 index = *(pack->data);
+                char reg[1024] = {0};
+                if(pack->data_len != sizeof(uint8) )
+                {
+                    err = MBTK_RIL_ERR_REQ_PARAMETER;
+                    LOG("Set SMS CMGF parameter error.");
+                    break;
+                }
+
+                if(req_cmgr_set(index, reg, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, reg, strlen(reg));
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_SMS_CMGW:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // +CMGW=<oa/da>[,<tooa/toda>[,<stat>]]<CR>
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set cmgw data.
+            {
+				char *cmgw = (char*)pack->data;
+				int len = pack->data_len;
+                LOGD("mbtk_sms,cmgw:%s,len:%d", cmgw, len);
+
+                if(req_cmgw_set(cmgw, len, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_SMS_CMGD:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                char reg[1024] = {0};
+                if(req_cmgd_get(reg, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get SMS CMGD fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, reg, strlen(reg));
+                }
+            }
+            else     // Set VoLTE state.
+            {
+				char *cmgd = (char*)pack->data;
+				int len = pack->data_len;
+                LOGD("mbtk_sms,cmgs:%s,len:%d", cmgd, len);
+
+                if(req_cmgd_set(cmgd,len, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+
+            }
+            break;
+        }
+        case RIL_MSG_ID_SMS_CMGL:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                err = MBTK_RIL_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};
+
+                if(req_cmgl_set(cmgl, reg, len, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    memcpy(reg1, reg, 1024);
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, reg1, strlen(reg1));
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_SMS_CSCA:
+        {
+            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_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Get SMS CSCA fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, csca, strlen(csca));
+                }
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+				char *csca = (char*)pack->data;
+				int len = pack->data_len;
+
+                if(req_csca_set(csca, len, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_SMS_CSMP:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+				char *csmp = (char*)pack->data;
+				int len = pack->data_len;
+
+                if(req_csmp_set(csmp,len, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_SMS_CSCB:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)   // Get VoLTE state.
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set VoLTE state.
+            {
+				char *cscb = (char*)pack->data;
+				int len = pack->data_len;
+
+                if(req_cscb_set(cscb,len, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                {
+                    if(cme_err != MBTK_RIL_ERR_CME_NON) {
+                        err = MBTK_RIL_ERR_CME + cme_err;
+                    } else {
+                        err = MBTK_RIL_ERR_UNKNOWN;
+                    }
+                    LOG("Set SMS CMGF fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        default:
+        {
+            err = MBTK_RIL_ERR_REQ_UNKNOWN;
+            LOG("Unknown request : %s", id2str(pack->msg_id));
+            break;
+        }
+    }
+
+    return err;
+}
+
+
+
+
+
diff --git a/mbtk/mbtk_servicesd_v2/Makefile b/mbtk/mbtk_servicesd_v2/Makefile
new file mode 100755
index 0000000..5208a5e
--- /dev/null
+++ b/mbtk/mbtk_servicesd_v2/Makefile
@@ -0,0 +1,51 @@
+BUILD_ROOT = $(shell pwd)/..
+include $(BUILD_ROOT)/Make.defines
+
+LOCAL_PATH=$(BUILD_ROOT)/mbtk_servicesd_v2
+
+INC_DIR += \
+		-I$(LOCAL_PATH)/inc \
+		-I$(BUILD_ROOT)/libmbtk_ril_v2/inc
+
+LIB_DIR +=
+
+LIBS += -lmbtk_lib -lmbtk_net -lmbtk_ril -lrilutil -lprop2uci -lmtel -laudio-apu -lcutils -ltinyalsa -lacm -lubus -lubox -lutil
+
+CFLAGS +=
+
+DEFINE +=
+
+#MY_FILES_PATH:=$(LOCAL_PATH)
+#ifeq ($(CONFIG_MBTK_QL_SUPPORT),y)
+#MY_FILES_PATH += $(LOCAL_PATH)/ql
+#endif
+
+#ifeq ($(CONFIG_MBTK_PLATFORM),linux)
+#MY_FILES_PATH += $(LOCAL_PATH)/platform/linux
+#endif
+#LOCAL_SRC_FILES = $(wildcard *.c) $(wildcard *.cpp)
+LOCAL_SRC_FILES = src/main.c \
+				  src/instance_monitor_service.c \
+				  src/led_control_service.c \
+				  src/ntp_service.c
+
+OBJS = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(LOCAL_SRC_FILES)))
+$(info OBJS = $(OBJS))
+
+dtarget := $(OUT_DIR)/bin/mbtk_servicesd
+
+all: $(dtarget)
+
+$(dtarget): $(OBJS)
+	@echo "  BIN     $@"
+	$(CC) $(CFLAGS) $(LIB_DIR) $(LIBS) $(OBJS) -o $@
+
+%.o:%.c
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+%.o:%.cpp
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+clean:
+	rm -f $(OBJS) $(dtarget)
+
diff --git a/mbtk/mbtk_servicesd_v2/inc/instance_info.h b/mbtk/mbtk_servicesd_v2/inc/instance_info.h
new file mode 100755
index 0000000..02bedfb
--- /dev/null
+++ b/mbtk/mbtk_servicesd_v2/inc/instance_info.h
@@ -0,0 +1,23 @@
+/*
+* instance_info.h
+*
+* Instance monitor service informations.
+*
+* Author : lb
+* Date   : 2024/6/12 16:56:22
+*/
+#ifndef _INSTANCE_INFO_H
+#define _INSTANCE_INFO_H
+#include "mbtk_type.h"
+
+#define INSTANCE_NUM_MAX 10
+
+typedef struct {
+    char ins_name[64];
+    char ins_cmd[128];
+    int ins_pid;
+} instance_info_t;
+
+
+
+#endif /* _INSTANCE_INFO_H */
diff --git a/mbtk/mbtk_servicesd_v2/inc/mbtk_led.h b/mbtk/mbtk_servicesd_v2/inc/mbtk_led.h
new file mode 100755
index 0000000..244805c
--- /dev/null
+++ b/mbtk/mbtk_servicesd_v2/inc/mbtk_led.h
@@ -0,0 +1,33 @@
+#ifndef __MBTK_LED_H__
+#define __MBTK_LED_H__
+
+typedef enum
+{
+    MBTK_STATUS_LED_CLOSE = 0,     /*close status_led*/
+    MBTK_STATUS_LED_OPEN           /*open status_led*/
+}mbtk_status_led_type;
+
+typedef enum
+{
+    MBTK_NET_LED_SEARCH_NETWORK = 0,/*Searching the network or talking on the phone*/
+    MBTK_NET_LED_DATA_CONNECT,       /*Data connection successful*/
+    MBTK_NET_LED_NET_CONNECT,        /*Network connection successful*/
+    MBTK_NET_LED_CALL_RINGBACK,         /*CALL during dialing*/
+    MBTK_NET_LED_CALL_CONNECT,         /*CALL connection successful*/
+    MBTK_NET_LED_CALL_DISCONNECT,         /*CALL disconnection*/
+    MBTK_NET_LED_POWER,               /*Turn off */
+    MBTK_NET_LED_SLEEP,             /* sleep */
+    MBTK_NET_LED_CLOSE,            /*close net_led*/
+    MBTK_NET_LED_OPEN              /*open net_led*/
+}mbtk_net_led_type;
+
+void mbtk_net_led_set(mbtk_net_led_type status);
+
+int status_led_set(mbtk_status_led_type status);
+
+int mbtk_led_init(void);
+
+#endif
+
+
+
diff --git a/mbtk/mbtk_servicesd_v2/src/instance_monitor_service.c b/mbtk/mbtk_servicesd_v2/src/instance_monitor_service.c
new file mode 100755
index 0000000..2557304
--- /dev/null
+++ b/mbtk/mbtk_servicesd_v2/src/instance_monitor_service.c
@@ -0,0 +1,106 @@
+/*
+*    instance_monitor_service.c
+*
+*    $file_describe$
+*
+*/
+/******************************************************************************
+
+                          EDIT HISTORY FOR FILE
+
+  WHEN        WHO       WHAT,WHERE,WHY
+--------    --------    -------------------------------------------------------
+2024/6/12     LiuBin      Initial version
+
+******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "instance_info.h"
+#include "mbtk_log.h"
+#include "mbtk_utils.h"
+
+#define INS_MONITOR_INTERVAL 3  // s
+
+int instance_info_size = 0;
+instance_info_t instance_infos[INSTANCE_NUM_MAX] = {0};
+
+static void program_start(instance_info_t *info)
+{
+    LOGD("Will start program : %s", info->ins_name);
+    system(info->ins_cmd);
+}
+
+static int pidof(const char *program)
+{
+    char buff[128] = {0};
+    char cmd[128] = {0};
+    snprintf(cmd, sizeof(cmd), "pidof %s", program);
+    if(mbtk_cmd_line(cmd, buff, sizeof(buff)) && strlen(buff)) {
+        int pid = atoi(buff);
+        if(pid > 0) {
+            return pid;
+        } else {
+            return -1;
+        }
+    }
+    return -1;
+}
+
+static void* ins_monitor_service_run(void *arg)
+{
+    int i = 0;
+    LOGD("Will monitor program:");
+    while(i < instance_info_size) {
+        LOGD("%s:%s", instance_infos[i].ins_name, instance_infos[i].ins_cmd);
+        if(instance_infos[i].ins_pid < 0) {
+            instance_infos[i].ins_pid = pidof(instance_infos[i].ins_name);
+        }
+
+        if(instance_infos[i].ins_pid < 0) {
+            LOGE("%s has not running,will not monitor...", instance_infos[i].ins_name);
+        }
+        i++;
+    }
+
+    while(1) {
+        sleep(INS_MONITOR_INTERVAL);
+        i = 0;
+        while(i < instance_info_size) {
+            if(instance_infos[i].ins_pid > 0) {
+                int pid = pidof(instance_infos[i].ins_name);
+                if(pid > 0) {
+                    // Programe is running, do nothing.
+                } else {
+                    program_start(instance_infos + i);
+                }
+            }
+            i++;
+        }
+    }
+
+    return NULL;
+}
+
+int ins_monitor_service_start()
+{
+    pthread_t pid;
+    pthread_attr_t thread_attr;
+    pthread_attr_init(&thread_attr);
+    if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
+    {
+        LOGE("pthread_attr_setdetachstate() fail.");
+        return -1;
+    }
+
+    if(pthread_create(&pid, &thread_attr, ins_monitor_service_run, NULL))
+    {
+        LOGE("pthread_create() fail.");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/mbtk/mbtk_servicesd_v2/src/led_control_service.c b/mbtk/mbtk_servicesd_v2/src/led_control_service.c
new file mode 100755
index 0000000..7fd53dc
--- /dev/null
+++ b/mbtk/mbtk_servicesd_v2/src/led_control_service.c
@@ -0,0 +1,322 @@
+#if 1
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include "mbtk_led.h"
+#include "mbtk_log.h"
+
+/****************************DEFINE***************************************/
+#define MBTK_RESULT_FAIL   -1
+#define MBTK_RESULT_SUCCESS 0
+
+#define MBTK_NET_LED 99
+#define MBTK_STATUS_LED 8
+/****************************DEFINE***************************************/
+
+/****************************VARIABLE***************************************/
+static mbtk_net_led_type mbtk_net_led_state = MBTK_NET_LED_SEARCH_NETWORK;
+static mbtk_net_led_type mbtk_net_led_prev_state = MBTK_NET_LED_SEARCH_NETWORK;
+static mbtk_status_led_type mbtk_status_led_state = MBTK_STATUS_LED_CLOSE;
+
+static int MBTK_NET_LED_LOCK_SET = 0;
+/****************************VARIABLE***************************************/
+
+/******************************FUNC*****************************************/
+int mbtk_read_ccinet(void)
+{
+    FILE *fp;
+    int ret = 0;
+    char buffer[1024];
+    char type[10]={0};
+
+    fp = popen("ifconfig", "r");
+    if (fp == NULL) {
+        printf("popen fail\n");
+        return -1;
+    }
+
+    fread(buffer,1, sizeof(buffer) -1, fp);
+    //LOGE("[led]buffer:%s\n", buffer);
+    pclose(fp); //
+
+    char *p1 = strstr(buffer, "ccinet");
+    if(p1 == NULL)
+    {
+    	//LOGE("[led]read ccinet is null\n");
+    	return -1;
+    }
+
+    return 0;
+}
+
+int mbtk_net_led_get(void)
+{
+
+    if (MBTK_NET_LED_LOCK_SET == 1)
+    {
+        mbtk_net_led_state = MBTK_NET_LED_CALL_CONNECT;//call 优先级最高
+        return mbtk_net_led_state;
+    }
+
+    if(mbtk_net_led_state == MBTK_NET_LED_OPEN)
+    {
+        mbtk_net_led_state = mbtk_net_led_prev_state;
+    }
+
+    int ret = -1;
+    if(mbtk_net_led_state == MBTK_NET_LED_NET_CONNECT)
+    {
+        ret = mbtk_read_ccinet();
+        if(ret == 0)
+        {
+            mbtk_net_led_state = MBTK_NET_LED_DATA_CONNECT;
+        }
+    }
+    return mbtk_net_led_state;
+}
+
+void mbtk_net_led_set(mbtk_net_led_type status)
+{
+    if(mbtk_net_led_state == MBTK_NET_LED_CLOSE)
+    {
+        if(status == MBTK_NET_LED_CLOSE || status == MBTK_NET_LED_OPEN)
+        {
+            //
+        }
+        else
+        {
+            mbtk_net_led_prev_state = status;
+        }
+    }
+    else
+    {
+        if(status == MBTK_NET_LED_CLOSE)
+        {
+            mbtk_net_led_prev_state = mbtk_net_led_state;
+        }
+    }
+
+    if (status == MBTK_NET_LED_CALL_CONNECT)
+    {
+        MBTK_NET_LED_LOCK_SET = 1;
+    }
+
+    if (status == MBTK_NET_LED_CALL_DISCONNECT)
+    {
+        MBTK_NET_LED_LOCK_SET = 0;
+        status = MBTK_NET_LED_NET_CONNECT;
+    }
+
+    mbtk_net_led_state = status;
+}
+
+static int mbtk_led_gpio_init(int gpio)
+{
+    char buffer[50]= {0};
+    char pin_index_buffer[5]= {0};
+    int fd =-1;
+    int result = -1;
+
+    memset(buffer,0,50);
+    sprintf(buffer,"/sys/class/gpio/gpio%d/direction", gpio);
+    if(access(buffer , F_OK) != 0)
+    {
+        fd = open("/sys/class/gpio/export",O_WRONLY);
+        if(fd < -1)
+        {
+            LOGE("[led]Open export fail.", gpio);
+            return MBTK_RESULT_FAIL;
+        }
+
+        memset(pin_index_buffer,0,5);
+        sprintf(pin_index_buffer,"%d", gpio);
+        result = write(fd,pin_index_buffer,strlen(pin_index_buffer));
+        close(fd);
+        if(result < 0)
+        {
+            LOGE("[led]Gpio[%d] export fail.", gpio);
+            return MBTK_RESULT_FAIL;
+        }
+        fd = -1;
+    }
+
+    fd = open(buffer, O_WRONLY);
+    if(fd < -1)
+    {
+        LOGE("[led]Open gpio[%d] direct fail.", gpio);
+        return MBTK_RESULT_FAIL;
+    }
+
+    result = write(fd, "out",strlen("out"));
+    close(fd);
+    if(result < 0)
+    {
+        LOGE("[led]Set gpio[%d] direct fail.", gpio);
+        return MBTK_RESULT_FAIL;
+    }
+    return MBTK_RESULT_SUCCESS;
+}
+
+static int mbtk_led_gpio_level_set(int gpio, int value)
+{
+    char buffer[50]= {0};
+    int fd =-1;
+    int result =-1;
+
+    memset(buffer,0,50);
+    sprintf(buffer,"/sys/class/gpio/gpio%d/value", gpio);
+    fd = open(buffer,O_WRONLY);
+    if(fd < -1)
+    {
+        LOGE("[led]Open gpio[%d] value fail.", gpio);
+        return MBTK_RESULT_FAIL;
+    }
+    if(value == 0)
+    {
+        result = write(fd,"0",1);
+    }
+    else
+    {
+        result = write(fd,"1",1);
+    }
+    close(fd);
+
+    if(result != 1)
+    {
+        LOGE("[led]Set gpio[%d] value fail.", gpio);
+        return MBTK_RESULT_FAIL;
+    }
+
+    return MBTK_RESULT_SUCCESS;
+}
+
+static void net_led_close(void)
+{
+    mbtk_led_gpio_level_set(MBTK_NET_LED, 0);
+}
+
+static void net_led_open(void)
+{
+    mbtk_led_gpio_level_set(MBTK_NET_LED, 1);
+}
+
+static void net_led_flicker_200ms(void)
+{
+    mbtk_led_gpio_level_set(MBTK_NET_LED, 1);
+    usleep(200000);
+    mbtk_led_gpio_level_set(MBTK_NET_LED, 0);
+    usleep(200000);
+}
+
+static void net_led_flicker_800ms(void)
+{
+    mbtk_led_gpio_level_set(MBTK_NET_LED, 1);
+    usleep(800000);
+    mbtk_led_gpio_level_set(MBTK_NET_LED, 0);
+    usleep(800000);
+}
+
+static void* net_led_thread_run(void* arg)
+{
+    mbtk_net_led_type status = MBTK_NET_LED_CLOSE;
+    while(1)
+    {
+        status = mbtk_net_led_get();
+        //LOGE("[led] get net led status = [%d].", status);
+
+        if (status == MBTK_NET_LED_CALL_CONNECT) //call 优先
+        {
+            net_led_open();
+        }
+        else
+        {
+            switch(status)
+            {
+                case MBTK_NET_LED_CLOSE:
+                case MBTK_NET_LED_POWER:
+                {
+                    net_led_close();
+                    sleep(2);
+                    break;
+                }
+                case MBTK_NET_LED_SEARCH_NETWORK:
+                {
+                    net_led_open();
+                    sleep(2);
+                    break;
+                }
+                case MBTK_NET_LED_DATA_CONNECT:
+                {
+                    net_led_flicker_200ms();
+                    break;
+                }
+                case MBTK_NET_LED_NET_CONNECT:
+                {
+                    net_led_flicker_800ms();
+                    break;
+                }
+                default:
+                {
+                    LOGE("[led]Uknown status.");
+                    break;
+                }
+            }
+        }
+        sleep(1);
+    }
+    return NULL;
+}
+
+int status_led_set(mbtk_status_led_type status)
+{
+    int ret = MBTK_RESULT_FAIL;
+    ret = mbtk_led_gpio_level_set(MBTK_STATUS_LED, status);
+    if(ret != MBTK_RESULT_SUCCESS)
+    {
+        LOGE("[led]set status led fail.");
+        return MBTK_RESULT_FAIL;
+    }
+
+    mbtk_status_led_state = status;
+    return MBTK_RESULT_SUCCESS;
+}
+
+
+int mbtk_led_init(void)
+{
+    int ret = MBTK_RESULT_FAIL;
+
+    mbtk_led_gpio_init(MBTK_STATUS_LED);
+    mbtk_led_gpio_init(MBTK_NET_LED);
+    status_led_set(MBTK_STATUS_LED_OPEN);
+    mbtk_net_led_set(MBTK_NET_LED_SEARCH_NETWORK);
+
+    pthread_attr_t thread_attr;
+    pthread_t net_led_thread_id;
+    pthread_t status_led_thread_id;
+    pthread_attr_init(&thread_attr);
+    if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
+    {
+        LOGE("[led] pthread_attr_setdetachstate() fail.");
+        return MBTK_RESULT_FAIL;
+    }
+
+    if(pthread_create(&net_led_thread_id, &thread_attr, net_led_thread_run, NULL))
+    {
+        LOGE("[led] pthread_create() fail.");
+        return MBTK_RESULT_FAIL;
+    }
+
+    pthread_attr_destroy(&thread_attr);
+    return MBTK_RESULT_SUCCESS;
+}
+/******************************FUNC*****************************************/
+
+#endif
+
diff --git a/mbtk/mbtk_servicesd_v2/src/main.c b/mbtk/mbtk_servicesd_v2/src/main.c
new file mode 100755
index 0000000..c832588
--- /dev/null
+++ b/mbtk/mbtk_servicesd_v2/src/main.c
@@ -0,0 +1,108 @@
+/*
+*    main.c
+*
+*    MBTK important service support.
+*
+*/
+/******************************************************************************
+
+                          EDIT HISTORY FOR FILE
+
+  WHEN        WHO       WHAT,WHERE,WHY
+--------    --------    -------------------------------------------------------
+2024/6/12     LiuBin      Initial version
+
+******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "mbtk_type.h"
+#include "mbtk_log.h"
+#include "instance_info.h"
+
+#define MBTK_SERVICES_PID_FILE "/var/run/mbtk_servicesd.pid"
+#define MBTK_SERVICES_CONF_FILE "/etc/mbtk_servicesd.conf"
+
+extern int instance_info_size;
+extern instance_info_t instance_infos[];
+int ins_monitor_service_start();
+
+static void config_parse(const char *conf_file)
+{
+    FILE *fptr = fopen(conf_file, "r");
+    if(fptr != NULL) {
+        char line[1024] = {0};
+        bool respawn_process = FALSE;
+        while(fgets(line, sizeof(line), fptr) != NULL && strlen(line) > 0) {
+            if(str_startwith(line, "#")) {
+                memset(line, 0, sizeof(line));
+                continue;
+            }
+
+            if(!respawn_process && str_startwith(line, "respawn_start")) {
+                respawn_process = TRUE;
+                memset(line, 0, sizeof(line));
+                continue;
+            } else if(respawn_process && str_startwith(line, "respawn_end")) {
+                respawn_process = FALSE;
+                memset(line, 0, sizeof(line));
+                continue;
+            }
+
+            char *ptr = line + strlen(line) - 1;
+            while(ptr >= line && (*ptr == '\r' || *ptr == '\n' || *ptr == ' ')) {
+                *ptr-- = '\0';
+            }
+
+            if(ptr < line) { // Empty line
+                memset(line, 0, sizeof(line));
+                continue;
+            }
+
+            if(respawn_process && instance_info_size < INSTANCE_NUM_MAX) {
+                ptr = strstr(line, ":");
+                if(ptr) {
+                    *ptr++ = '\0';
+                    memcpy(instance_infos[instance_info_size].ins_name, line, strlen(line));
+                    memcpy(instance_infos[instance_info_size].ins_cmd, ptr, strlen(ptr));
+                    instance_infos[instance_info_size].ins_pid = -1;
+                    instance_info_size++;
+                }
+            }
+
+            memset(line, 0, sizeof(line));
+        }
+        fclose(fptr);
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    mbtk_log_init("radio", "MBTK_SERVICES");
+
+#ifdef MBTK_DUMP_SUPPORT
+    mbtk_debug_open(NULL, TRUE);
+#endif
+
+    if(app_already_running(MBTK_SERVICES_PID_FILE)) {
+        LOGW("daemon already running.");
+        exit(1);
+    }
+
+    config_parse(MBTK_SERVICES_CONF_FILE);
+
+    // Start services.
+    if(ins_monitor_service_start()) {
+        LOGW("ins_monitor_service_start() fail.");
+    }
+
+    while(1) {
+        sleep(24 * 60 * 60);
+    }
+
+    return 0;
+}
+
diff --git a/mbtk/mbtk_servicesd_v2/src/ntp_service.c b/mbtk/mbtk_servicesd_v2/src/ntp_service.c
new file mode 100755
index 0000000..c552d88
--- /dev/null
+++ b/mbtk/mbtk_servicesd_v2/src/ntp_service.c
@@ -0,0 +1,122 @@
+/*
+*    ntp_service.c
+*
+*    NTP service source.
+*
+*/
+/******************************************************************************
+
+                          EDIT HISTORY FOR FILE
+
+  WHEN        WHO       WHAT,WHERE,WHY
+--------    --------    -------------------------------------------------------
+2024/7/5     LiuBin      Initial version
+
+******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <cutils/properties.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "mbtk_type.h"
+#include "mbtk_log.h"
+#include "mbtk_ntp.h"
+#include "mbtk_info_api.h"
+
+static bool is_first_boot = TRUE;
+
+
+//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)) {
+            LOGE("Set time fail:%d", errno);
+            return -1;
+        } else {
+            LOGD("Set time to %s.", str_time);
+            return 0;
+        }
+    } else {
+        LOGE("Set time fail.");
+        return -1;
+    }
+}
+
+static void* ntp_pthread_run(void* arg)
+{
+    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))
+    {
+        LOGE("pthread_attr_setdetachstate() fail.");
+        return;
+    }
+
+    if(pthread_create(&ntp_pid, &thread_attr, ntp_pthread_run, NULL))
+    {
+        LOGE("pthread_create() fail.");
+    }
+}
+
+/**
+* Called after starting the first time.
+*/
+int ntp_service_start()
+{
+    if(!is_first_boot) {
+        LOGW("NTP has already been executed.");
+        return -1;
+    }
+
+    is_first_boot = FALSE;
+
+    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
+        LOGE("Start NTP thread.");
+        ntp_thread_start();
+    }
+
+    return 0;
+}
diff --git a/mbtk/test/libmbtk_ril_v2/Makefile.backup b/mbtk/test/libmbtk_ril_v2/Makefile.backup
new file mode 100755
index 0000000..7acd22f
--- /dev/null
+++ b/mbtk/test/libmbtk_ril_v2/Makefile.backup
@@ -0,0 +1,34 @@
+BUILD_ROOT = $(shell pwd)/../..
+include $(BUILD_ROOT)/Make.defines
+
+INC_DIR +=
+
+LIB_DIR +=
+
+LIBS += -lmbtk_lib -lmbtk_ril
+
+CFLAGS += 
+
+DEFINE +=
+
+LOCAL_SRC_FILES = $(wildcard *.c) $(wildcard *.cpp)
+
+$(info LOCAL_SRC_FILES = $(LOCAL_SRC_FILES))
+
+OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(LOCAL_SRC_FILES)))
+BINS = $(patsubst %.o,%,$(OBJS))
+
+all: $(BINS)
+
+$(BINS):$(OBJS)
+	@echo "  BIN     $@"
+	$(CC) $(CFLAGS) $(LIB_DIR) $(LIBS) $@.o -o $(OUT_DIR)/bin/$@
+
+%.o:%.c
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+%.o:%.cpp
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+clean:
+	rm -f $(OBJS)
diff --git a/mbtk/test/libmbtk_ril_v2/mbtk_ril_test.c b/mbtk/test/libmbtk_ril_v2/mbtk_ril_test.c
new file mode 100755
index 0000000..cbb56c2
--- /dev/null
+++ b/mbtk/test/libmbtk_ril_v2/mbtk_ril_test.c
@@ -0,0 +1,1481 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include "mbtk_ril_api.h"
+
+#define CLI_THREAD_MAX 3
+
+typedef struct {
+    pthread_t pid;
+    bool is_running;
+    char name[20];
+} ril_cli_thread_info_t;
+
+static ril_cli_thread_info_t cli_threads[CLI_THREAD_MAX];
+static int cli_pid_index = 1;
+
+static void help()
+{
+    printf("version: Get version.\n");
+    printf("imei: Get IMEI.\n");
+    printf("sn: Get SN.\n");
+    printf("meid: Get MEID.\n");
+    printf("volte: Get VoLTE state.\n");
+    printf("volte 0: Close VoLTE.\n");
+    printf("volte 1: Open VoLTE.\n");
+    printf("radio: Get radio state.\n");
+    printf("radio 0 [0/1]: Close radio.\n");
+    printf("radio 1 [0/1]: Open radio.\n");
+    printf("temp <0,1>: Get SOC/RF temperature.\n");
+    printf("cell_time: Get cell time.\n");
+    printf("sim_state: Get sim state.\n");
+    printf("sim_type: Get sim type.\n");
+    printf("imsi: Get IMSI.\n");
+    printf("iccid: Get ICCID.\n");
+    printf("pn: Get Phone Number.\n");
+    printf("pin_state:Get Sim lock state.\n");
+    printf("pin_times:Get PIN/PUK last times.\n");
+    printf("pin_open <PIN>:Enable sim lock.\n");
+    printf("pin_close <PIN>:Disable sim lock.\n");
+    printf("pin_change <old_pin> <new_pin>:Change sim PIN.\n");
+    printf("pin_verify <PIN>:Verify PIN.\n");
+    printf("puk_verify <PUK> <PIN>:Verify PUK.\n");
+    printf("plmn:Get PLMN List.\n");
+    printf("avail_net: Get available network.\n");
+    printf("sel_mode: Get network select mode.\n");
+    printf("sel_mode <sel_mode> <net_type> <plmn>: Set network select mode.\n");
+    printf("band: Get current bands.\n");
+    printf("band support: Get support bands.\n");
+    printf("band <net_pref> <gsm_band> <umts_band> <tdlte_band> <fddlte_band>: Set current bands.\n");
+    printf("signal: Get network signal.\n");
+    printf("reg: Get network registe information.\n");
+    printf("cell: Get current cell information.\n");
+    printf("shutdown <0,1,2>: reboot/poweroff/halt system.\n");
+    printf("power_sim <0,1>: Power off/on sim.\n");
+    printf("time <0,1,2> YYYY-MM-DD HH:MM:SS : Set system time as CELL/NTP/User.\n");
+    printf("apn : Get current apns.\n");
+    printf("apn <cid> <ip_type:1/2/3/4> <save:0/1> <auto_call:0/1> <apn/null> : Set apn.\n");
+    printf("apn_del <cid> <save:0/1> : Delete APN.\n");
+    printf("data_call <0/1/2> <cid> <timeout>: Stop/Start/State data call.\n");
+    printf("call: Call the phone number.\n");
+    printf("answer: Answer the phone call.\n");
+    printf("hangup: Hang up all phone call. No id.\n");
+    printf("hangup 0: Hang up waiting or background phone call.\n");
+    printf("hangup 1: Hang up a phone call.\n");
+    printf("hangup 2: Hang up a phone call.\n");
+    printf("hangup 3: Hangup foreground resume background call.\n");
+    printf("waitin: Returns the list of current calls.\n");
+    printf("mute: Get mute state.\n");
+    printf("mute 0: Close mute.\n");
+    printf("mute 1: Open mute.\n");
+    printf("dtmf : Set dtmf character[0, 1, 2, ..., A, B, C, D, *, #], duration [300-600].\n   Such as: dtmf 0 300\n");
+    printf("ims_en 0/1 : Close/Open IMS(Restart takes effect).\n");
+    printf("ims_state : Get IMS open or not?\n");
+    printf("ims_reg: Get IMS register state.\n");
+}
+
+static void thread_exit_with_wait()
+{
+    int i = 0;
+    while(i < CLI_THREAD_MAX) {
+        cli_threads[i].is_running = FALSE;
+        i++;
+    }
+
+    i = 0;
+    while(i < CLI_THREAD_MAX) {
+        if(cli_threads[i].pid) {
+            pthread_join(cli_threads[i].pid, NULL);
+            printf("Thread (%s) exit.\n", cli_threads[i].name);
+        }
+        i++;
+    }
+}
+
+static void sig_process(int sig)
+{
+    LOGI("I got signal %d\n", sig);
+    switch(sig)
+    {
+        case SIGINT: // Ctrl + C
+        {
+            LOGI("Exit by SIGINT.\n");
+            thread_exit_with_wait();
+            mbtk_ril_deinit();
+            exit(0);
+        }
+        case SIGQUIT: // Ctrl + \ (类似 SIGINT ,但要产生core文件)
+        {
+            LOGI("Exit by SIGQUIT.\n");
+            thread_exit_with_wait();
+            mbtk_ril_deinit();
+            exit(0);
+        }
+        case SIGTERM:// 默认kill   (同 SIGKILL ,但 SIGKILL 不可捕获)
+        {
+            LOGI("Exit by SIGTERM.\n");
+            thread_exit_with_wait();
+            mbtk_ril_deinit();
+            exit(0);
+        }
+        case SIGTSTP:// Ctrl + Z (同 SIGSTOP ,但 SIGSTOP 不可捕获)
+        {
+            LOGI("Exit by SIGTSTP.\n");
+            exit(0);
+        }
+        case SIGSEGV: // 如空指针
+        {
+            LOGI("Exit by SIGSEGV.\n");
+            exit(0);
+        }
+        default:
+        {
+            LOGI("Unknown sig:%d\n",sig);
+            break;
+        }
+    }
+}
+
+static char* thread_id2name(pthread_t pid)
+{
+    int i = 0;
+    while(i < CLI_THREAD_MAX) {
+        if(pid == cli_threads[i].pid) {
+            return cli_threads[i].name;
+        }
+        i++;
+    }
+
+    return "UNKNOWN";
+}
+
+static void* sub_thread_run(void *arg)
+{
+    ril_cli_thread_info_t *cli = (ril_cli_thread_info_t*)arg;
+    cli->pid = pthread_self();
+    cli->is_running = TRUE;
+    sprintf(cli->name, "PID-%d", cli_pid_index++);
+
+    printf("[%s] enter.\n", thread_id2name(cli->pid));
+    while(cli->is_running) {
+        srand((int)(time(0) + cli->pid));
+        int time_sec = 1 + (int)(10.0 * rand() / ( RAND_MAX + 1.0));
+        char version[50] = {0};
+        mbtk_ril_err_enum err = mbtk_version_get(version);
+        if(err != MBTK_RIL_ERR_SUCCESS) {
+            printf("[%s : %ds]Error : %d\n", thread_id2name(cli->pid), time_sec, err);
+        } else {
+            printf("[%s : %ds]Version : %s\n", thread_id2name(cli->pid), time_sec, version);
+        }
+
+        sleep(time_sec);
+    }
+    printf("[%s] exit.\n", thread_id2name(cli->pid));
+    return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+    signal(SIGINT, sig_process);
+    signal(SIGQUIT, sig_process);
+    signal(SIGTERM, sig_process);
+    //signal(SIGTSTP, sig_process);
+    //signal(SIGSEGV, sig_process);
+
+    mbtk_log_init("radio","RIL_CLI");
+
+#ifdef MBTK_DUMP_SUPPORT
+    mbtk_debug_open(NULL, TRUE);
+#endif
+
+    //test2(0, "192.168.1.198");
+    //test2(1, "2409:8162:140:cd3c:1:2:1494:72ba");
+    //test2(1, "254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239");
+    //test2(1, "2400:3200::1");
+
+    if(mbtk_ril_init() != MBTK_RIL_ERR_SUCCESS)
+    {
+        return -1;
+    }
+
+#if 0
+    memset(cli_threads, 0, sizeof(ril_cli_thread_info_t) * CLI_THREAD_MAX);
+
+    pthread_t pid1, pid2, pid3;
+    if(pthread_create(&pid1, NULL, sub_thread_run, &cli_threads[0]))
+    {
+        printf("pthread_create() fail.");
+        goto exit;
+    }
+
+    if(pthread_create(&pid2, NULL, sub_thread_run, &cli_threads[1]))
+    {
+        printf("pthread_create() fail.");
+        goto exit;
+    }
+
+    if(pthread_create(&pid3, NULL, sub_thread_run, &cli_threads[2]))
+    {
+        printf("pthread_create() fail.");
+        goto exit;
+    }
+#endif
+    printf(">>>>>>>>>>>>>>>>>>>>>>>>Enter cmd:\n");
+    char cmd[100];
+    while(1)
+    {
+        memset(cmd, 0, 100);
+        mbtk_ril_err_enum err;
+        if(fgets(cmd, 100, stdin))
+        {
+            char *ptr = cmd + strlen(cmd) - 1;
+            while(ptr >= cmd && (*ptr == '\r' || *ptr == '\n'))
+            {
+                *ptr-- = '\0';
+            }
+            if(!strncasecmp(cmd, "version", 7))
+            {
+                char version[50] = {0};
+                err = mbtk_version_get(version);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Version : %s\n", version);
+                }
+            }
+            else if(!strncasecmp(cmd, "imei", 4)){
+                char imei[50] = {0};
+                err = mbtk_imei_get(imei);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("IMEI : %s\n", imei);
+                }
+            } else if(!strncasecmp(cmd, "sn", 2)){
+                char sn[50] = {0};
+                err = mbtk_sn_get(sn);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("SN : %s\n", sn);
+                }
+            } else if(!strncasecmp(cmd, "meid", 4)){
+                char meid[50] = {0};
+                err = mbtk_meid_get(meid);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("MEID : %s\n", meid);
+                }
+            } else if(!strncasecmp(cmd, "volte", 5)){ // "volte" or "volte 0" or "volte 1"
+                int volte;
+                if(!strcasecmp(cmd, "volte")) { // Get
+                    err = mbtk_volte_state_get(&volte);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE : %d\n", volte);
+                    }
+                } else { // Set
+                    if(!strcasecmp(cmd, "volte 1")) { // Open VoLTE
+                        volte = 1;
+                    } else { // Close VoLTE
+                        volte = 0;
+                    }
+                    err = mbtk_volte_state_set(volte);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "radio", 5)){ // "radio" or "radio 0" or "radio 1"
+                mbtk_radio_state_enum radio;
+                if(!strcasecmp(cmd, "radio")) { // Get
+                    err = mbtk_radio_state_get(&radio);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Radio : %d\n", radio);
+                    }
+                } else { // Set
+                    int reset;
+                    int count = sscanf(cmd, "radio %d %d", &radio, &reset);
+                    if(count > 0) {
+                        if(count == 1) {
+                            reset = 0;
+                        }
+
+                        err = mbtk_radio_state_set(radio, reset);
+                        if(err != MBTK_RIL_ERR_SUCCESS) {
+                            printf("Error : %d\n", err);
+                        } else {
+                            printf("Radio set success\n");
+                        }
+                    }
+                }
+            } else if(!strncasecmp(cmd, "temp", 4)){
+                int temp;
+                if(!strcasecmp(cmd, "temp 0")) {
+                    err = mbtk_temp_get(MBTK_TEMP_TYPE_SOC, &temp);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("SOC : %d\n", temp);
+                    }
+                } else if(!strcasecmp(cmd, "temp 1")) {
+                    err = mbtk_temp_get(MBTK_TEMP_TYPE_RF, &temp);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("RF : %d\n", temp);
+                    }
+                }
+            } else if(!strncasecmp(cmd, "cell_time", 9)){
+                char time[128] = {0};
+                err = mbtk_cell_time_get(time);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Cell Time : %s\n", time);
+                }
+            } else if(!strncasecmp(cmd, "sim_state", 9)){
+                mbtk_sim_state_enum sim;
+                err = mbtk_sim_state_get(&sim);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Sim State : %d\n", sim);
+                }
+            } else if(!strncasecmp(cmd, "sim_type", 8)){
+                mbtk_sim_card_type_enum type;
+                err = mbtk_sim_type_get(&type);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Sim Type : %d\n", type);
+                }
+            } else if(!strncasecmp(cmd, "imsi", 4)){
+                char imsi[50] = {0};
+                err = mbtk_imsi_get(imsi);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("IMSI : %s\n", imsi);
+                }
+            } else if(!strncasecmp(cmd, "iccid", 5)){
+                char iccid[50] = {0};
+                err = mbtk_iccid_get(iccid);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("ICCID : %s\n", iccid);
+                }
+            } else if(!strncasecmp(cmd, "pn", 2)){
+                char phone_number[50] = {0};
+                err = mbtk_phone_number_get(phone_number);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Phone Number : %s\n", phone_number);
+                }
+            }
+            /*
+                printf("pin_state:Get Sim lock state.\n");
+                printf("pin_times:Get PIN/PUK last times.\n");
+                printf("pin_open <PIN>:Enable sim lock.\n");
+                printf("pin_close <PIN>:Disable sim lock.\n");
+                printf("pin_change <old_pin> <new_pin>:Change sim PIN.\n");
+                printf("pin_verify <PIN>:Verify PIN.\n");
+                printf("puk_verify <PUK> <PIN>:Verify PUK.\n");
+            */
+            else if(!strncasecmp(cmd, "pin_state", 9)){
+                int lock_state;
+                err = mbtk_sim_lock_get(&lock_state);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("PIN state : %d\n", lock_state);
+                }
+            } else if(!strncasecmp(cmd, "pin_times", 9)){
+                mbtk_pin_puk_last_times_t times;
+                err = mbtk_sim_lock_retry_times_get(&times);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("PIN/PUK retry times:%d,%d,%d,%d\n", times.p1_retry, times.p2_retry, times.puk1_retry, times.puk2_retry);
+                }
+            } else if(!strncasecmp(cmd, "pin_open", 8)){
+                mbtk_sim_lock_info_t info;
+                info.type = MBTK_SIM_LOCK_TYPE_ENABLE;
+                int count = sscanf(cmd, "pin_open %s", info.pin1);
+                if(count == 1) {
+                    err = mbtk_sim_lock_set(&info);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Enable sim lock success.\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "pin_close", 9)){
+                mbtk_sim_lock_info_t info;
+                info.type = MBTK_SIM_LOCK_TYPE_DISABLE;
+                int count = sscanf(cmd, "pin_close %s", info.pin1);
+                if(count == 1) {
+                    err = mbtk_sim_lock_set(&info);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Disable sim lock success.\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "pin_change", 10)){
+                mbtk_sim_lock_info_t info;
+                info.type = MBTK_SIM_LOCK_TYPE_CHANGE;
+                int count = sscanf(cmd, "pin_change %s %s", info.pin1, info.pin2);
+                if(count == 2) {
+                    err = mbtk_sim_lock_set(&info);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("PIN change success.\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "pin_verify", 10)){
+                mbtk_sim_lock_info_t info;
+                info.type = MBTK_SIM_LOCK_TYPE_VERIFY_PIN;
+                int count = sscanf(cmd, "pin_verify %s", info.pin1);
+                if(count == 1) {
+                    err = mbtk_sim_lock_set(&info);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("PIN verify success.\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "puk_verify", 10)){
+                mbtk_sim_lock_info_t info;
+                info.type = MBTK_SIM_LOCK_TYPE_VERIFY_PUK;
+                int count = sscanf(cmd, "puk_verify %s %s", info.puk, info.pin1);
+                if(count == 2) {
+                    err = mbtk_sim_lock_set(&info);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("PUK verify success.\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "plmn", 4)){
+                mbtk_plmn_info info;
+                err = mbtk_plmn_list_get(&info);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("PLMN number:%d\n", info.count);
+                    int i = 0;
+                    while(i < info.count) {
+                        printf("%d,%d,%s\n", i+1, info.plmn[i].format, info.plmn[i].name);
+                        i++;
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "avail_net", 9)){
+                mbtk_net_info_array_t net_list;
+                err = mbtk_available_net_get(&net_list);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Available net number:%d\n", net_list.num);
+                    int i = 0;
+                    while(i < net_list.num) {
+                        printf("NET : %d,%d,%d,%d\n", net_list.net_info[i].net_sel_mode,
+                            net_list.net_info[i].net_type, net_list.net_info[i].net_state,
+                            net_list.net_info[i].plmn);
+                        i++;
+                    }
+                }
+            } else if(!strncasecmp(cmd, "sel_mode", 8)){ // "sel_mode" or "sel_mode 1 7 46000"
+                mbtk_net_info_t net;
+                memset(&net, 0, sizeof(mbtk_net_info_t));
+                if(!strcasecmp(cmd, "sel_mode")) { // Get
+                    err = mbtk_net_sel_mode_get(&net);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Net : %d, %d, %d, %d\n", net.net_sel_mode, net.net_type, net.net_state, net.plmn);
+                    }
+                } else { // Set
+                    char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    net.net_sel_mode = (uint8)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    net.net_type = (uint8)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    net.plmn = (uint32)atoi(ptr);
+
+                    err = mbtk_net_sel_mode_set(&net);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Net select mode set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "band", 4)){ // "band" or "band support" or "band 0 79 147 482 524503"
+                mbtk_band_info_t band;
+                memset(&band, 0x0, sizeof(mbtk_band_info_t));
+                if(!strcasecmp(cmd, "band")) { // Get
+                    err = mbtk_current_band_get(&band);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Band : %d, %d, %d, %d, %d, %d\n", band.net_pref, band.gsm_band, band.umts_band, band.tdlte_band, band.fddlte_band, band.lte_ext_band);
+                    }
+                } else if(!strcasecmp(cmd, "band support")) { // Get
+                    err = mbtk_support_band_get(&band);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Band : %d, %d, %d, %d, %d, %d\n", band.net_pref, band.gsm_band, band.umts_band, band.tdlte_band, band.fddlte_band, band.lte_ext_band);
+                    }
+                } else { // "band 0 79 147 482 524503"
+                    char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    band.net_pref = (uint8)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    band.gsm_band = (uint16)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    band.umts_band = (uint16)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    band.tdlte_band = (uint32)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    band.fddlte_band = (uint32)atoi(ptr);
+
+                    err = mbtk_current_band_set(&band);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Band set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "signal", 6)){
+                mbtk_signal_info_t signal;
+                err = mbtk_net_signal_get(&signal);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Signal : %d, %d, %d, %d, %d, %d, %d, %d\n", signal.type, signal.rssi, signal.rxlev, signal.ber,
+                        signal.rscp, signal.ecno, signal.rsrq, signal.rsrp);
+                }
+            } else if(!strncasecmp(cmd, "reg", 3)){
+                mbtk_net_reg_info_t reg;
+                err = mbtk_net_reg_get(&reg);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("REG : call_state=%d, data_state=%d, ims_state=%d, net_type=%d, %04x, %08x\n", reg.call_state, reg.data_state, reg.ims_state, reg.type, reg.lac, reg.ci);
+                }
+            } else if(!strncasecmp(cmd, "apn_del", 7)) {
+                mbtk_apn_info_t apn;
+                memset(&apn, 0, sizeof(mbtk_apn_info_t));
+                int cid, auto_save;
+                int count = sscanf(cmd, "apn_del %d %d", &cid, &auto_save);
+                if(count == 2) {
+                    apn.cid = (mbtk_ril_cid_enum)cid;
+                    apn.auto_save = (uint8)auto_save;
+                }
+                err = mbtk_apn_set(&apn);
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("APN delete success\n");
+                }
+
+            } else if(!strncasecmp(cmd, "apn", 3)){
+                if(!strcasecmp(cmd, "apn")) { // Get apn
+                    mbtk_apn_info_array_t apns;
+                    err = mbtk_apn_get(&apns);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("APN Num:%d\n", apns.num);
+                        int i = 0;
+                        while(i < apns.num) {
+                            printf("APN : %d, %s, %s\n", apns.apns[i].cid, apn2str(apns.apns[i].ip_type), apns.apns[i].apn);
+                            i++;
+                        }
+                    }
+                } else { // apn <cid> <0/1/2/3> <0/1> <0/1> <apn>
+                    mbtk_apn_info_t apn;
+                    memset(&apn, 0, sizeof(mbtk_apn_info_t));
+#if 1
+                    int cid, ip_type, auto_save, auto_boot_call;
+                    int count = sscanf(cmd, "apn %d %d %d %d %s",
+                                    &cid, &ip_type, &auto_save, &auto_boot_call, apn.apn);
+
+                    // Delete APN
+                    if(strcmp(apn.apn,"null") == 0 || strcmp(apn.apn,"NULL") == 0) {
+                        memset(apn.apn, 0, sizeof(apn.apn));
+                    }
+                    if(count == 5) {
+                        apn.cid = (mbtk_ril_cid_enum)cid;
+                        apn.ip_type = (mbtk_ip_type_enum)ip_type;
+                        apn.auto_save = (uint8)auto_save;
+                        apn.auto_boot_call = (uint8)auto_boot_call;
+                    }
+#else
+                    char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    apn.cid = (mbtk_ril_cid_enum)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    apn.ip_type = (mbtk_ip_type_enum)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    memcpy(apn.apn, ptr, strlen(ptr));
+#endif
+                    err = mbtk_apn_set(&apn);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("APN set success\n");
+                    }
+                }
+            }
+#if 0
+
+            else if(!strncasecmp(cmd, "cell", 4)){
+                char *ptr = strstr(cmd, ",");	 //CPMS,ME,ME,ME
+				if(ptr == NULL)
+				{
+                    printf("ptr == NULL\n");
+                    list_node_t* cell_list = NULL;
+                    int type;
+                    err = mbtk_cell_get(info_handle, &type, &cell_list);
+                    if(err || cell_list == NULL) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        list_first(cell_list);
+                        mbtk_cell_info_t* cell = (mbtk_cell_info_t*) list_next(cell_list);
+                        if(cell) { // Current server cell.
+                            switch(type)
+                            {
+                                case 0:
+                                    printf("GSM : lac=%d, ci=%d, arfcn=%d, bsic=%d\n", cell->value1, cell->value2, cell->value3, cell->value4);
+                                    break;
+                                case 1:
+                                    printf("UMTS : lac=%d, ci=%d, arfcn=%d\n", cell->value1, cell->value2, cell->value3);
+                                    break;
+                                case 2:
+                                    printf("LTE : tac=%d, PCI=%d, dlEuarfcn=%d, ulEuarfcn=%d, band=%d\n", cell->value1, cell->value2, cell->value3, cell->value4, cell->value5);
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+                        while ((cell = (mbtk_cell_info_t*) list_next(cell_list)))
+                        {
+                            switch(type)
+                            {
+                                case 0:
+                                    printf("CELL : %d, %d, %d, %d, %d", cell->value1, cell->value2, cell->value3, cell->value4, cell->value5);
+                                    break;
+                                case 1:
+                                    printf("CELL : lac=%d, ci=%d, arfcn=%d\n", cell->value1, cell->value2, cell->value3);
+                                    break;
+                                case 2:
+                                    printf("CELL : phyCellId=%d, euArfcn=%d, rsrp=%d, rsrq=%d\n", cell->value1, cell->value2, cell->value3, cell->value4);
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+                    }
+                    list_free(cell_list);
+                }
+                else{
+                    char *ptr = strstr(cmd, ",");	 //cell,2,3,,40936,430
+					char mem[50]={0};
+					char resp[1024] = {0};
+					if(ptr != NULL)
+					{
+						ptr++;
+						memset(mem, 0, sizeof(mem));
+						memcpy(mem, ptr, strlen(ptr));
+						printf("cell:%s\n", mem);
+					}
+					printf("cell_mem: %s \n", mem);
+
+					memset(resp, 0, sizeof(resp));
+					err = mbtk_cell_set(info_handle, mem, resp);
+					if(err) {
+						printf("Error : %d\n", err);
+					} else {
+						printf("cell set . resp:%s\n", resp);
+					}
+
+                }
+            } else if(!strncasecmp(cmd, "call", 4)){
+                char phone_number[12];
+                char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                memset(phone_number,0,strlen(phone_number));
+                memcpy(phone_number,ptr,strlen(ptr));
+                printf("phone number is: %s\n",phone_number);
+                err = mbtk_call_start(info_handle, phone_number);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Call success.\n");
+                }
+            } else if(!strncasecmp(cmd, "answer", 6)){
+                err = mbtk_call_answer(info_handle);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Call success.\n");
+                }
+            } else if(!strncasecmp(cmd, "hangup", 6)){
+                int phone_id;
+                if(!strcasecmp(cmd, "hangup")) { // hang up all
+                    err = mbtk_call_hang(info_handle);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Call hang up all.\n");
+                    }
+                } else if(!strcasecmp(cmd, "hangup 0")) {
+                    err = mbtk_waiting_or_background_call_hang(info_handle);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Call hang up waiting or background.\n");
+                    }
+                } else if(!strcasecmp(cmd, "hangup 3")) {
+                    err = mbtk_foreground_resume_background_call_hang(info_handle);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Call hang up foreground resume background.\n");
+                    }
+                } else {
+                    if(!strcasecmp(cmd, "hangup 1")) { // hang up a call
+                        phone_id = 1;
+                    } else if(!strcasecmp(cmd, "hangup 2")) {
+                        phone_id = 2;
+                    } else {
+                        printf("Error : Invalid input\n");
+                    }
+                    err = mbtk_a_call_hang(info_handle, phone_id);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("A Call hang up.\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "waitin", 6)){
+                mbtk_call_info_t reg;
+                err = mbtk_call_reg_get(info_handle, &reg);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    if(reg.call_wait == 0) {
+                        printf("No call ring\n");
+                    }
+                    else {
+                        printf("RING : %d, %d, %d, %d, %d, %s, %d\n", reg.dir1, reg.dir, reg.state, reg.mode, reg.mpty, reg.phone_number, reg.type);
+                    }
+                }
+            } else if(!strncasecmp(cmd, "mute", 4)){ // "mute" or "mute 0" or "mute 1"
+                int mute;
+                if(!strcasecmp(cmd, "mute")) { // Get
+                    err = mbtk_mute_state_get(info_handle, &mute);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("mute : %d\n", mute);
+                    }
+                } else { // Set
+                    if(!strcasecmp(cmd, "mute 1")) { // on mute
+                        mute = 1;
+                    } else { // off mute
+                        mute = 0;
+                    }
+                    err = mbtk_mute_state_set(info_handle, mute);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("mute set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "DTMF", 4)){ // valid character: (0, 1, ..., 9, A, B, C, D, *, #)
+
+                mbtk_call_dtmf_info_t reg;
+
+                char *ptr = strstr(cmd, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                reg.character = *ptr;
+
+                ptr = strstr(ptr, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                reg.duration = (uint32)atoi(ptr);
+                printf("DTMF character is: %c,%d\n",reg.character, reg.duration);
+                err = mbtk_dtmf_send(info_handle, &reg);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("DTMF success.\n");
+                }
+            } else if(!strncasecmp(cmd, "shutdown", 8)){
+                if(!strcasecmp(cmd, "shutdown 0")) {
+                    err = mbtk_system_reboot(0);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else if(!strcasecmp(cmd, "shutdown 1")) {
+                    err = mbtk_system_reboot(1);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else if(!strcasecmp(cmd, "shutdown 2")) {
+                    err = mbtk_system_reboot(2);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else {
+                    printf("Error.");
+                }
+            } else if(!strncasecmp(cmd, "power_sim", 9)){
+                if(!strcasecmp(cmd, "power_sim 0")) {
+                    err = mbtk_sim_power_set(0);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else if(!strcasecmp(cmd, "power_sim 1")) {
+                    err = mbtk_sim_power_set(1);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else {
+                    printf("Error.");
+                }
+            } else if(!strncasecmp(cmd, "time", 4)){
+                if(!strcasecmp(cmd, "time 0")) {
+                    err = mbtk_time_set(info_handle, 0, NULL);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else if(!strcasecmp(cmd, "time 1")) {
+                    err = mbtk_time_set(info_handle, 1, NULL);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else if(!strncasecmp(cmd, "time 2 ", 7)) {
+                    err = mbtk_time_set(info_handle, 2, cmd + 7);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else { // Get time type.
+                    int time_type;
+                    err = mbtk_time_get(info_handle, &time_type);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Time type:%d.\n", time_type);
+                    }
+                }
+            } else if(!strncasecmp(cmd, "apn", 3)){
+                if(!strcasecmp(cmd, "apn")) { // Get apn
+                #define APN_MAX 10
+                    mbtk_apn_info_t apns[APN_MAX];
+                    int apn_num = APN_MAX;
+                    err = mbtk_apn_get(info_handle, &apn_num, apns);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("APN Num:%d\n", apn_num);
+                        int i = 0;
+                        while(i < apn_num) {
+                            printf("APN : %d, %s, %s\n", apns[i].cid, apn2str(apns[i].ip_type), apns[i].apn);
+                            i++;
+                        }
+                    }
+                } else { // apn <cid> <0/1/2/3> <apn>
+                    char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    int cid = atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    mbtk_ip_type_enum ip_type = (mbtk_ip_type_enum)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    char *apn  = ptr;
+
+                    err = mbtk_apn_set(info_handle, cid, ip_type, apn, NULL, NULL, NULL);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("APN set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "data_call", 9)){ // data_call <0/1/2> <cid> <timeout>
+                // data_call <0/1/2> <cid> <timeout>
+                char *ptr = strstr(cmd, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                mbtk_data_call_type_enum type = (mbtk_data_call_type_enum)atoi(ptr);
+
+                ptr = strstr(ptr, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                int cid = atoi(ptr);
+
+                ptr = strstr(ptr, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                int timeout = atoi(ptr);
+
+                if(type == MBTK_DATA_CALL_START) {
+                    err = mbtk_data_call_start(info_handle, cid, 0, FALSE, timeout);
+                } else if(type == MBTK_DATA_CALL_STOP) {
+                    err = mbtk_data_call_stop(info_handle, cid, timeout);
+                } else {
+                    mbtk_ipv4_info_t ipv4;
+                    mbtk_ipv6_info_t ipv6;
+                    err = mbtk_data_call_state_get(info_handle, cid, &ipv4, &ipv6);
+                    if(!err) {
+                        if(ipv4.valid) {
+                            // log_hex("IPv4", &ipv4, sizeof(mbtk_ipv4_info_t));
+                            char ip_tmp[20];
+
+                            memset(ip_tmp, 0, 20);
+                            if(inet_ntop(AF_INET, &(ipv4.IPAddr), ip_tmp, 20) == NULL) {
+                                printf("IP error.\n");
+                            } else {
+                                printf("IP : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 20);
+                            if(inet_ntop(AF_INET, &(ipv4.PrimaryDNS), ip_tmp, 20) == NULL) {
+                                printf("PrimaryDNS error.\n");
+                            } else {
+                                printf("PrimaryDNS : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 20);
+                            if(inet_ntop(AF_INET, &(ipv4.SecondaryDNS), ip_tmp, 20) == NULL) {
+                                printf("SecondaryDNS error.\n");
+                            } else {
+                                printf("SecondaryDNS : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 20);
+                            if(inet_ntop(AF_INET, &(ipv4.GateWay), ip_tmp, 20) == NULL) {
+                                printf("GateWay error.\n");
+                            } else {
+                                printf("GateWay : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 20);
+                            if(inet_ntop(AF_INET, &(ipv4.NetMask), ip_tmp, 20) == NULL) {
+                                printf("NetMask error.\n");
+                            } else {
+                                printf("NetMask : %s\n", ip_tmp);
+                            }
+                        }
+
+                        if(ipv6.valid) {
+                            // log_hex("IPv6", &ipv6, sizeof(mbtk_ipv6_info_t));
+                            char ip_tmp[50];
+
+                            memset(ip_tmp, 0, 50);
+                            if(ipv6_2_str(&(ipv6.IPV6Addr), ip_tmp)) {
+                                printf("IP error.\n");
+                            } else {
+                                printf("IP : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 50);
+                            if(ipv6_2_str(&(ipv6.PrimaryDNS), ip_tmp)) {
+                                printf("PrimaryDNS error.\n");
+                            } else {
+                                printf("PrimaryDNS : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 50);
+                            if(ipv6_2_str(&(ipv6.SecondaryDNS), ip_tmp)) {
+                                printf("SecondaryDNS error.\n");
+                            } else {
+                                printf("SecondaryDNS : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 50);
+                            if(ipv6_2_str(&(ipv6.GateWay), ip_tmp)) {
+                                printf("GateWay error.\n");
+                            } else {
+                                printf("GateWay : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 50);
+                            if(ipv6_2_str(&(ipv6.NetMask), ip_tmp)) {
+                                printf("NetMask error.\n");
+                            } else {
+                                printf("NetMask : %s\n", ip_tmp);
+                            }
+                        }
+                    }
+                }
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("DATA_CALL success\n");
+                }
+            }else if(!strncasecmp(cmd, "cmgf", 4)){ // set mode 0: pud, 1:text
+                int mode;
+                if(!strcasecmp(cmd, "cmgf")) { // Get
+                    err = mbtk_sms_cmgf_get(info_handle, &mode);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE : %d\n", mode);
+                    }
+                } else { // Set
+                    if(!strcasecmp(cmd, "cmgf 1")) { // cmgf 1
+                        mode = 1;
+                    } else { //
+                        mode = 0;
+                    }
+                    printf("mode:%d\n", mode);
+                    sleep(2);
+                   err = mbtk_sms_cmgf_set(info_handle, mode);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE set success\n");
+                    }
+                }
+            }else if(!strncasecmp(cmd, "cpms", 4)){ // //CPMS=ME, ME, ME
+				char mem[100] = {0};
+                char resp[100] = {0};
+                if(!strcasecmp(cmd, "cpms")) { // Get
+                    err = mbtk_sms_cpms_get(info_handle, &mem);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cpms : %s\n", mem);
+                    }
+                } else { // Set
+
+					char *ptr = strstr(cmd, ",");    //CPMS,ME,ME,ME
+                    if(ptr != NULL)
+				    {
+				    	ptr++;
+                        memset(mem, 0, sizeof(mem));
+				        memcpy(mem, ptr, strlen(ptr));
+						printf("cpms:%s\n", mem);
+				    }
+                    printf("cpms 0\n");
+
+                    memset(resp, 0, sizeof(resp));
+                    err = mbtk_sms_cpms_set(info_handle, mem, resp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cpms set success. resp:%s\n", resp);
+                    }
+                }
+            }else if(!strncasecmp(cmd, "cmgs", 4)){ //   AT+CMGS="10086", CMGS TEST
+                char cmgs[1024] = {0};
+                char resp[50] = {0};
+                if(!strcasecmp(cmd, "cmgs")) { // Get
+                    int mode;
+                //    err = mbtk_sms_cmgs_get(info_handle, &mode);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE : %d\n", mode);
+                    }
+                } else { // Set
+
+							/*
+							*AT+CMGS="10086", CMGS TEST	                  // Send a SMS
+							> CMGS TEST
+							+CMGS: 17
+							OK
+							*/
+
+                    char *ptr = strstr(cmd, "cmgs,");      //CMGS="10086",hf
+                    if(ptr != NULL)
+				    {
+				    	ptr = strstr(cmd, ",");
+                        ptr++;
+                        memset(cmgs, 0, sizeof(cmgs));
+				        memcpy(cmgs, ptr, strlen(ptr));
+						printf("1cmgs:%s, strlen(cmgs):%d\n", cmgs, strlen(cmgs));
+				    }
+
+					memset(resp, 0, sizeof(resp));
+                    err = mbtk_sms_cmgs_set(info_handle, cmgs, resp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cmgs set success . resp:%s\n", resp);
+                    }
+                }
+            }else if(!strncasecmp(cmd, "cmss", 4)){ // +CMSS=<index>[,<da>[,<toda>]]
+                char cmss[20] = {0};
+                char resp[20] = {0};
+                if(!strcasecmp(cmd, "cmgs")) { // Get
+                    printf("cmss : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, "cmss,");    //CMSS=<index>
+                    if(ptr != NULL)
+				    {
+                        ptr = strstr(cmd, ",");
+				    	ptr++;
+                        memset(cmss, 0, sizeof(cmss));
+				        memcpy(cmss, ptr, strlen(ptr));
+						printf("1cmss:%s\n", cmss);
+				    }
+
+
+                    err = mbtk_sms_cmss_set(info_handle, cmss, resp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cmss set success. resp:%s\n", resp);
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "cmgr", 4)){ // +CMGR=<index
+                int index = 0;
+                char resp[1024] = {0};
+                if(!strcasecmp(cmd, "cmgr")) { // Get
+                    printf("cmgr : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, "cmgr,");    //+CMGR <index>
+                    if(ptr != NULL)
+				    {
+                        ptr = strstr(cmd, ",");
+                        ptr++;
+				    	index = atoi(ptr);
+				    }
+                    printf("1index:%d\n", index);
+
+                    memset(resp, 0, sizeof(resp));
+                    err = mbtk_sms_cmgr_set(info_handle, index, resp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cmgr set success. rep:%s\n", resp);
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "cmgw", 4)){ // +CMGW=<oa/da>[,<tooa/toda>[,<stat>]]<CR>
+                                                    //+CMGW=<length>[,<stat>]<CR>PDU is given<ctrl-Z/ESC>
+                char cmgw[128] = {0};
+                char resp[50] = {0};
+                if(!strcasecmp(cmd, "cmgw")) { // Get
+                    printf("cmgw : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, "cmgw,");    //+CMGW, <oa/da>, data
+                    if(ptr != NULL)
+				    {
+                        ptr = strstr(cmd, ",");
+				    	ptr++;
+                        memset(cmgw, 0, sizeof(cmgw));
+				        memcpy(cmgw, ptr, strlen(ptr));
+						printf("cmgw:%s\n", cmgw);
+				    }
+
+                    memset(resp, 0, sizeof(resp));
+                    err = mbtk_sms_cmgw_set(info_handle, cmgw, resp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cmgw set success. resp:%s\n", resp);
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "cmgd", 4)){ // +CMGD=<index>[,<delflag>
+                                                    //
+                char cmgd[128] = {0};
+                if(!strcasecmp(cmd, "cmgd")) { // Get
+                    printf("cmgd : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, ",");    //+CMGD=<index>[,<delflag>
+                    if(ptr != NULL)
+				    {
+				    	ptr++;
+                        memset(cmgd, 0, sizeof(cmgd));
+				        memcpy(cmgd, ptr, strlen(ptr));
+						printf("1cmgd:%s\n", cmgd);
+				    }
+
+
+                    err = mbtk_sms_cmgd_set(info_handle, cmgd);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE set success\n");
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "cmgl", 4)){ // AT+CMGL[=<stat>]
+                                                    //
+                char cmgl[128] = {0};
+                char resp[5*1024] ={0};
+                if(!strcasecmp(cmd, "cmgl")) { // Get
+                    printf("cmgl : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, "cmgl,");  //  AT+CMGL[=<stat>]
+                    if(ptr != NULL)
+				    {
+                        ptr = strstr(cmd, ",");
+				    	ptr++;
+                        memset(cmgl, 0, sizeof(cmgl));
+				        memcpy(cmgl, ptr, strlen(ptr));
+						printf("0cmgl:%s\n", cmgl);
+				    }
+
+					memset(resp, 0, sizeof(resp));
+                    err = mbtk_sms_cmgl_set(info_handle, cmgl, resp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                      //  printf("cmgl set success, reg:%s\n",resp);
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "csca", 4)){ // AT+CSCA=<number> [,<type>]
+                                                    //
+                char csca[128] = {0};
+                if(!strcasecmp(cmd, "csca")) { // Get
+                    err = mbtk_sms_csca_get(info_handle, csca);
+                    if(err) {
+                        printf("mbtk_sms_csca_get Error : %d\n", err);
+                    } else {
+                        printf("mbtk_sms_csca_get success\n");
+                    }
+
+                } else {
+                    char *ptr = strstr(cmd, ",");  //  AT+CSCA=<number> [,<type>]
+                    if(ptr != NULL)
+				    {
+				    	ptr++;
+                        memset(csca, 0, sizeof(csca));
+				        memcpy(csca, ptr, strlen(ptr));
+						printf("csca:%s\n", csca);
+				    }
+
+                    err = mbtk_sms_csca_set(info_handle, csca);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE set success\n");
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "csmp", 4)){ // AT+CSMP=[<fo>[,<vp>[,<pid>[,<dcs>]]]]
+                                                    //
+                char csmp[128] = {0};
+                if(!strcasecmp(cmd, "csmp")) { // Get
+                    printf("cmgl : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, ",");  //  AT+CSMP=[<fo>[,<vp>[,<pid>[,<dcs>]]]]
+                    if(ptr != NULL)
+				    {
+				    	ptr++;
+                        memset(csmp, 0, sizeof(csmp));
+				        memcpy(csmp, ptr, strlen(ptr));
+						printf("csmp:%s\n", csmp);
+				    }
+
+                    err = mbtk_sms_csmp_set(info_handle, csmp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE set success\n");
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "cscb", 4)){ // AT+CSCB=<[<mode>[,<mids>[,<dcss>]]]>
+                                                    //
+                char cscb[128] = {0};
+                if(!strcasecmp(cmd, "cscb")) { // Get
+                    printf("cmgl : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, ",");  //  AT+CSCB=<[<mode>[,<mids>[,<dcss>]]]>
+                    if(ptr != NULL)
+				    {
+				    	ptr++;
+                        memset(cscb, 0, sizeof(cscb));
+				        memcpy(cscb, ptr, strlen(ptr));
+						printf("cscb:%s\n", cscb);
+				    }
+
+                    err = mbtk_sms_cscb_set(info_handle, cscb);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE set success\n");
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "ims_en", 6)){ // ims_en 0/1
+                char enable[10] = {0};
+                if(1 == sscanf(cmd, "ims_en %s", enable)) {
+                    err = mbtk_net_ims_set(info_handle, atoi(enable) ? 1 : 0);
+                    if(err) {
+                        printf("Set IMS fail : %d\n", err);
+                    } else {
+                        printf("Set IMS success\n");
+                    }
+                } else {
+                    printf("ARG error\n");
+                }
+            }
+            else if(!strncasecmp(cmd, "ims_state", 9)){ // ims_state
+                int enable = 0;
+                err = mbtk_net_ims_get(info_handle, &enable);
+                if(err) {
+                    printf("Get IMS state fail : %d\n", err);
+                } else {
+                    printf("IMS state : %d\n", enable);
+                }
+            }
+            else if(!strncasecmp(cmd, "ims_reg", 7)){ // ims_reg
+                int reg = 0;
+                err = mbtk_net_ims_reg_state_get(info_handle, &reg);
+                if(err) {
+                    printf("Get IMS register state fail : %d\n", err);
+                } else {
+                    printf("IMS register state : %d\n", reg);
+                }
+            }
+#endif
+            else if(!strcasecmp(cmd, "h") || !strcasecmp(cmd, "help")) {
+                help();
+            } else if(!strcasecmp(cmd, "q")) {
+                mbtk_ril_deinit();
+                break;
+            } else {
+                printf("\n");
+            }
+        }
+    }
+
+    thread_exit_with_wait();
+
+exit:
+    mbtk_ril_deinit();
+
+    LOG("Client exec complete.");
+
+    return 0;
+}