Add ril v2 support.

Change-Id: I14f4d5f3650f0d397c38a72e8bea2600c17b07de
diff --git a/mbtk/include/mbtk/mbtk_ril_api.h b/mbtk/include/mbtk/mbtk_ril_api.h
index 4cb916a..2ffe0f9 100755
--- a/mbtk/include/mbtk/mbtk_ril_api.h
+++ b/mbtk/include/mbtk/mbtk_ril_api.h
@@ -27,6 +27,9 @@
 #define APN_NAME_STR_MAX (64+1)
 #endif
 #define RIL_PIN_STR_MAX 16
+#define RIL_DATA_CALL_RETRY_MAX 20
+#define RIL_MAX_NUMBER_LEN 40
+#define MBTK_ECALL_MSD_LEN_MAX      600
 
 typedef void (*mbtk_ril_callback_func)(const void* data, int data_len);
 
@@ -105,7 +108,8 @@
     MBTK_RADIO_TECH_UTRAN_HSUPA,
     MBTK_RADIO_TECH_UTRAN_HSDPA_HSUPA,
     MBTK_RADIO_TECH_E_UTRAN,      // LTE
-    MBTK_RADIO_TECH_UTRAN_HSPA
+    MBTK_RADIO_TECH_UTRAN_HSPA,
+    MBTK_RADIO_TECH_UNKNOWN = 0xFF
 } mbtk_radio_technology_enum;
 
 typedef enum {
@@ -495,7 +499,7 @@
     uint8 auto_boot_call;       // Will reset proc if necessary.
     uint8 def_route;            // Will reset proc if necessary.
     uint8 as_dns;               // Will reset proc if necessary.
-    uint16 retry_interval;      // second
+    uint16 retry_interval[RIL_DATA_CALL_RETRY_MAX];      // second
     uint16 timeout;             // second
 } mbtk_data_call_info_t;
 
@@ -526,6 +530,234 @@
     mbtk_cell_info_array_t cell_list;
 } mbtk_cell_pack_info_t;
 
+typedef struct
+{
+    uint16 cid;
+    uint16 action;
+    uint16 reason;
+    uint16 auto_change;
+} mbtk_ril_pdp_state_info_t;
+
+typedef enum {
+    MBTK_NET_REG_TYPE_CALL,             // +CREG
+    MBTK_NET_REG_TYPE_DATA_GSM_WCDMA,   // +CGREG
+    MBTK_NET_REG_TYPE_DATA_LTE,         // +CEREG
+    MBTK_NET_REG_TYPE_IMS
+} mbtk_net_reg_type_enum;
+
+typedef enum {
+    MBTK_RIL_SER_STATE_READY,
+    MBTK_RIL_SER_STATE_EXIT         // ril server has exit,should reset ril API.
+} mbtk_ril_ser_state_enum;
+
+typedef struct
+{
+    mbtk_net_reg_type_enum type : 8;
+    mbtk_radio_technology_enum tech : 8;
+    mbtk_net_reg_state_enum reg_state : 8;
+} mbtk_ril_net_reg_state_info_t;
+
+typedef struct
+{
+    mbtk_sim_card_type_enum sim_type : 8;
+    mbtk_sim_state_enum sim_state : 8;
+} mbtk_ril_sim_state_info_t;
+
+typedef struct
+{
+    mbtk_radio_state_enum radio_state : 8;
+} mbtk_ril_radio_state_info_t;
+
+typedef struct
+{
+    mbtk_signal_info_t signal_state;
+} mbtk_ril_signal_state_info_t;
+
+typedef struct
+{
+    uint8 urc_id;
+    uint8 urc_data[5];
+} mbtk_ril_ecall_state_info_t;
+
+typedef struct
+{
+
+} mbtk_ril_sms_state_info_t;
+
+typedef enum
+{
+    MBTK_RIL_CALL_DIR_MO = 0,
+    MBTK_RIL_CALL_DIR_MT
+} mbtk_ril_call_dir_enum;
+
+typedef enum
+{
+    MBTK_RIL_CALL_STATE_ACTIVE = 0,
+    MBTK_RIL_CALL_STATE_HELD,
+    MBTK_RIL_CALL_STATE_DIALING,
+    MBTK_RIL_CALL_STATE_ALERTING,
+    MBTK_RIL_CALL_STATE_INCOMING,
+    MBTK_RIL_CALL_STATE_WAITING,
+    MBTK_RIL_CALL_STATE_OFFERING,
+    MBTK_RIL_CALL_STATE_DISCONNECT
+} mbtk_ril_call_state_enum;
+
+typedef enum
+{
+    MBTK_RIL_CALL_NUM_TYPE_129 = 129,
+    MBTK_RIL_CALL_NUM_TYPE_145 = 145
+} mbtk_ril_call_num_type_enum;
+
+
+typedef struct
+{
+    uint8 call_id;
+    mbtk_ril_call_dir_enum dir : 8;
+    mbtk_ril_call_state_enum state : 8;
+    mbtk_ril_call_num_type_enum num_type : 8;
+
+    uint8 call_number[100];
+} mbtk_ril_call_state_info_t;
+
+typedef enum {
+    MBTK_ECALL_MSD_VERSION_2 = 2,
+    MBTK_ECALL_MSD_VERSION_3 = 3
+} mbtk_ecall_msd_version_enum;
+
+typedef enum {
+    MBTK_ECALL_MSD_VEHICLE_TYPE_M1 = 1,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_M2,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_M3,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_N1,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_N2,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_N3,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_L1E,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_L2E,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_L3E,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_L4E,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_L5E,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_L6E,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_L7E,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_O,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_R,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_S,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_T,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_G,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_SA,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_SB,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_SC,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_SD,
+    MBTK_ECALL_MSD_VEHICLE_TYPE_OTHER
+} mbtk_ecall_msd_vehicle_type_enum;
+
+
+typedef enum {
+    MBTK_ECALL_MSD_ITEM_VERSION = 0,
+    MBTK_ECALL_MSD_ITEM_MSG_ID,
+    MBTK_ECALL_MSD_ITEM_CONTROLTYPE,
+    MBTK_ECALL_MSD_ITEM_VIN,
+    MBTK_ECALL_MSD_ITEM_STORAGETYPE,
+    MBTK_ECALL_MSD_ITEM_TIMESTAMP,
+    MBTK_ECALL_MSD_ITEM_LOCATION,
+    MBTK_ECALL_MSD_ITEM_DIRECTION,
+    MBTK_ECALL_MSD_ITEM_LOCATIONN1,
+    MBTK_ECALL_MSD_ITEM_LOCATIONN2,
+    MBTK_ECALL_MSD_ITEM_NUMBEROFOCCUPANTS,
+    MBTK_ECALL_MSD_ITEM_ADDITIONALDATA,
+    MBTK_ECALL_MSD_ITEM_ALL_IN_ONE,
+    MBTK_ECALL_MSD_ITEM_ASI,
+    MBTK_ECALL_MSD_ITEM_VEHICLE_DIAGNOSTIC,
+    MBTK_ECALL_MSD_ITEM_CRASH_INFO,
+    MBTK_ECALL_MSD_ITEM_GNSS_TYPE
+} mbtk_ecall_msd_item_enum;
+
+typedef struct
+{
+    mbtk_ecall_msd_item_enum item_type;
+
+    uint8 data[64];
+} mbtk_ecall_msd_cfg_info_t;
+
+typedef struct
+{
+    uint8 msd[MBTK_ECALL_MSD_LEN_MAX];
+} mbtk_ecall_msd_info_t;
+
+typedef enum {
+    MBTK_ECALL_ONLY_TYPE_DISABLE = 0,
+    MBTK_ECALL_ONLY_TYPE_ENABLE_ECALL,
+    MBTK_ECALL_ONLY_TYPE_ENABLE_NG_ECALL,
+    MBTK_ECALL_ONLY_TYPE_ENABLE_ALL,
+    MBTK_ECALL_ONLY_TYPE_CONF_NUM,
+    MBTK_ECALL_ONLY_TYPE_NORMAL
+} mbtk_ecall_only_type_enum;
+
+typedef enum {
+    MBTK_ECALL_SIM_TYPE_NO_SUPPORT = 0,
+    MBTK_ECALL_SIM_TYPE_SUPPORT_ECALL,
+    MBTK_ECALL_SIM_TYPE_SUPPORT_ECALL_ONLY
+} mbtk_ecall_sim_type_enum;
+
+typedef struct {
+    mbtk_ecall_only_type_enum active : 8;
+    mbtk_ecall_sim_type_enum sim_type : 8;     // Only for GET.
+    uint8 test_num[RIL_MAX_NUMBER_LEN];
+    uint8 reconfig_num[RIL_MAX_NUMBER_LEN];
+} mbtk_ecall_only_info_t;
+
+typedef enum {
+    MBTK_ECALL_DIAL_TYPE_TEST = 0,
+    MBTK_ECALL_DIAL_TYPE_RECONFIG,
+    MBTK_ECALL_DIAL_TYPE_MANUALLY,
+    MBTK_ECALL_DIAL_TYPE_AUTO,
+    MBTK_ECALL_DIAL_TYPE_NOT_ACTIVATED,
+    MBTK_ECALL_DIAL_TYPE_RELEASE
+} mbtk_ecall_dial_type_enum;
+
+typedef enum {
+    MBTK_ECALL_MODE_TYPE_EU = 0,
+    MBTK_ECALL_MODE_TYPE_ERA
+} mbtk_ecall_mode_type_enum;
+
+typedef enum {
+    MBTK_ECALL_CFG_ITEM_T3 = 0,         // ms
+    MBTK_ECALL_CFG_ITEM_T5,             // ms
+    MBTK_ECALL_CFG_ITEM_T6,             // ms
+    MBTK_ECALL_CFG_ITEM_T7,             // ms
+    MBTK_ECALL_CFG_ITEM_TH,             // ms
+    MBTK_ECALL_CFG_ITEM_TIMER_CALLBACK,     // T9       // 5
+    MBTK_ECALL_CFG_ITEM_TIMER_CLEARDOWN,     // T2
+    MBTK_ECALL_CFG_ITEM_TIMER_DEREG,    // T10
+    MBTK_ECALL_CFG_ITEM_TIMER_DIAL,     // "dial"
+    MBTK_ECALL_CFG_ITEM_TIMER_REDIAL,   // "redialtmr"
+    MBTK_ECALL_CFG_ITEM_TIMER_SMS,      // "sms"        // 10
+    MBTK_ECALL_CFG_ITEM_REDIALCNT,      // "redialcnt"
+    MBTK_ECALL_CFG_ITEM_SMSPROCESS,     // "smsprocess"
+    MBTK_ECALL_CFG_ITEM_SMSMSDCNT,       // "smsmsdcnt"
+
+    MBTK_ECALL_CFG_ITEM_MAX
+} mbtk_ecall_cfg_item_enum;
+
+typedef struct {
+    mbtk_ecall_cfg_item_enum type;
+
+    uint32 data;
+} mbtk_ecall_cfg_info_t;
+
+typedef enum {
+    MBTK_ECALL_GAIN_MODE_TX = 0,
+    MBTK_ECALL_GAIN_MODE_RX,
+    MBTK_ECALL_GAIN_MODE_SIDETONE
+} mbtk_ecall_gain_mode_enum;
+
+typedef struct {
+    mbtk_ecall_gain_mode_enum mode;
+
+    int8 gain;
+} mbtk_ecall_gain_info_t;
+
+////////////////////////////////////////////////////
+
 mbtk_ril_err_enum mbtk_ril_init();
 
 mbtk_ril_err_enum mbtk_ril_deinit();
@@ -692,7 +924,8 @@
 * Start data call.
 */
 mbtk_ril_err_enum mbtk_data_call_start(mbtk_ril_cid_enum cid, bool auto_boot_call,
-            bool def_route, bool as_dns, int retry_interval, int timeout, mbtk_ip_info_t *rsp_info);
+            bool def_route, bool as_dns, int *retry_interval, int retry_interval_num,
+            int timeout, mbtk_ip_info_t *rsp_info);
 
 /*
 * Stop data call.
@@ -945,38 +1178,123 @@
 mbtk_ril_err_enum mbtk_mute_state_set(int mute_state);
 
 /*
-* System power.
-* type:
-* 0: Reboot system.
-* 1: Poweroff system.
-* 2: Halt system.
+* Set msd item.
+*
 */
-int mbtk_system_reboot(int type);
+mbtk_ril_err_enum mbtk_ecall_msd_item_set(const mbtk_ecall_msd_cfg_info_t *msd_cfg);
 
 /*
-* Get time type.
+* Generate msd after msd item set.
+*
 */
-int mbtk_time_get(int *time_type);
+mbtk_ril_err_enum mbtk_ecall_msd_gen();
 
 /*
-* Get net time.
+* Set ecall msd.
+*
 */
-int mbtk_net_time_get(char* time_str);
+mbtk_ril_err_enum mbtk_ecall_msd_set(const void* msd);
 
 /*
-* Absolute time conversion
+* Get ecall msd.
+*
 */
-int mbtk_get_abs_time(char *time_str, time_t *time_out);
+mbtk_ril_err_enum mbtk_ecall_msd_get(void* msd);
+
 
 /*
-* Set pdp state change callback function.
+* Set ecall msd item.
+*
 */
-int mbtk_pdp_state_change_cb_reg(mbtk_ril_callback_func cb);
+mbtk_ril_err_enum mbtk_ecall_push();
 
 /*
-* Set network state change callback function.
+* Set ecall only configs.
+*
 */
-int mbtk_net_state_change_cb_reg(mbtk_ril_callback_func cb);
+mbtk_ril_err_enum mbtk_ecall_only_set(const mbtk_ecall_only_info_t* info);
+
+/*
+* Get ecall only configs.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_only_get(mbtk_ecall_only_info_t* info);
+
+/*
+* Set ecall network reg.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_reg_set(int reg);
+
+/*
+* Start ecall dial start.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_dial_start(mbtk_ecall_dial_type_enum type);
+
+/*
+* Get ecall dial state.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_dial_state_get(mbtk_ecall_dial_type_enum* type);
+
+/*
+* Set ecall mode.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_mode_set(mbtk_ecall_mode_type_enum mode);
+
+/*
+* Get ecall mode.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_mode_get(mbtk_ecall_mode_type_enum *mode);
+
+/*
+* Set ecall configs.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_cfg_set(const mbtk_ecall_cfg_info_t *cfg);
+
+/*
+* Get ecall configs.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_cfg_get(mbtk_ecall_cfg_info_t* cfg);
+
+/*
+* Set ecall sms number.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_sms_number_set(const void *number);
+
+/*
+* Get ecall sms number.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_sms_number_get(void *number);
+
+/*
+* Set ecall mute speaker.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_mute_spk_set(int mute);
+
+/*
+* Set ecall dsp gain.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_dsp_gain_set(const mbtk_ecall_gain_info_t *gain_info);
+
+/*
+* Set ril server ready callback function.
+*/
+int mbtk_ril_ser_state_change_cb_reg(mbtk_ril_callback_func cb);
+
+/*
+* Set net reg state change callback function.
+*/
+int mbtk_net_reg_state_change_cb_reg(mbtk_ril_callback_func cb);
 
 /*
 * Set call state change callback function.
@@ -999,10 +1317,21 @@
 int mbtk_sim_state_change_cb_reg(mbtk_ril_callback_func cb);
 
 /*
+* Set pdp state change callback function.
+*/
+int mbtk_pdp_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);
 
+/*
+* Set ecall state change callback function.
+*/
+int mbtk_ecall_state_change_cb_reg(mbtk_ril_callback_func cb);
+
+
 
 #endif /* _MBTK_INFO_API_2_H */
 
diff --git a/mbtk/libmbtk_lib_v2/Makefile b/mbtk/libmbtk_lib_v2/Makefile
index 295f873..2883152 100755
--- a/mbtk/libmbtk_lib_v2/Makefile
+++ b/mbtk/libmbtk_lib_v2/Makefile
@@ -16,11 +16,12 @@
 	-I$(LOCAL_PATH)/mqtt/MQTTPacket \
 	-I$(LOCAL_PATH)/net \
 	-I$(LOCAL_PATH)/tcpip \
-	-I$(LOCAL_PATH)/ril
+	-I$(LOCAL_PATH)/ril \
+	-I$(LOCAL_PATH)/wifi
 
 LIB_DIR +=
 
-LIBS += -llog -lubus -lubox -luci -lprop2uci -lrilutil -lblobmsg_json -ldl -lcutils -laudio-apu  -lssl -lcrypto
+LIBS += -llog -lubus -lubox -luci -lprop2uci -lrilutil -lblobmsg_json -ldl -lcutils -laudio-apu  -lssl -lcrypto -lwpa_client
 
 ifeq ($(BUILD_LIB_TYPE), shared)
 CFLAGS += -shared -Wl,-shared,-Bsymbolic
@@ -64,6 +65,7 @@
 	common/mbtk_device_info.c \
 	common/mbtk_version.c \
 	common/mbtk_gpio.c \
+	common/mbtk_adc.c \
 	common/mbtk_debug.c
 
 # audio
@@ -134,6 +136,11 @@
 # tcpip
 LOCAL_SRC_FILES += \
     tcpip/mbtk_tcpip_at.c
+    
+#wifi
+LOCAL_SRC_FILES += \
+    wifi/sta_cli.c \
+	wifi/sta_ctrl.c 
 
 
 OBJS = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(LOCAL_SRC_FILES)))
diff --git a/mbtk/libmbtk_lib_v2/common/mbtk_adc.c b/mbtk/libmbtk_lib_v2/common/mbtk_adc.c
new file mode 100755
index 0000000..55cce7c
--- /dev/null
+++ b/mbtk/libmbtk_lib_v2/common/mbtk_adc.c
@@ -0,0 +1,102 @@
+/**
+ *   \file mbtk_adc.c
+ *   \brief A Documented file.
+ *
+ *  Detailed description
+ *   \Author:  js.wang <js.wang@mobiletek.cn>
+ *   \Version: 1.0.0
+ *   \Date: 2022-04-22
+ */
+#include <fcntl.h>
+#include <stdint.h>
+#include <limits.h>
+#include <termios.h>
+#include <stdarg.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/types.h>
+#include "mbtk_log.h"
+#include "mbtk_type.h"
+#include "mbtk_adc.h"
+
+int mbtk_adc_close(const char* adc_dev)
+{
+    int ret = 0;
+    int fd = 0;
+    char adc = '3';
+    //system("echo 3 > /sys/kernel/debug/adc");
+    if(adc_dev != NULL && !access(adc_dev, R_OK))
+    {
+        //LOGI("DEV:%s", ADC_DEVICE_803);
+        fd = open(adc_dev, O_RDWR|O_CREAT|O_TRUNC, 0644);
+    }
+    else
+    {
+        LOGE("No found ADC devices.");
+        return -1;
+    }
+
+    if(fd < 0) {
+        LOGE("[%s]  file open error\n", __FUNCTION__);
+        return -2;
+    }
+    ret = write(fd, &adc, 1);
+    if (ret < 0) {
+        LOGE("%s: error writing to file!\n", __FUNCTION__);
+        close(fd);
+        return -2;
+    }
+    close(fd);
+    return 0;
+}
+
+int mbtk_adc_get(const char* adc_dev, mbtk_adc_enum channle)
+{
+    int ret = 0;
+    int fd = 0;
+    char adc_buf[24] = {0};
+    char *adc_value = NULL;
+    char adc =(channle == MBTK_ADC0 ? '0' : (channle == MBTK_ADC1 ? '1' : '2'));
+
+
+    if(adc_dev != NULL && !access(adc_dev, R_OK))
+    {
+        LOGI("[adc] DEV:%s", adc_dev);
+        fd = open(adc_dev, O_RDWR|O_CREAT|O_TRUNC, 0644);
+    }
+    else
+    {
+        LOGE("No found ADC devices : %s", adc_dev ? adc_dev : "NULL");
+        return -1;
+    }
+
+    if(fd < 0) {
+        LOGE("[%s]  file open error\n", __FUNCTION__);
+        return -2;
+    }
+    ret = write(fd, &adc, 1);
+    if (ret < 0) {
+        LOGE("%s: error writing to file!\n", __FUNCTION__);
+        close(fd);
+        return -2;
+    }
+    ret = read(fd, adc_buf, 24);
+    if (ret < 0) {
+        LOGE("%s: error writing to file!\n", __FUNCTION__);
+        close(fd);
+        return -2;
+    }else{
+        //LOGI("%s %d adc:%s\n", __FUNCTION__, __LINE__, adc_buf);
+        adc_value = strstr(adc_buf, "channel");
+    }
+    close(fd);
+    if(adc_value)
+    {
+        //LOGI("%s adc: %s\n", __FUNCTION__, adc_value);
+    }
+    else
+        return -2;
+
+    return atoi(&adc_value[9]);
+}
diff --git a/mbtk/libmbtk_lib_v2/common/mbtk_gpio.c b/mbtk/libmbtk_lib_v2/common/mbtk_gpio.c
index 0116f60..d80b014 100755
--- a/mbtk/libmbtk_lib_v2/common/mbtk_gpio.c
+++ b/mbtk/libmbtk_lib_v2/common/mbtk_gpio.c
@@ -12,7 +12,7 @@
 #include "mbtk_gpio.h"
 
 
-static int gpio_export(int gpio)
+int gpio_export(int gpio)
 {
     int fd = -1;
     char buffer[50];
@@ -44,7 +44,7 @@
     return 0;
 }
 
-static int gpio_unexport(int gpio)
+int gpio_unexport(int gpio)
 {
     int fd = -1;
     char buffer[50];
diff --git a/mbtk/libmbtk_lib_v2/ril/mbtk_ril.h b/mbtk/libmbtk_lib_v2/ril/mbtk_ril.h
index 04b5623..b8b21b5 100755
--- a/mbtk/libmbtk_lib_v2/ril/mbtk_ril.h
+++ b/mbtk/libmbtk_lib_v2/ril/mbtk_ril.h
@@ -13,6 +13,10 @@
 #define RIL_SOCK_NAME "/tmp/mbtk_ril_sock"
 #define RIL_SOCK_MSG_LEN_MAX (1024 * 6)
 
+#define IND_REGISTER_MAX 20
+#define PACK_PROCESS_QUEUE_MAX 20
+
+
 // 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)
@@ -31,7 +35,7 @@
 typedef enum
 {
     // Device Information
-    RIL_MSG_ID_DEV_BEGIN = 0,
+    RIL_MSG_ID_DEV_BEGIN = 0x0,
     // <string> IMEI
     RIL_MSG_ID_DEV_IMEI,
     // <string> SN
@@ -54,7 +58,7 @@
     RIL_MSG_ID_DEV_END,
 
     // Sim Information
-    RIL_MSG_ID_SIM_BEGIN = 1000,
+    RIL_MSG_ID_SIM_BEGIN = 0x100,
     // <uint8> 0:NOT_EXIST 1:READY ...
     RIL_MSG_ID_SIM_STATE,
     // <uint8> 0: SIM 1: USIM 2: TEST SIM 3: TEST USIM 4: UNKNOWN
@@ -75,7 +79,7 @@
     RIL_MSG_ID_SIM_END,
 
     // Network Information
-    RIL_MSG_ID_NET_BEGIN = 2000,
+    RIL_MSG_ID_NET_BEGIN = 0x200,
     // sel_mode(uint8)type(uint8)plmn(uint32)...sel_mode(uint8)type(uint8)plmn(uint32)
     RIL_MSG_ID_NET_AVAILABLE,
     // <uint8> 0: automatic 1: manual
@@ -90,8 +94,14 @@
     RIL_MSG_ID_NET_REG,
     // mbtk_cell_info_t[]
     RIL_MSG_ID_NET_CELL,
+
+    RIL_MSG_ID_NET_END,
+
+
+    // Network Information
+    RIL_MSG_ID_DATA_CALL_BEGIN = 0x300,
     // mbtk_apn_info_t
-    RIL_MSG_ID_NET_APN,
+    RIL_MSG_ID_DATA_CALL_APN,
     // REQ:
     // <call_type[1]><cid[1]><timeout[1]>
     //  call_type : mbtk_data_call_type_enum
@@ -102,13 +112,13 @@
     //  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_DATA_CALL_OPT,
 
-    RIL_MSG_ID_NET_END,
+    RIL_MSG_ID_DATA_CALL_END,
 
 
     // Call Information
-    RIL_MSG_ID_CALL_BEGIN = 3000,
+    RIL_MSG_ID_CALL_BEGIN = 0x400,
     RIL_MSG_ID_CALL_STATE,
 
     // Start call.
@@ -132,7 +142,7 @@
     RIL_MSG_ID_CALL_END,
 
     // SMS Information
-    RIL_MSG_ID_SMS_BEGIN = 4000,
+    RIL_MSG_ID_SMS_BEGIN = 0x500,
     RIL_MSG_ID_SMS_STATE,
     RIL_MSG_ID_SMS_CMGF,
     RIL_MSG_ID_SMS_CPMS,
@@ -150,33 +160,71 @@
     RIL_MSG_ID_SMS_END,
 
     // PhoneBook Information
-    RIL_MSG_ID_PB_BEGIN = 5000,
+    RIL_MSG_ID_PB_BEGIN = 0x600,
     RIL_MSG_ID_PB_STATE,
 
     RIL_MSG_ID_PB_END,
 
-    // IND Information
-    RIL_MSG_ID_IND_BEGIN = 10000,
+    // Ecall Information
+    RIL_MSG_ID_ECALL_BEGIN = 0x700,
+    // mbtk_ecall_msd_cfg_info_t
+    RIL_MSG_ID_ECALL_MSDCFG,
     // NULL
-    RIL_MSG_ID_IND_SER_READY,
-    // <uint8>  State
-    RIL_MSG_ID_IND_NET_STATE_CHANGE,
+    RIL_MSG_ID_ECALL_MSDGEN,
+    // uint8[]
+    RIL_MSG_ID_ECALL_MSD,
+    // NULL
+    RIL_MSG_ID_ECALL_PUSH,
+    // mbtk_ecall_only_info_t
+    RIL_MSG_ID_ECALL_ONLY,
+    // reg <uint8>
+    RIL_MSG_ID_ECALL_REG,
+    // mbtk_ecall_dial_type_enum
+    RIL_MSG_ID_ECALL_DIAL,
+    // mbtk_ecall_mode_type_enum
+    RIL_MSG_ID_ECALL_MODE,
+    // mbtk_ecall_cfg_item_enum / mbtk_ecall_cfg_info_t
+    RIL_MSG_ID_ECALL_CFG,
+    // uint8[]
+    RIL_MSG_ID_ECALL_SMS_NUM,
+    // uint8
+    RIL_MSG_ID_ECALL_MUTESPK,
+    // mbtk_ecall_gain_info_t
+    RIL_MSG_ID_ECALL_DSP_GAIN,
+
+    RIL_MSG_ID_ECALL_END,
+
+    // IND Information
+    RIL_MSG_ID_IND_BEGIN = 0x1000,
+    // mbtk_ril_ser_state_enum
+    RIL_MSG_ID_IND_SER_STATE_CHANGE,
+    // mbtk_ril_net_reg_state_info_t
+    RIL_MSG_ID_IND_NET_REG_STATE_CHANGE,
     // <uint8>  State
     RIL_MSG_ID_IND_CALL_STATE_CHANGE,
     // <uint8>  State
     RIL_MSG_ID_IND_SMS_STATE_CHANGE,
-    // <uint8>  State
+    // mbtk_ril_radio_state_info_t
     RIL_MSG_ID_IND_RADIO_STATE_CHANGE,
-    // <uint8>  State
+    // mbtk_ril_sim_state_info_t
     RIL_MSG_ID_IND_SIM_STATE_CHANGE,
-    // <uint8>  State
+    // mbtk_ril_pdp_state_info_t
     RIL_MSG_ID_IND_PDP_STATE_CHANGE,
-    // <uint8> State
+    // mbtk_ril_signal_state_info_t
     RIL_MSG_ID_IND_SIGNAL_STATE_CHANGE,
+    // mbtk_ril_ecall_state_info_t
+    RIL_MSG_ID_IND_ECALL_STATE_CHANGE,
 
 
     RIL_MSG_ID_IND_END,
-    RIL_MSG_ID_UNKNOWN        // Unknown information.
+
+    // URC message
+    RIL_URC_MSG_BEGIN = 0x2000,
+    RIL_URC_MSG_GET_SIM_STATE,     //check sim status
+    RIL_URC_MSG_NET_STATE_LOG,      // Save Network state into file.
+    RIL_URC_MSG_END,
+
+    RIL_MSG_ID_UNKNOWN = 0xFFFF        // Unknown information.
 } ril_msg_id_enum;
 
 typedef struct {
diff --git a/mbtk/libmbtk_lib_v2/ril/mbtk_ril_api.c b/mbtk/libmbtk_lib_v2/ril/mbtk_ril_api.c
index 93efd84..b6b61ca 100755
--- a/mbtk/libmbtk_lib_v2/ril/mbtk_ril_api.c
+++ b/mbtk/libmbtk_lib_v2/ril/mbtk_ril_api.c
@@ -21,6 +21,7 @@
     int cli_fd;
     bool ril_ready;
     int exit_fd[2];
+    mbtk_ril_callback_func cb[IND_REGISTER_MAX];
     pthread_t read_thread_id;
     pthread_mutex_t send_mutex;
     list_node_t* msg_list;           // ril_msg_info_t
@@ -110,13 +111,24 @@
 
 static int ril_ind_process(ril_msg_pack_info_t* pack)
 {
+    LOGD("IND - %d", id2str(pack->msg_id));
+    if(pack->msg_id > RIL_MSG_ID_IND_BEGIN && pack->msg_id < RIL_MSG_ID_IND_END) {
+        if(ril_cli.cb[pack->msg_id - RIL_MSG_ID_IND_BEGIN - 1])
+            ril_cli.cb[pack->msg_id - RIL_MSG_ID_IND_BEGIN - 1](pack->data, pack->data_len);
+    }
+
     switch(pack->msg_id) {
-        case RIL_MSG_ID_IND_SER_READY: // rild service ready.
+        case RIL_MSG_ID_IND_SER_STATE_CHANGE: // rild service ready.
         {
-            ril_cli.ril_ready = TRUE;
+            if(pack->data && pack->data_len > 0) {
+                mbtk_ril_ser_state_enum state = (mbtk_ril_ser_state_enum)pack->data[0];
+                if(state == MBTK_RIL_SER_STATE_READY) {
+                    ril_cli.ril_ready = TRUE;
+                }
+            }
             return 0;
         }
-        case RIL_MSG_ID_IND_NET_STATE_CHANGE:
+        case RIL_MSG_ID_IND_NET_REG_STATE_CHANGE:
         {
             return 0;
         }
@@ -255,6 +267,10 @@
                 if(epoll_events[i].events & EPOLLHUP)   // Closed by server.
                 {
                     LOGD("Closed by server.");
+                    if(ril_cli.cb[RIL_MSG_ID_IND_SER_STATE_CHANGE - RIL_MSG_ID_IND_BEGIN - 1]) {
+                        mbtk_ril_ser_state_enum state = MBTK_RIL_SER_STATE_EXIT;
+                        ril_cli.cb[RIL_MSG_ID_IND_SER_STATE_CHANGE - RIL_MSG_ID_IND_BEGIN - 1](&state, 1);
+                    }
                     goto read_thread_exit;
                 }
                 else if(epoll_events[i].events & EPOLLIN)
@@ -1256,7 +1272,7 @@
         return MBTK_RIL_ERR_PARAMETER;
     }
 
-    return ril_req_process(RIL_MSG_ID_NET_APN, NULL, 0, apns, FALSE);
+    return ril_req_process(RIL_MSG_ID_DATA_CALL_APN, NULL, 0, apns, FALSE);
 }
 
 
@@ -1286,14 +1302,15 @@
         }
     }
 
-    return ril_req_process(RIL_MSG_ID_NET_APN, apn, sizeof(mbtk_apn_info_t), NULL, FALSE);
+    return ril_req_process(RIL_MSG_ID_DATA_CALL_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, bool as_dns, int retry_interval, int timeout, mbtk_ip_info_t *rsp_info)
+            bool def_route, bool as_dns, int *retry_interval, int retry_interval_num,
+            int timeout, mbtk_ip_info_t *rsp_info)
 {
     if(!ril_cli.ril_ready)
     {
@@ -1311,12 +1328,18 @@
     info.auto_boot_call = (uint8)auto_boot_call;
     info.def_route = (uint8)def_route;
     info.as_dns = (uint8)as_dns;
-    info.retry_interval = (uint16)retry_interval;
+    int i = 0;
+    while(i < retry_interval_num && i < RIL_DATA_CALL_RETRY_MAX) {
+        info.retry_interval[i] = (uint16)retry_interval[i];
+        i++;
+    }
     if(timeout > 0) {
         info.timeout = (uint16)timeout;
+    } else {
+        info.timeout = (uint16)10;
     }
 
-    return ril_req_process(RIL_MSG_ID_NET_DATA_CALL, &info, sizeof(mbtk_data_call_info_t), rsp_info, FALSE);
+    return ril_req_process(RIL_MSG_ID_DATA_CALL_OPT, &info, sizeof(mbtk_data_call_info_t), rsp_info, FALSE);
 }
 
 /*
@@ -1340,7 +1363,7 @@
     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);
+    return ril_req_process(RIL_MSG_ID_DATA_CALL_OPT, &info, sizeof(mbtk_data_call_info_t), NULL, FALSE);
 }
 
 /*
@@ -1368,7 +1391,7 @@
     info.type = MBTK_DATA_CALL_STATE;
     info.cid = cid;
 
-    return ril_req_process(RIL_MSG_ID_NET_DATA_CALL, &info, sizeof(mbtk_data_call_info_t), ip, FALSE);
+    return ril_req_process(RIL_MSG_ID_DATA_CALL_OPT, &info, sizeof(mbtk_data_call_info_t), ip, FALSE);
 }
 
 /*
@@ -2108,6 +2131,344 @@
     return ril_req_process(RIL_MSG_ID_CALL_DTMF, dtmf_character, sizeof(mbtk_call_dtmf_info_t), NULL, FALSE);
 }
 
+/*
+* Set msd item.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_msd_item_set(const mbtk_ecall_msd_cfg_info_t *msd_cfg)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(msd_cfg == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_MSDCFG, msd_cfg, sizeof(mbtk_ecall_msd_cfg_info_t), NULL, FALSE);
+}
+
+/*
+* Generate msd after msd item set.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_msd_gen()
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_MSDGEN, NULL, 0, NULL, FALSE);
+}
+
+/*
+* Set ecall msd.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_msd_set(const void* msd)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(str_empty(msd))
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_MSD, msd, strlen(msd), NULL, FALSE);
+}
+
+/*
+* Get ecall msd.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_msd_get(void* msd)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(msd == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_MSD, NULL, 0, msd, FALSE);
+}
+
+
+/*
+* Set ecall msd item.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_push()
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_PUSH, NULL, 0, NULL, FALSE);
+}
+
+/*
+* Set ecall only configs.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_only_set(const mbtk_ecall_only_info_t* info)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(info == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_ONLY, info, sizeof(mbtk_ecall_only_info_t), NULL, FALSE);
+}
+
+/*
+* Get ecall only configs.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_only_get(mbtk_ecall_only_info_t* info)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(info == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_ONLY, NULL, 0, info, FALSE);
+}
+
+/*
+* Set ecall network reg.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_reg_set(int reg)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(reg != 0 && reg != 1)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+    return ril_req_process(RIL_MSG_ID_ECALL_REG, &reg, 1, NULL, FALSE);
+}
+
+/*
+* Start ecall dial start.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_dial_start(mbtk_ecall_dial_type_enum type)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_DIAL, &type, 1, NULL, FALSE);
+}
+
+/*
+* Get ecall dial state.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_dial_state_get(mbtk_ecall_dial_type_enum* type)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(type == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+    memset(type, 0, sizeof(mbtk_ecall_dial_type_enum));
+
+    return ril_req_process(RIL_MSG_ID_ECALL_DIAL, NULL, 0, type, FALSE);
+}
+
+/*
+* Set ecall mode.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_mode_set(mbtk_ecall_mode_type_enum mode)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_MODE, &mode, 1, NULL, FALSE);
+}
+
+/*
+* Get ecall mode.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_mode_get(mbtk_ecall_mode_type_enum *mode)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(mode == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+    memset(mode, 0, sizeof(mbtk_ecall_mode_type_enum));
+
+    return ril_req_process(RIL_MSG_ID_ECALL_MODE, NULL, 0, mode, FALSE);
+}
+
+/*
+* Set ecall configs.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_cfg_set(const mbtk_ecall_cfg_info_t *cfg)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(cfg == NULL || cfg->type >= MBTK_ECALL_CFG_ITEM_MAX)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_CFG, cfg, sizeof(mbtk_ecall_cfg_info_t), NULL, FALSE);
+}
+
+/*
+* Get ecall configs.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_cfg_get(mbtk_ecall_cfg_info_t* cfg)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(cfg == NULL || cfg->type >= MBTK_ECALL_CFG_ITEM_MAX)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+    mbtk_ecall_cfg_item_enum type = cfg->type;
+
+    return ril_req_process(RIL_MSG_ID_ECALL_CFG, &type, 1, cfg, FALSE);
+}
+
+/*
+* Set ecall sms number.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_sms_number_set(const void *number)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(str_empty(number))
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_SMS_NUM, number, strlen(number), NULL, FALSE);
+}
+
+/*
+* Get ecall sms number.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_sms_number_get(void *number)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(number == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_SMS_NUM, NULL, 0, number, FALSE);
+}
+
+/*
+* Set ecall mute speaker.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_mute_spk_set(int mute)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(mute != 0 && mute != 1)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_MUTESPK, &mute, 1, NULL, FALSE);
+}
+
+/*
+* Set ecall dsp gain.
+*
+*/
+mbtk_ril_err_enum mbtk_ecall_dsp_gain_set(const mbtk_ecall_gain_info_t *gain_info)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    if(gain_info == NULL)
+    {
+        LOGE("ARG error.");
+        return MBTK_RIL_ERR_PARAMETER;
+    }
+
+    return ril_req_process(RIL_MSG_ID_ECALL_DSP_GAIN, gain_info, sizeof(mbtk_ecall_gain_info_t), NULL, FALSE);
+}
 
 #if 0
 /*
@@ -2156,151 +2517,163 @@
 
 #endif
 
-#if 0
 /*
-* Set pdp state change callback function.
+* Set ril server state change callback function.
 */
-int mbtk_pdp_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+int mbtk_ril_ser_state_change_cb_reg(mbtk_ril_callback_func cb)
 {
-    if(handle == NULL)
+    if(!ril_cli.ril_ready)
     {
-        LOGE("ARG error.");
-        return -1;
+        return MBTK_RIL_ERR_NOT_INIT;
     }
-    if(info_item_process(handle, MBTK_INFO_ID_IND_PDP_STATE_CHANGE, NULL, 0, NULL) < 0)
+
+    int ret = ril_req_process(RIL_MSG_ID_IND_SER_STATE_CHANGE, NULL, 0, NULL, FALSE);
+    if(MBTK_RIL_ERR_SUCCESS == ret)
     {
-        return handle->info_err;
+        ril_cli.cb[RIL_MSG_ID_IND_SER_STATE_CHANGE - RIL_MSG_ID_IND_BEGIN - 1] = cb;
     }
-    else
-    {
-        handle->pdp_state_cb = cb;
-        return 0;
-    }
+    return ret;
 }
 
 /*
-* Set network state change callback function.
+* Set net reg state change callback function.
 */
-int mbtk_net_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+int mbtk_net_reg_state_change_cb_reg(mbtk_ril_callback_func cb)
 {
-    if(handle == NULL)
+    if(!ril_cli.ril_ready)
     {
-        LOGE("ARG error.");
-        return -1;
+        return MBTK_RIL_ERR_NOT_INIT;
     }
-    if(info_item_process(handle, MBTK_INFO_ID_IND_NET_STATE_CHANGE, NULL, 0, NULL) < 0)
+
+    int ret = ril_req_process(RIL_MSG_ID_IND_NET_REG_STATE_CHANGE, NULL, 0, NULL, FALSE);
+    if(MBTK_RIL_ERR_SUCCESS == ret)
     {
-        return handle->info_err;
+        ril_cli.cb[RIL_MSG_ID_IND_NET_REG_STATE_CHANGE - RIL_MSG_ID_IND_BEGIN - 1] = cb;
     }
-    else
-    {
-        handle->net_state_cb = cb;
-        return 0;
-    }
+    return ret;
 }
 
 /*
 * Set call state change callback function.
 */
-int mbtk_call_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+int mbtk_call_state_change_cb_reg(mbtk_ril_callback_func cb)
 {
-    if(handle == NULL)
+    if(!ril_cli.ril_ready)
     {
-        LOGE("ARG error.");
-        return -1;
+        return MBTK_RIL_ERR_NOT_INIT;
     }
-    if(info_item_process(handle, MBTK_INFO_ID_IND_CALL_STATE_CHANGE, NULL, 0, NULL) < 0)
+
+    int ret = ril_req_process(RIL_MSG_ID_IND_CALL_STATE_CHANGE, NULL, 0, NULL, FALSE);
+    if(MBTK_RIL_ERR_SUCCESS == ret)
     {
-        return handle->info_err;
+        ril_cli.cb[RIL_MSG_ID_IND_CALL_STATE_CHANGE - RIL_MSG_ID_IND_BEGIN - 1] = cb;
     }
-    else
-    {
-        handle->call_state_cb = cb;
-        return 0;
-    }
+    return ret;
 }
 
 /*
 * Set sms state change callback function.
 */
-int mbtk_sms_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+int mbtk_sms_state_change_cb_reg(mbtk_ril_callback_func cb)
 {
-    if(handle == NULL)
+    if(!ril_cli.ril_ready)
     {
-        LOGE("ARG error.");
-        return -1;
+        return MBTK_RIL_ERR_NOT_INIT;
     }
-    if(info_item_process(handle, MBTK_INFO_ID_IND_SMS_STATE_CHANGE, NULL, 0, NULL) < 0)
+
+    int ret = ril_req_process(RIL_MSG_ID_IND_SMS_STATE_CHANGE, NULL, 0, NULL, FALSE);
+    if(MBTK_RIL_ERR_SUCCESS == ret)
     {
-        return handle->info_err;
+        ril_cli.cb[RIL_MSG_ID_IND_SMS_STATE_CHANGE - RIL_MSG_ID_IND_BEGIN - 1] = cb;
     }
-    else
-    {
-        handle->sms_state_cb = cb;
-        return 0;
-    }
+    return ret;
 }
 
 /*
 * Set radio state change callback function.
 */
-int mbtk_radio_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+int mbtk_radio_state_change_cb_reg(mbtk_ril_callback_func cb)
 {
-    if(handle == NULL)
+    if(!ril_cli.ril_ready)
     {
-        LOGE("ARG error.");
-        return -1;
+        return MBTK_RIL_ERR_NOT_INIT;
     }
-    if(info_item_process(handle, MBTK_INFO_ID_IND_RADIO_STATE_CHANGE, NULL, 0, NULL) < 0)
+
+    int ret = ril_req_process(RIL_MSG_ID_IND_RADIO_STATE_CHANGE, NULL, 0, NULL, FALSE);
+    if(MBTK_RIL_ERR_SUCCESS == ret)
     {
-        return handle->info_err;
+        ril_cli.cb[RIL_MSG_ID_IND_RADIO_STATE_CHANGE - RIL_MSG_ID_IND_BEGIN - 1] = cb;
     }
-    else
-    {
-        handle->radio_state_cb = cb;
-        return 0;
-    }
+    return ret;
 }
 
 /*
 * Set sim state change callback function.
 */
-int mbtk_sim_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+int mbtk_sim_state_change_cb_reg(mbtk_ril_callback_func cb)
 {
-    if(handle == NULL)
+    if(!ril_cli.ril_ready)
     {
-        LOGE("ARG error.");
-        return -1;
+        return MBTK_RIL_ERR_NOT_INIT;
     }
-    if(info_item_process(handle, MBTK_INFO_ID_IND_SIM_STATE_CHANGE, NULL, 0, NULL) < 0)
+
+    int ret = ril_req_process(RIL_MSG_ID_IND_SIM_STATE_CHANGE, NULL, 0, NULL, FALSE);
+    if(MBTK_RIL_ERR_SUCCESS == ret)
     {
-        return handle->info_err;
+        ril_cli.cb[RIL_MSG_ID_IND_SIM_STATE_CHANGE - RIL_MSG_ID_IND_BEGIN - 1] = cb;
     }
-    else
+    return ret;
+}
+
+/*
+* Set pdp state change callback function.
+*/
+int mbtk_pdp_state_change_cb_reg(mbtk_ril_callback_func cb)
+{
+    if(!ril_cli.ril_ready)
     {
-        handle->sim_state_cb = cb;
-        return 0;
+        return MBTK_RIL_ERR_NOT_INIT;
     }
+
+    int ret = ril_req_process(RIL_MSG_ID_IND_PDP_STATE_CHANGE, NULL, 0, NULL, FALSE);
+    if(MBTK_RIL_ERR_SUCCESS == ret)
+    {
+        ril_cli.cb[RIL_MSG_ID_IND_PDP_STATE_CHANGE - RIL_MSG_ID_IND_BEGIN - 1] = cb;
+    }
+    return ret;
 }
 
 /*
 * Set signal state change callback function.
 */
-int mbtk_signal_state_change_cb_reg(mbtk_info_handle_t* handle, mbtk_info_callback_func cb)
+int mbtk_signal_state_change_cb_reg(mbtk_ril_callback_func cb)
 {
-    if(handle == NULL)
+    if(!ril_cli.ril_ready)
     {
-        LOGE("ARG error.");
-        return -1;
+        return MBTK_RIL_ERR_NOT_INIT;
     }
-    if(info_item_process(handle, MBTK_INFO_ID_IND_SIGNAL_STATE_CHANGE, NULL, 0, NULL) < 0)
+
+    int ret = ril_req_process(RIL_MSG_ID_IND_SIGNAL_STATE_CHANGE, NULL, 0, NULL, FALSE);
+    if(MBTK_RIL_ERR_SUCCESS == ret)
     {
-        return handle->info_err;
+        ril_cli.cb[RIL_MSG_ID_IND_SIGNAL_STATE_CHANGE - RIL_MSG_ID_IND_BEGIN - 1] = cb;
     }
-    else
-    {
-        handle->signal_state_cb = cb;
-        return 0;
-    }
+    return ret;
 }
-#endif
+
+int mbtk_ecall_state_change_cb_reg(mbtk_ril_callback_func cb)
+{
+    if(!ril_cli.ril_ready)
+    {
+        return MBTK_RIL_ERR_NOT_INIT;
+    }
+
+    int ret = ril_req_process(RIL_MSG_ID_IND_ECALL_STATE_CHANGE, NULL, 0, NULL, FALSE);
+    if(MBTK_RIL_ERR_SUCCESS == ret)
+    {
+        ril_cli.cb[RIL_MSG_ID_IND_ECALL_STATE_CHANGE - RIL_MSG_ID_IND_BEGIN - 1] = cb;
+    }
+    return ret;
+}
+
+
diff --git a/mbtk/libmbtk_lib_v2/ril/ril_utils.c b/mbtk/libmbtk_lib_v2/ril/ril_utils.c
index f71b2dd..371275d 100755
--- a/mbtk/libmbtk_lib_v2/ril/ril_utils.c
+++ b/mbtk/libmbtk_lib_v2/ril/ril_utils.c
@@ -258,12 +258,12 @@
         case RIL_MSG_ID_NET_REG:
             return "NET_REG";
         // <string> cmnet/ctnet/3gnet/...
-        case RIL_MSG_ID_NET_APN:
+        case RIL_MSG_ID_DATA_CALL_APN:
             return "APN";
         // Lock net/cell/frequency
         case RIL_MSG_ID_NET_CELL:
             return "NET_CELL";
-        case RIL_MSG_ID_NET_DATA_CALL:
+        case RIL_MSG_ID_DATA_CALL_OPT:
             return "DATA_CALL";
         // Call Information
         case RIL_MSG_ID_CALL_STATE:
@@ -279,8 +279,8 @@
         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";
+        case RIL_MSG_ID_IND_NET_REG_STATE_CHANGE:
+            return "IND_NET_REG_STATE";
         // <uint8>  State
         case RIL_MSG_ID_IND_CALL_STATE_CHANGE:
             return "IND_CALL_STATE";
diff --git a/mbtk/libmbtk_lib_v2/wifi/sta_cli.c b/mbtk/libmbtk_lib_v2/wifi/sta_cli.c
new file mode 100755
index 0000000..316d70f
--- /dev/null
+++ b/mbtk/libmbtk_lib_v2/wifi/sta_cli.c
@@ -0,0 +1,2008 @@
+#include <stdio.h>

+#include <pthread.h>

+#include <time.h>

+#include <sys/time.h>

+#include <unistd.h>

+#include <sys/un.h>

+#include <poll.h>

+#include <sys/socket.h>

+#include <netinet/in.h>

+#include <arpa/inet.h>

+#include <errno.h>

+#include <sys/ioctl.h>

+#include <net/if.h>

+#include <string.h>

+

+

+#include "sta_cli.h"

+#include "sta_ctrl.h"

+//#include "sta_log.h"

+//#include "mbtk_string.h"

+

+#define STA_CLI_TIMEOUT 15000   // 15s

+#define UNIXSTR_PATH "/data/sta_cli_sock"

+#define	SA	struct sockaddr

+#define	LISTENQ		1024	/* 2nd argument to listen() */

+#define STA_CMD_SEPARATED "#$#"

+#define STA_MAC_LEN 17	  // xx:xx:xx:xx:xx:xx

+#define STA_SSID_MAX_LEN (32 * 5)

+

+

+#ifndef INFTIM

+#define INFTIM          (-1)    /* infinite poll timeout */

+#endif

+

+#define STA_TAG_IND "IND"

+#define STA_TAG_CMD "CMD"

+#define STA_TAG_CMD_SUCCESS "SUCCESS"

+#define STA_TAG_CMD_FAIL "FAIL"

+#define STA_TAG_CMD_FAIL_BUSY "FAIL-BUSY"

+#define STA_CMD_OPEN "OPEN"

+//#define STA_CMD_EXIT "EXIT"

+#define STA_CMD_CLOSE "CLOSE"

+#define STA_CMD_SCAN "SCAN"

+#define STA_CMD_STATUS "STATUS"

+#define STA_CMD_MIB "MIB"

+#define STA_CMD_RECONFIGURE "RECONFIGURE"

+#define STA_CMD_DISCONNECT "DISCONNECT"

+#define STA_CMD_RECONNECT "RECONNECT"

+#define STA_CMD_SAVE_CONFIG "SAVE_CONFIG"

+#define STA_CMD_SET_NETWORK "SET_NETWORK"

+#define STA_CMD_GET_NETWORK "GET_NETWORK"

+#define STA_CMD_REMOVE_NETWORK "REMOVE_NETWORK"

+#define STA_CMD_ADD_NETWORK "ADD_NETWORK"

+#define STA_CMD_DISABLE_NETWORK "DISABLE_NETWORK"

+#define STA_CMD_ENABLE_NETWORK "ENABLE_NETWORK"

+#define STA_CMD_SELECT_NETWORK "SELECT_NETWORK"

+#define STA_CMD_LIST_NETWORKS "LIST_NETWORKS"

+#define STA_CMD_REASSOCIATE "REASSOCIATE"

+#define STA_CMD_REATTACH "REATTACH"

+

+// /var/run/wpa_supplicant

+static sta_cli_cmd_id_enum sta_cli_cmd_id = CMD_ID_NON;

+static char sta_cli_cmd_reply[STA_BUF_SIZE];

+static pthread_cond_t cond;

+static pthread_mutex_t mutex;

+static int sta_cli_conn_fd = -1;

+static char sta_cli_buf[STA_BUF_SIZE];

+static bool sta_should_send_connected_msg = TRUE;

+//static bool sta_connected = FALSE;

+static bool sta_disconnectting = FALSE;

+//static pthread_mutex_t sta_mutex;

+

+

+

+int sta_cli_ssid_get(char *ssid)

+{

+    FILE *fd_tmp = NULL;

+

+    fd_tmp = popen("cat /etc/wifi/sta_network.conf | grep -w 'SSID'   | cut -d '=' -f 2","r");

+  

+    if(fd_tmp){

+        char buf[200] = {0};

+        fgets(ssid,200,fd_tmp); 

+        pclose(fd_tmp);

+        if(strlen(ssid) > 0){

+           printf("test 100:%s, len:%d\n", ssid, strlen(ssid));

+            

+        }else{// Open wpa_supplicant

+            printf("test 101:%s\n", ssid);

+        }

+    }else{

+       

+            printf("test 102:%s\n");

+    }

+

+    return 0;

+}

+

+int sta_cli_psk_get(char *psk)

+{

+    FILE *fd_tmp = NULL;

+

+    fd_tmp = popen("cat /etc/wifi/sta_network.conf | grep -w 'PASSWORD'   | cut -d '=' -f 2","r");

+  

+    if(fd_tmp){

+        char buf[200] = {0};

+        fgets(psk,200,fd_tmp);

+        pclose(fd_tmp);

+        if(strlen(psk) > 0){

+           printf("test 100:%s\n", psk);

+            

+        }else{// Open wpa_supplicant

+            printf("test 101:%s\n", psk);

+        }

+    }else{

+       

+            printf("test 102:%s\n");

+    }

+

+    return 0;

+}

+

+

+

+static char*

+sta_cli_ssid_process

+(

+	const char *ssid,

+	char *result,

+	int len

+)

+{

+    bzero(result,len);

+    int ascii = 1;

+    int i;

+    for (i = 0; i < strlen(ssid); i++){

+        if (!isascii(ssid[i])){

+            //printf("0x%02x\n",(unsigned char)ssid[i]);

+            //return 0;

+            ascii = 0;

+            break;

+        }

+    }

+

+    if(ascii)

+    {

+        snprintf(result,len,

+                "\"%s\"",ssid);

+    }else{

+		int pos = 0;

+        for (i = 0; i < strlen(ssid); i++){

+            printf("0x%02x\n",(unsigned char)ssid[i]);

+        	snprintf(result + pos,len - pos,

+                "%02x",(unsigned char)ssid[i]);

+			pos += 2;

+        }

+    }

+    return result;

+}

+

+

+static char*

+sta_cli_mac_get

+(

+	char *ifname,

+	char *mac,

+	size_t mac_len

+)

+{

+    struct   ifreq   ifreq;

+    int   sock;

+	bzero(mac,mac_len);

+

+    if((sock=socket(AF_INET,SOCK_STREAM,0))<0)

+    {

+        printf("socket:errno(%d)\n",errno);

+        return NULL;

+    }

+    strcpy(ifreq.ifr_name,ifname);

+    if(ioctl(sock,SIOCGIFHWADDR,&ifreq) <0)

+    {

+		printf("ioctl:errno(%d)\n",errno);

+        return NULL;

+    }

+    snprintf(mac,mac_len,

+    	"%02x%02x%02x%02x%02x%02x",

+        (unsigned char)ifreq.ifr_hwaddr.sa_data[0],

+        (unsigned char)ifreq.ifr_hwaddr.sa_data[1],

+        (unsigned char)ifreq.ifr_hwaddr.sa_data[2],

+        (unsigned char)ifreq.ifr_hwaddr.sa_data[3],

+        (unsigned char)ifreq.ifr_hwaddr.sa_data[4],

+        (unsigned char)ifreq.ifr_hwaddr.sa_data[5]);

+	return mac;

+}

+

+

+static char*

+sta_cli_sta_name_get

+(

+	char *name,

+	size_t name_len

+)

+{

+	bzero(name,name_len);

+

+	// Get host name.

+    FILE *stream = NULL;

+	char host[100];

+	bzero(host,100);

+    stream = popen("hostname","r");

+    if(stream != NULL)

+    {

+		fgets(host, 100, stream);

+		pclose(stream);

+		int index = str_indexof(host,"\n");

+		if(strlen(host) > 0

+			&& index != 0)

+		{

+			if(index > 0)

+			{

+				host[index] = '\0';

+			}

+

+			// index < 0

+			// No "\n"

+		}

+		else // No data or empty line.

+		{

+			// Can not get host,set default to "MBTK".

+			memcpy(host,"MBTK",4);

+		}

+    }

+	else

+	{

+		// Can not get host,set default to "MBTK".

+		memcpy(host,"MBTK",4);

+	}

+

+	// Get mac address.

+	char mac[20];

+	if(NULL == sta_cli_mac_get("wlan0", mac, 20))

+	{

+		// Can not get mac,set default to current time.

+		time_t t;

+		t = time(NULL);

+		snprintf(mac,20,

+			"%ld",t);

+	}

+

+	snprintf(name,name_len,

+		"%s-%s",host,mac);

+

+	return name;

+}

+

+static void

+sta_cli_wpa_open_success

+(

+	void

+)

+{

+    char buf[100];

+    int len = snprintf(buf,100,

+        "%s-%s-%s"STA_CMD_SEPARATED,

+        STA_TAG_CMD,

+        STA_CMD_OPEN,

+        STA_TAG_CMD_SUCCESS);

+    buf[len] = '\0';

+    if(sta_cli_conn_fd != -1){

+        if(write(sta_cli_conn_fd,buf,len) != len){

+            printf("Send open msg to client fail.\n");

+        }else{

+            printf("Send open msg to client success.\n");

+        }

+    }else{

+        printf("No client connected.\n");

+    }

+	sta_should_send_connected_msg = FALSE;

+}

+

+

+static void

+sta_cli_wpa_msg_cb

+(

+    char *msg

+)

+{

+    printf("cmd_id = %d,[%s]\n",sta_cli_cmd_id,msg);

+

+//    if(sta_cli_conn_fd != -1){

+//        if(write(sta_cli_conn_fd,msg,strlen(msg)) != strlen(msg)){

+//            printf("Send msg to client fail.\n");

+//        }else{

+//            printf("Send msg to client success.\n");

+//        }

+//    }else{

+//        printf("No client connected.\n");

+//    }

+

+	// Send msg(CMD_OPEN_SUCCESS) to wifi_server.

+    if(sta_should_send_connected_msg) {

+		sta_cli_wpa_open_success();

+    }

+

+    // Connected to AP

+    if(str_contains(msg, "CTRL-EVENT-CONNECTED")){

+		//sta_connected = TRUE;

+		char sta_name[100];

+		sta_cli_sta_name_get(sta_name,100);

+		char cmd[200];

+		int size = snprintf(cmd,200,

+			"dhcpcd -h %s -o domain_name_servers --noipv4ll wlan0",sta_name);

+        //dhcpcd wlan0 -t 0 -o domain_name_servers --noipv4ll -b -G

+		cmd[size] = '\0';

+        if(sta_ctrl_system(cmd)){

+            char buf[100];

+            int len = snprintf(buf,100,

+                "%s-CONNECTED"STA_CMD_SEPARATED,

+                STA_TAG_IND);

+            buf[len] = '\0';

+            if(sta_cli_conn_fd != -1){

+				usleep(500);

+                if(write(sta_cli_conn_fd,buf,len) != len){

+                    printf("Send msg to client fail.\n");

+                }else{

+                    printf("Send msg to client success.\n");

+                }

+            }else{

+                printf("No client connected.\n");

+            }

+        }

+        return;

+    }

+#if 1

+	else if(str_contains(msg, "CTRL-EVENT-DISCONNECTED")

+		&& !str_contains(msg, "bssid=00:00:00:00:00:00")

+		&& !sta_disconnectting)

+	{

+		//pthread_mutex_lock(&sta_mutex);

+		//if(sta_connected){

+	        // Disconnected from AP

+	        char buf[100];

+	        int len = snprintf(buf,100,

+	            "%s-DISCONNECTED"STA_CMD_SEPARATED,

+	            STA_TAG_IND);

+	        buf[len] = '\0';

+	        if(sta_cli_conn_fd != -1){

+	            if(write(sta_cli_conn_fd,buf,len) != len){

+	                printf("Send msg to client fail.\n");

+	            }else{

+	                printf("Send msg to client success.\n");

+	            }

+	        }else{

+	            printf("No client connected.\n");

+	        }

+			//sta_connected = FALSE;

+			//pthread_mutex_unlock(&sta_mutex);

+	        return;

+		//}

+		//pthread_mutex_unlock(&sta_mutex);

+    }

+#endif

+

+    switch(sta_cli_cmd_id)

+    {

+        case CMD_ID_NON:

+        {

+

+            break;

+        }

+        case CMD_ID_SCAN:

+        {

+            if(str_contains(msg, "CTRL-EVENT-SCAN-RESULTS")){

+                printf("Start resume thread.\n");

+                pthread_mutex_lock(&mutex);

+                pthread_cond_signal(&cond);

+                //pthread_cond_broadcast(&cond);

+                pthread_mutex_unlock(&mutex);

+            }

+            break;

+        }

+        default:

+            printf("cmd_id[%d] unknown.\n",sta_cli_cmd_id);

+            break;

+    }

+}

+

+static void

+sta_cli_thread_pause

+(

+    long time /* ms */

+)

+{

+    struct timeval now_1;

+    struct timespec outtime;

+    int thread_id = pthread_self();

+    printf("Thread(%ld) pause.\n",thread_id);

+    pthread_mutex_lock(&mutex);

+    gettimeofday(&now_1, NULL);

+    outtime.tv_sec = now_1.tv_sec + time / 1000;

+    outtime.tv_nsec = now_1.tv_usec * 1000;

+    pthread_cond_timedwait(&cond, &mutex, &outtime);

+    pthread_mutex_unlock(&mutex);

+    printf("Thread(%ld) resume.\n",thread_id);

+}

+

+static bool

+sta_cli_is_empty_char(char ch)

+{

+    if(/*ch == ' ' || */ch == '\r' || ch == '\n'

+        || ch == '\t')

+        return TRUE;

+    else

+        return FALSE;

+}

+

+static char*

+sta_cli_value_get

+(

+	const char *data,

+	const char *key, // "key="

+	char *value,

+	int len

+)

+{

+	bzero(value,len);

+	char *ptr = strstr(data,key);

+	if(ptr)

+	{

+		ptr += strlen(key);

+		int i = 0;

+		while(*ptr != '\r' && *ptr != '\n')

+		{

+			if(i == len - 1)

+				return NULL;

+			value[i++] = *ptr++;

+		}

+		return value;

+	}else{

+		return NULL;

+	}

+}

+

+

+static sta_err_enum

+sta_cli_cmd_scan_parse

+(

+    const char *reply,

+    char *data,

+    size_t len

+)

+{

+	char *data_base = data;

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

+    bzero(data,len);

+    const char *ptr = reply;

+    bool start = FALSE;

+    int count = 0; // count for ',' by every line.

+    while(*ptr){

+        if(!start && *ptr == '\n'){

+            start = TRUE;

+            ptr++;

+        }

+

+        if(start){

+            if(sta_cli_is_empty_char(*ptr)){

+                if(*ptr == '\r' || *ptr == '\n'){

+                    *data++ = '\r';

+                    *data++ = '\n';

+                    while(*++ptr == '\r' || *ptr == '\n')

+                        ;

+                    count = 0; // reset for next line.

+                }else{

+                    if(count < 4) {

+                        *data++ = ',';

+                        count++;

+                        while(*++ptr == ' ' || *ptr == '\t')

+                            ;

+                    } else {

+                        *data++ = *ptr++;

+                    }

+                }

+            }else{

+                *data++ = *ptr++;

+            }

+        }else{

+            ptr++;

+        }

+    }

+

+    printf("SCAN 0:\n%s\n",data_base);

+

+	// Delete empty ssid line.

+	char *tmp = (char*)calloc(len,1);

+	memcpy(tmp,data_base,strlen(data_base));

+	bzero(data_base,len);

+

+	char *ptr_pre = tmp;

+	ptr = strstr(ptr_pre,"\r\n");

+	printf("line:%s\n",ptr == NULL?"NULL":ptr);

+	char ssid[STA_BUF_SIZE] = {0};

+	char *p;

+	while(ptr)

+	{

+		printf("Get line.\n");

+		// Get ssid.

+		if(*(ptr - 1) == ',') // No ssid

+		{

+			printf("Delete one line.\n");

+		}else{

+			char s[STA_BUF_SIZE] = {0};

+			p = ptr - 1;

+			int len = 0;

+			while(*p-- != ','){

+				len++;

+			}

+			p += 2;

+			memcpy(s,p,len);

+			printf("ssid = %s;s = %s\n",ssid,s);

+			if(str_contains(ssid,s))

+			{

+				printf("Jump the same ssid:%s\n",s);

+				ptr_pre = ptr + 2;

+				ptr = strstr(ptr_pre,"\r\n");

+				continue;

+			}

+

+			if(strlen(ssid) > 0){

+				ssid[strlen(ssid)] = ',';

+			}

+			memcpy(ssid + strlen(ssid),s,len);

+

+			memcpy(data_base + strlen(data_base),ptr_pre,ptr + 2 - ptr_pre);

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

+		}

+		ptr_pre = ptr + 2;

+		ptr = strstr(ptr_pre,"\r\n");

+	}

+

+	printf("Scan parse end.\n");

+

+	free(tmp);

+	tmp = NULL;

+

+	printf("SCAN 1:\n%s\n",data_base);

+

+    return STA_ERR_SUCCESS;

+}

+

+static sta_err_enum

+sta_cli_cmd_status_parse

+(

+    const char *reply,

+    char *data,

+    size_t data_len

+)

+{

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

+

+    bzero(data,data_len);

+

+//	  const char *ptr = reply;

+//    while(*ptr){

+//        if(*ptr == '\r' || *ptr == '\n'){

+//            *data++ = '\r';

+//            *data++ = '\n';

+//            while(*++ptr == '\r' || *ptr == '\n')

+//                ;

+//        }else{

+//            *data++ = *ptr++;

+//        }

+//    }

+

+#define BUF_SIZE 500

+	int len = 0;

+	char buf[BUF_SIZE];

+	char mac_ap[STA_MAC_LEN + 1];

+	int size;

+	if(sta_cli_value_get(reply,

+			"bssid=",

+			mac_ap,

+			STA_MAC_LEN + 1)) // Connected.

+	{

+		// State

+		memcpy(data + len,"1",1);

+		len += 1;

+

+		// mac_own

+		if(sta_cli_value_get(reply,

+			"\naddress=",

+			buf,

+			BUF_SIZE))

+		{

+			size = snprintf(data + len,data_len - len,

+				",%s",buf);

+			len += size;

+		}else{

+			memcpy(data + len,",",1);

+			len += 1;

+			printf("Not get own MAC address.\n");

+		}

+

+		// net_id

+		if(sta_cli_value_get(reply,

+			"\nid=",

+			buf,

+			BUF_SIZE))

+		{

+			size = snprintf(data + len,data_len - len,

+				",%s",buf);

+			len += size;

+		}else{

+			memcpy(data + len,",",1);

+			len += 1;

+			printf("Not get net id.\n");

+		}

+

+		// ssid

+		if(sta_cli_value_get(reply,

+			"\nssid=",

+			buf,

+			BUF_SIZE))

+		{

+			size = snprintf(data + len,data_len - len,

+				",%s",buf);

+			len += size;

+		}else{

+			memcpy(data + len,",",1);

+			len += 1;

+			printf("Not get ssid.\n");

+		}

+

+		// freq

+		if(sta_cli_value_get(reply,

+			"freq=",

+			buf,

+			BUF_SIZE))

+		{

+			int freq = atoi(buf);

+			int channel = (freq - 2412) / 5 + 1;

+			size = snprintf(data + len,data_len - len,

+				",%d,%s",channel,buf);

+			len += size;

+		}else{

+			memcpy(data + len,",",1);

+			len += 1;

+			printf("Not get freq.\n");

+		}

+

+		// auth

+		if(sta_cli_value_get(reply,

+			"key_mgmt=",

+			buf,

+			BUF_SIZE))

+		{

+			// WPA/WPA2

+			if(strncmp(buf,"WPA",3)== 0)

+			{

+				size = snprintf(data + len,data_len - len,

+					",%d",2);

+				len += size;

+			}else{

+				if(sta_cli_value_get(reply,

+					"group_cipher=",

+					buf,

+					BUF_SIZE))

+				{

+					// Open

+					if(strncmp(buf,"NONE",4) == 0)

+					{

+						size = snprintf(data + len,data_len - len,

+							",%d",0);

+						len += size;

+					}else{// WEP

+						size = snprintf(data + len,data_len - len,

+							",%d",1);

+						len += size;

+					}

+				}else{

+					memcpy(data + len,",",1);

+					len += 1;

+					printf("Not get group_cipher.\n");

+				}

+			}

+		}else{

+			memcpy(data + len,",",1);

+			len += 1;

+			printf("Not get key_mgmt.\n");

+		}

+

+		// mac_ap

+		size = snprintf(data + len,data_len - len,

+			",%s",mac_ap);

+		len += size;

+

+		// ip

+		if(sta_cli_value_get(reply,

+			"ip_address=",

+			buf,

+			BUF_SIZE))

+		{

+			size = snprintf(data + len,data_len - len,

+				",%s",buf);

+			len += size;

+		}else{

+			memcpy(data + len,",",1);

+			len += 1;

+			printf("Not get IP.\n");

+		}

+	}else{

+		memcpy(data + len,"0",1);

+		len += 1;

+

+		if(sta_cli_value_get(reply,

+			"\naddress=",

+			buf,

+			BUF_SIZE))

+		{

+			size = snprintf(data + len,data_len - len,

+				",%s",buf);

+			len += size;

+

+		}else{

+			memcpy(data + len,",",1);

+			len += 1;

+			printf("Not get MAC address.\n");

+		}

+

+		memcpy(data + len,",,,,,,,",7);

+		len += 7;

+	}

+

+	memcpy(data + len,"\r\n",2);

+	len += 2;

+	data[len] = '\0';

+

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

+#undef BUF_SIZE

+    return STA_ERR_SUCCESS;

+}

+

+static sta_err_enum

+sta_cli_cmd_mib_parse

+(

+    const char *reply,

+    char *data,

+    size_t len

+)

+{

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

+

+    memcpy(data,reply,strlen(reply));

+

+    return STA_ERR_SUCCESS;

+}

+

+static sta_err_enum

+sta_cli_cmd_list_network_parse

+(

+    const char *reply,

+    char *data,

+    size_t len

+)

+{

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

+

+    bzero(data,len);

+    const char *ptr = reply;

+    bool start = FALSE;

+    bool skip = FALSE;

+    int count = 0; // count for ',' by every line.

+    while(*ptr){

+        if(!start && *ptr == '\n'){

+            start = TRUE;

+            ptr++;

+        }

+

+        if(start){

+            if(sta_cli_is_empty_char(*ptr)){

+                if(*ptr == '\r' || *ptr == '\n'){

+                    *data++ = '\r';

+                    *data++ = '\n';

+                    while(*++ptr == '\r' || *ptr == '\n')

+                        ;

+                    count = 0;

+                    skip = FALSE;

+                }else{

+                    if(count < 1) {

+                        *data++ = ',';

+                        count++;

+                        while(*++ptr == ' ' || *ptr == '\t')

+                            ;

+                    } else {

+                        skip = TRUE;

+                        ptr++;

+                    }

+                }

+            }else{

+                if(!skip)

+                    *data++ = *ptr++;

+                else

+                    ptr++;

+            }

+        }else{

+            ptr++;

+        }

+    }

+

+    //memcpy(data,reply,strlen(reply));

+

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

+

+    return STA_ERR_SUCCESS;

+}

+

+static sta_err_enum

+sta_cli_process_cmd

+(

+    const char *cmd

+)

+{

+    sta_err_enum err = sta_ctrl_cmd_process(cmd,sta_cli_cmd_reply,STA_BUF_SIZE);

+    if(err == STA_ERR_SUCCESS){

+        if(strncmp(cmd,STA_CMD_SCAN,strlen(STA_CMD_SCAN)) == 0

+            && strncmp(sta_cli_cmd_reply,STA_TAG_CMD_FAIL_BUSY,strlen(STA_TAG_CMD_FAIL_BUSY)) == 0){

+            printf("\"%s\" busy.\n",cmd);

+            return STA_ERR_SUCCESS;

+        }

+

+        if(strncmp(sta_cli_cmd_reply,STA_TAG_CMD_FAIL,strlen(STA_TAG_CMD_FAIL)) == 0){

+            printf("\"%s\" fail.\n",cmd);

+            return STA_ERR_UNKNOWN;

+        }

+        printf("[%s]:\n%s\n",cmd,sta_cli_cmd_reply);

+    }else{

+        printf("[%s]:FAIL\n",cmd);

+    }

+    return err;

+}

+

+static sta_err_enum

+sta_cli_cmd_scan

+(

+    const char *cmd,

+    char *data,

+    size_t len

+)

+{

+    bzero(data,len);

+    sta_cli_cmd_id = CMD_ID_SCAN;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    if(STA_ERR_SUCCESS == err){

+        if(strncmp(sta_cli_cmd_reply,"OK",2) == 0

+            || strncmp(sta_cli_cmd_reply,STA_TAG_CMD_FAIL_BUSY,strlen(STA_TAG_CMD_FAIL_BUSY)) == 0){// Is scanning ...

+            sta_cli_thread_pause(STA_CLI_TIMEOUT);

+

+            // Scan end.

+

+            sta_cli_cmd_id = CMD_ID_SCAN_RESULTS;

+            err = sta_cli_process_cmd("SCAN_RESULTS");

+            sta_cli_cmd_id = CMD_ID_NON;

+            if(STA_ERR_SUCCESS == err){

+                return sta_cli_cmd_scan_parse(sta_cli_cmd_reply,

+                    data,

+                    len);

+            }else{

+                printf("SCAN_RESULTS cmd fail.\n");

+                return STA_ERR_UNKNOWN;

+            }

+        }else{

+            sta_cli_cmd_id = CMD_ID_NON;

+            printf("SCAN cmd fail.\n");

+            return STA_ERR_UNKNOWN;

+        }

+    }else{

+        sta_cli_cmd_id = CMD_ID_NON;

+        printf("SCAN cmd fail.\n");

+        return err;

+    }

+}

+

+

+static char*

+sta_cli_flag_get

+(

+	const char *ssid,

+	char *flag,

+	size_t len

+)

+{

+	sta_err_enum err;

+    char data[STA_BUF_SIZE];

+	bzero(flag,len);

+    err = sta_cli_cmd_scan("SCAN", data,STA_BUF_SIZE);

+    if(err == STA_ERR_SUCCESS){

+		if(strlen(data) == 0)

+		{

+			return NULL;

+		}

+		ssize_t end = str_indexof(data,ssid) - 1; // Point to ','

+		if(end > 0)

+		{

+			char *ptr = data + end - 1;// Jump the ','

+			int len = 0;

+			while(*ptr != ',' && ptr != data)

+			{

+				ptr--;

+				len++;

+			}

+			ptr++; // Point to flag.

+

+			memcpy(flag,ptr,len);

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

+			return flag;

+		}

+    }else{

+		printf("SCAN_RESULTS cmd fail.");

+		return NULL;

+    }

+    return NULL;

+}

+

+

+static sta_err_enum

+sta_cli_cmd_status

+(

+    const char *cmd,

+    char *data,

+    size_t len

+)

+{

+    bzero(data,len);

+    sta_cli_cmd_id = CMD_ID_STATUS;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    sta_cli_cmd_id = CMD_ID_NON;

+    if(STA_ERR_SUCCESS == err){

+        return sta_cli_cmd_status_parse(sta_cli_cmd_reply,

+            data,

+            len);

+    }else{

+        printf("STATUS cmd fail.\n");

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_cmd_mib

+(

+    const char *cmd,

+    char *data,

+    size_t len

+)

+{

+    bzero(data,len);

+    sta_cli_cmd_id = CMD_ID_MIB;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    sta_cli_cmd_id = CMD_ID_NON;

+    if(STA_ERR_SUCCESS == err){

+        return sta_cli_cmd_mib_parse(sta_cli_cmd_reply,

+            data,

+            len);

+    }else{

+        printf("MIB cmd fail.\n");

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_cmd_reconfigure

+(

+    const char *cmd

+)

+{

+    sta_cli_cmd_id = CMD_ID_RECONFIGURE;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    if(STA_ERR_SUCCESS == err){

+        sta_cli_cmd_id = CMD_ID_NON;

+        if(strncmp(sta_cli_cmd_reply,"OK",2) == 0){

+            return STA_ERR_SUCCESS;

+        }else{

+            printf("RECONFIGURE cmd fail.\n");

+            return STA_ERR_UNKNOWN;

+        }

+    }else{

+        sta_cli_cmd_id = CMD_ID_NON;

+        printf("RECONFIGURE cmd fail.\n");

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_cmd_disconnect

+(

+    const char *cmd

+)

+{

+    sta_cli_cmd_id = CMD_ID_DISCONNECT;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    if(STA_ERR_SUCCESS == err){

+        sta_cli_cmd_id = CMD_ID_NON;

+        if(strncmp(sta_cli_cmd_reply,"OK",2) == 0){

+            return STA_ERR_SUCCESS;

+        }else{

+            printf("DISCONNECT cmd fail.\n");

+            return STA_ERR_UNKNOWN;

+        }

+    }else{

+        sta_cli_cmd_id = CMD_ID_NON;

+        printf("DISCONNECT cmd fail.\n");

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_cmd_reconnect

+(

+    const char *cmd

+)

+{

+    sta_cli_cmd_id = CMD_ID_RECONNECT;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    if(STA_ERR_SUCCESS == err){

+        sta_cli_cmd_id = CMD_ID_NON;

+        if(strncmp(sta_cli_cmd_reply,"OK",2) == 0){

+            return STA_ERR_SUCCESS;

+        }else{

+            printf("RECONNECT cmd fail.\n");

+            return STA_ERR_UNKNOWN;

+        }

+    }else{

+        sta_cli_cmd_id = CMD_ID_NON;

+        printf("RECONNECT cmd fail.\n");

+        return err;

+    }

+}

+

+

+static sta_err_enum

+sta_cli_cmd_save_config

+(

+    const char *cmd

+)

+{

+    sta_cli_cmd_id = CMD_ID_SAVE_CONFIG;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    if(STA_ERR_SUCCESS == err){

+        sta_cli_cmd_id = CMD_ID_NON;

+        if(strncmp(sta_cli_cmd_reply,"OK",2) == 0){

+            return STA_ERR_SUCCESS;

+        }else{

+            printf("SAVE_CONFIG cmd fail.\n");

+            return STA_ERR_UNKNOWN;

+        }

+    }else{

+        sta_cli_cmd_id = CMD_ID_NON;

+        printf("SAVE_CONFIG cmd fail.\n");

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_cmd_set_network_process

+(

+	char *c

+)

+{

+	printf("cmd = %s\n",c);

+	char *ptr = c;

+

+    sta_cli_cmd_id = CMD_ID_SET_NETWORK;

+	sta_err_enum err = STA_ERR_SUCCESS;

+	char cmd[100];

+	int index = str_indexof(ptr,"#");

+	bzero(cmd,100);

+	if(index > 0)

+	{

+		memcpy(cmd,ptr,index);

+		ptr += (index + 1);

+	}else

+	{

+		memcpy(cmd,ptr,strlen(ptr));

+		ptr = NULL;

+	}

+

+	while(TRUE)

+	{

+	    err = sta_cli_process_cmd(c);

+	    if(STA_ERR_SUCCESS == err){

+	        if(strncmp(sta_cli_cmd_reply,"OK",2) == 0){

+	            //return STA_ERR_SUCCESS;

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

+	        }else{

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

+				sta_cli_cmd_id = CMD_ID_NON;

+	            return STA_ERR_UNKNOWN;

+	        }

+	    }else{

+	        sta_cli_cmd_id = CMD_ID_NON;

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

+	        return err;

+	    }

+

+		if(ptr == NULL)

+			break;

+

+		printf("ptr = %s",ptr);

+

+		index = str_indexof(ptr,"#");

+		bzero(cmd,100);

+		if(index > 0)

+		{

+			memcpy(cmd,ptr,index);

+			ptr += (index + 1);

+		}else

+		{

+			memcpy(cmd,ptr,strlen(ptr));

+			ptr = NULL;

+		}

+	}

+

+	sta_cli_cmd_id = CMD_ID_NON;

+	return STA_ERR_SUCCESS;

+}

+

+static sta_err_enum

+sta_cli_cmd_set_network

+(

+    const char *cmd,

+    const char *flag

+)

+{

+	printf("cmd = %s\n",cmd);

+	char buf[500];

+    printf("test11\n");

+	int index = str_indexof(cmd," psk ");

+    printf("test12\n");

+	int net_id = atoi(cmd + strlen(STA_CMD_SET_NETWORK) + 1);

+    printf("test13\n");

+	if(index > 0){ // Is set "psk"

+	    printf("test14\n");

+		char psk[64] = {0};

+		int start = index + 5; // " psk "

+		if(*(cmd + start) == '"')

+		{

+		    printf("test15\n");

+			memcpy(psk,cmd + start + 1,strlen(cmd) - start - 2);

+		}else{

+            printf("test16\n");

+			memcpy(psk,cmd + start,strlen(cmd) - start);

+		}

+		printf("psk = %s\n",psk);

+

+		// Set to OPEN (No psk)

+		// SET_NETWORK <net_id> key_mgmt NONE

+		if(strcmp(psk,"0") == 0)

+		{

+			int size = snprintf(buf,500,

+					"%s %d key_mgmt NONE",

+					STA_CMD_SET_NETWORK,

+					net_id);

+			buf[size] = '\0';

+			return sta_cli_cmd_set_network_process(buf);

+		}

+

+		// WEP

+		// key_mgmt=NONE

+		// auth_alg=OPEN SHARED

+		// wep_key0="0123456789abc"

+		if(flag && str_contains(flag, "WEP")

+			&&(strlen(psk) == 5

+				|| strlen(psk) == 13

+				|| strlen(psk) == 10

+				|| strlen(psk) == 26))

+		{

+			int size = 0;

+			if(strlen(psk) == 5

+				|| strlen(psk) == 13)

+			{

+				size = snprintf(buf,500,

+					"%s %d key_mgmt NONE#%s %d auth_alg SHARED#%s %d wep_key0 \"%s\"",

+					STA_CMD_SET_NETWORK,

+					net_id,

+					STA_CMD_SET_NETWORK,

+					net_id,

+					STA_CMD_SET_NETWORK,

+					net_id,

+					psk);

+			}else{

+				size = snprintf(buf,500,

+					"%s %d key_mgmt NONE#%s %d auth_alg SHARED#%s %d wep_key0 %s",

+					STA_CMD_SET_NETWORK,

+					net_id,

+					STA_CMD_SET_NETWORK,

+					net_id,

+					STA_CMD_SET_NETWORK,

+					net_id,

+					psk);

+			}

+

+			buf[size] = '\0';

+			return sta_cli_cmd_set_network_process(buf);

+		}

+

+		// Default is "WPA/WPA2"

+		int size = snprintf(buf,500,

+				"%s#%s %d key_mgmt WPA-PSK",

+				cmd,

+				STA_CMD_SET_NETWORK,

+				net_id);

+		buf[size] = '\0';

+		return sta_cli_cmd_set_network_process(buf);

+	}

+	else // SSID

+	{

+	    printf("test21\n");

+		index = str_indexof(cmd," ssid ");

+		char ssid[STA_BUF_SIZE] = {0};

+		int start = index + 6; // " ssid "

+		if(*(cmd + start) == '"')

+		{

+			memcpy(ssid,cmd + start + 1,strlen(cmd) - start - 2);

+		}else{

+			memcpy(ssid,cmd + start,strlen(cmd) - start);

+		}

+		printf("ssid = %s\n",ssid);

+

+

+		//char ssid_result[STA_SSID_MAX_LEN + 1];

+		//sta_cli_ssid_process(ssid,ssid_result,STA_SSID_MAX_LEN + 2 + 1);

+       // printf("test22, ssid_result: %s\n", ssid_result);

+		char cmd_result[STA_BUF_SIZE];

+		int size = snprintf(cmd_result,STA_BUF_SIZE,

+			"%s %d ssid %s",

+			STA_CMD_SET_NETWORK,

+			net_id,

+			ssid);

+		cmd_result[size] = '\0';

+		printf("cmd = %s\n",cmd_result);

+

+		return sta_cli_cmd_set_network_process(cmd);

+	}

+}

+

+

+static sta_err_enum

+sta_cli_cmd_get_network

+(

+    const char *cmd,

+    char *value,

+    int len

+)

+{

+    bzero(value,len);

+    sta_cli_cmd_id = CMD_ID_GET_NETWORK;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    if(STA_ERR_SUCCESS == err){

+        sta_cli_cmd_id = CMD_ID_NON;

+

+        char *tmp = sta_cli_cmd_reply;

+        while(*tmp == '\"'){

+            tmp++;

+        }

+        // Copy with '\0'

+        memcpy(value,tmp,strlen(tmp) + 1);

+

+        tmp = value + strlen(value) -1;

+        while(*tmp == '\"'){

+            tmp = '\0';

+            tmp--;

+        }

+

+        printf("GET_NETWORK:%s.\n",value);

+        return STA_ERR_SUCCESS;

+    }else{

+        sta_cli_cmd_id = CMD_ID_NON;

+        printf("GET_NETWORK cmd fail.\n");

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_cmd_remove_network

+(

+    const char *cmd

+)

+{

+    sta_cli_cmd_id = CMD_ID_REMOVE_NETWORK;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    if(STA_ERR_SUCCESS == err){

+        sta_cli_cmd_id = CMD_ID_NON;

+        if(strncmp(sta_cli_cmd_reply,"OK",2) == 0){

+            return STA_ERR_SUCCESS;

+        }else{

+            printf("REMOVE_NETWORK cmd fail.\n");

+            return STA_ERR_UNKNOWN;

+        }

+    }else{

+        sta_cli_cmd_id = CMD_ID_NON;

+        printf("REMOVE_NETWORK cmd fail.\n");

+        return err;

+    }

+}

+

+

+static sta_err_enum

+sta_cli_cmd_add_network

+(

+    const char *cmd

+)

+{

+	printf("cmd = %s\n",cmd);

+    sta_cli_cmd_id = CMD_ID_ADD_NETWORK;

+    sta_err_enum err = sta_cli_process_cmd(STA_CMD_ADD_NETWORK);

+    printf("test1\n");

+    if(STA_ERR_SUCCESS == err){

+        sta_cli_cmd_id = CMD_ID_NON;

+        int net_id = atoi(sta_cli_cmd_reply);

+        printf("test2\n");

+        if(net_id >= 0){ // Add network success.

+            // Point to ssid

+            printf("test3\n");

+            /*

+            const char *ptr = cmd + strlen(STA_CMD_ADD_NETWORK) + 1;

+

+            //int index = str_indexof(ptr," ");

+

+            char *pass_ptr = cmd + strlen(cmd);

+            while(*--pass_ptr != ' ')

+                ;

+            pass_ptr++; // Point to pass.

+

+

+            char ssid[STA_BUF_SIZE] = {0};

+            printf("test4\n");

+            memcpy(ssid,ptr,pass_ptr - ptr - 1);

+            */

+

+            char buf[STA_BUF_SIZE] = {'\0'};

+            char ssid[STA_BUF_SIZE] = {'\0'};

+            char psk[STA_BUF_SIZE] = {'\0'};

+            int len = 0;

+            printf("test5\n");

+

+            sta_cli_ssid_get(ssid);

+            len = strlen(ssid);

+            ssid[len - 1] = '\0';

+            

+            sta_cli_psk_get(psk);

+            len = strlen(psk);

+            psk[len - 1] = '\0';

+

+            

+            int size = snprintf(buf,STA_BUF_SIZE,

+                "%s %d ssid \"%s\"",

+                STA_CMD_SET_NETWORK,

+                net_id,

+                ssid);

+            printf("test6\n");

+            buf[size] = '\0';

+

+         

+            err = sta_cli_cmd_set_network(buf,NULL);

+            printf("test7\n");

+            if(STA_ERR_SUCCESS == err){

+				char flag[50];

+				sta_cli_flag_get(ssid,flag,50);

+                size = snprintf(buf,100,

+                        "%s %d psk \"%s\"",

+                        STA_CMD_SET_NETWORK,

+                        net_id,

+                        psk);

+                buf[size] = '\0';

+                err = sta_cli_cmd_set_network(buf,flag);

+                if(STA_ERR_SUCCESS == err){

+                    return STA_ERR_SUCCESS;

+                }

+            }

+

+			if(err != STA_ERR_SUCCESS) // remove network

+			{

+				int size = snprintf(buf,STA_BUF_SIZE,

+	                "%s %d",

+	                STA_CMD_REMOVE_NETWORK,

+	                net_id);

+	            buf[size] = '\0';

+				sta_cli_process_cmd(buf);

+			}

+

+            return err;

+        }else{

+            printf("ADD_NETWORK cmd fail.\n");

+            return STA_ERR_UNKNOWN;

+        }

+    }else{

+        printf("ADD_NETWORK cmd fail.\n");

+        sta_cli_cmd_id = CMD_ID_NON;

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_cmd_disable_network

+(

+    const char *cmd

+)

+{

+    sta_cli_cmd_id = CMD_ID_DISABLE_NETWORK;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    if(STA_ERR_SUCCESS == err){

+        sta_cli_cmd_id = CMD_ID_NON;

+        if(strncmp(sta_cli_cmd_reply,"OK",2) == 0){

+            return STA_ERR_SUCCESS;

+        }else{

+            printf("DISABLE_NETWORK cmd fail.\n");

+            return STA_ERR_UNKNOWN;

+        }

+    }else{

+        sta_cli_cmd_id = CMD_ID_NON;

+        printf("DISABLE_NETWORK cmd fail.\n");

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_cmd_enable_network

+(

+    const char *cmd

+)

+{

+    sta_cli_cmd_id = CMD_ID_ENABLE_NETWORK;

+    sta_err_enum err = sta_cli_process_cmd("ENABLE_NETWORK 1");

+    if(STA_ERR_SUCCESS == err){

+        sta_cli_cmd_id = CMD_ID_NON;

+        if(strncmp(sta_cli_cmd_reply,"OK",2) == 0){

+            return STA_ERR_SUCCESS;

+        }else{

+            printf("ENABLE_NETWORK cmd fail.\n");

+            return STA_ERR_UNKNOWN;

+        }

+    }else{

+        sta_cli_cmd_id = CMD_ID_NON;

+        printf("ENABLE_NETWORK cmd fail.\n");

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_cmd_select_network

+(

+    const char *cmd

+)

+{

+    sta_cli_cmd_id = CMD_ID_SELECT_NETWORK;

+    sta_err_enum err = sta_cli_process_cmd("SELECT_NETWORK 1");

+    if(STA_ERR_SUCCESS == err){

+        sta_cli_cmd_id = CMD_ID_NON;

+        if(strncmp(sta_cli_cmd_reply,"OK",2) == 0){

+            return STA_ERR_SUCCESS;

+        }else{

+            printf("SELECT_NETWORK cmd fail.\n");

+            return STA_ERR_UNKNOWN;

+        }

+    }else{

+        sta_cli_cmd_id = CMD_ID_NON;

+        printf("SELECT_NETWORK cmd fail.\n");

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_cmd_list_networks

+(

+    const char *cmd,

+    char *data,

+    size_t len

+)

+{

+    bzero(data,len);

+    sta_cli_cmd_id = CMD_ID_LIST_NETWORKS;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    sta_cli_cmd_id = CMD_ID_NON;

+    if(STA_ERR_SUCCESS == err){

+        return sta_cli_cmd_list_network_parse(sta_cli_cmd_reply,

+            data,

+            len);

+    }else{

+        printf("LIST_NETWORKS cmd fail.\n");

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_cmd_reassociate

+(

+    const char *cmd

+)

+{

+    sta_cli_cmd_id = CMD_ID_REASSOCIATE;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    if(STA_ERR_SUCCESS == err){

+        sta_cli_cmd_id = CMD_ID_NON;

+        if(strncmp(sta_cli_cmd_reply,"OK",2) == 0){

+            return STA_ERR_SUCCESS;

+        }else{

+            printf("REASSOCIATE cmd fail.\n");

+            return STA_ERR_UNKNOWN;

+        }

+    }else{

+        sta_cli_cmd_id = CMD_ID_NON;

+        printf("REASSOCIATE cmd fail.\n");

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_cmd_reattach

+(

+    const char *cmd

+)

+{

+    sta_cli_cmd_id = CMD_ID_REATTACH;

+    sta_err_enum err = sta_cli_process_cmd(cmd);

+    if(STA_ERR_SUCCESS == err){

+        sta_cli_cmd_id = CMD_ID_NON;

+        if(strncmp(sta_cli_cmd_reply,"OK",2) == 0){

+            return STA_ERR_SUCCESS;

+        }else{

+            printf("REATTACH cmd fail.\n");

+            return STA_ERR_UNKNOWN;

+        }

+    }else{

+        sta_cli_cmd_id = CMD_ID_NON;

+        printf("REATTACH cmd fail.\n");

+        return err;

+    }

+}

+

+static sta_err_enum

+sta_cli_init

+(

+    void

+)

+{

+    sta_err_enum result = STA_ERR_SUCCESS;

+    if((result = sta_ctrl_driver_init(TRUE)) != STA_ERR_SUCCESS){

+        printf("Driver init fail(%d).\n",result);

+        return result;

+    }

+

+    if((result = sta_ctrl_wpa_init(

+        "/etc/wifi/wpa_supplicant.conf",

+        "wlan0",

+        sta_cli_wpa_msg_cb)) != STA_ERR_SUCCESS){

+        printf("wpa_supplicant init fail(%d).\n",result);

+        return result;

+    }

+	//pthread_mutex_init(&sta_mutex,NULL);

+    return result;

+}

+

+static sta_err_enum

+sta_cli_deinit

+(

+    void

+)

+{

+    sta_err_enum result = STA_ERR_SUCCESS;

+    if((result = sta_ctrl_wpa_deinit()) != STA_ERR_SUCCESS){

+        printf("sta_ctrl_wpa_deinit fail(%d).",result);

+        return result;

+    }

+

+    if((result = sta_ctrl_driver_init(FALSE)) != STA_ERR_SUCCESS){

+        printf("Driver close fail(%d).\n",result);

+        return result;

+    }

+	//pthread_mutex_destroy(&sta_mutex);

+    return result;

+}

+

+/**

+* CMD-CLOSE-SUCCESS

+* CMD-CLOSE-FAIL:2

+*

+* CMD-SCAN-XXX

+*

+* IND-XXX

+*

+*/

+bool sta_cli_cmd_parse

+(

+    const char *cmd,

+    char *reply,

+    size_t reply_len

+)

+{

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

+    bzero(reply,reply_len);

+    sta_err_enum err = STA_ERR_UNKNOWN;

+    if(strncmp(cmd,(STA_CMD_OPEN),strlen(STA_CMD_OPEN)) == 0){

+        // Will OPEN connection with wpa_supplicant.

+        err = sta_cli_init();

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+            sta_should_send_connected_msg = FALSE;

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_CLOSE,strlen(STA_CMD_CLOSE)) == 0){

+        err = sta_cli_deinit();

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+            sta_should_send_connected_msg = TRUE;

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_SCAN,strlen(STA_CMD_SCAN)) == 0){

+        char data[STA_BUF_SIZE];

+        err = sta_cli_cmd_scan(cmd, data,STA_BUF_SIZE);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                data);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_STATUS,strlen(STA_CMD_STATUS)) == 0){

+        char data[STA_BUF_SIZE];

+        err = sta_cli_cmd_status(cmd, data,STA_BUF_SIZE);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                data);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_MIB,strlen(STA_CMD_MIB)) == 0){

+        char data[STA_BUF_SIZE];

+        err = sta_cli_cmd_mib(cmd, data,STA_BUF_SIZE);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                data);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_RECONFIGURE,strlen(STA_CMD_RECONFIGURE)) == 0){

+        err = sta_cli_cmd_reconfigure(cmd);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_DISCONNECT,strlen(STA_CMD_DISCONNECT)) == 0){

+		sta_disconnectting = TRUE;

+		err = sta_cli_cmd_disconnect(cmd);

+		// Not reply(Reply after disconnecd).

+#if 0

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+#endif

+		if(err == STA_ERR_SUCCESS)

+		{

+			printf("sta_cli_cmd_disconnect success.\n");

+			//pthread_mutex_lock(&sta_mutex);

+			//if(sta_connected)

+			//{

+				#define GET_STATUS_MAX 5

+				int count = 0;

+				bool ok = FALSE;

+				usleep(500);

+				while(count++ < GET_STATUS_MAX)

+				{

+					sta_err_enum err = sta_cli_process_cmd(STA_CMD_STATUS);

+				    if(STA_ERR_SUCCESS == err){

+				        char mac_ap[STA_MAC_LEN + 1];

+						if(!sta_cli_value_get(sta_cli_cmd_reply,

+							"bssid=",

+							mac_ap,

+							STA_MAC_LEN + 1)) // Disconnected.

+						{

+							printf("Disconnected success.\n");

+							snprintf(reply,reply_len,

+								"%s-%s-%s"STA_CMD_SEPARATED,

+								STA_TAG_CMD,

+								cmd,

+								STA_TAG_CMD_SUCCESS);

+							ok = TRUE;

+							break;

+						}else{ // Connected.

+							printf("Not disconnected.Try again(STATUS).\n");

+							usleep(500);

+						}

+				    }else{

+				        printf("STATUS cmd fail.\n");

+				        break;

+				    }

+				}

+

+				if(!ok) // fail

+				{

+					printf("Disconnect fail.\n");

+		            snprintf(reply,reply_len,

+		                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+		                STA_TAG_CMD,

+		                cmd,

+		                STA_TAG_CMD_FAIL,

+		                STA_ERR_UNKNOWN);

+				}

+				//sta_connected = FALSE;

+			//}

+			//pthread_mutex_unlock(&sta_mutex);

+		}else{

+			printf("sta_cli_cmd_disconnect fail.\n");

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+		}

+		sta_disconnectting = FALSE;

+    }else if(strncmp(cmd,STA_CMD_RECONNECT,strlen(STA_CMD_RECONNECT)) == 0){

+        err = sta_cli_cmd_reconnect(cmd);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_SAVE_CONFIG,strlen(STA_CMD_SAVE_CONFIG)) == 0){

+        err = sta_cli_cmd_save_config(cmd);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_SET_NETWORK,strlen(STA_CMD_SET_NETWORK)) == 0){

+        err = sta_cli_cmd_set_network(cmd,NULL);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_GET_NETWORK,strlen(STA_CMD_GET_NETWORK)) == 0){

+        char data[100];

+        err = sta_cli_cmd_get_network(cmd,data,100);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                data);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_REMOVE_NETWORK,strlen(STA_CMD_REMOVE_NETWORK)) == 0){

+        err = sta_cli_cmd_remove_network(cmd);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_ADD_NETWORK,strlen(STA_CMD_ADD_NETWORK)) == 0){

+        err = sta_cli_cmd_add_network(cmd);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_DISABLE_NETWORK,strlen(STA_CMD_DISABLE_NETWORK)) == 0){

+        err = sta_cli_cmd_disable_network(cmd);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_ENABLE_NETWORK,strlen(STA_CMD_ENABLE_NETWORK)) == 0){

+        err = sta_cli_cmd_enable_network(cmd);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_SELECT_NETWORK,strlen(STA_CMD_SELECT_NETWORK)) == 0){

+        err = sta_cli_cmd_select_network(cmd);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_LIST_NETWORKS,strlen(STA_CMD_REASSOCIATE)) == 0){

+        char data[STA_BUF_SIZE];

+        err = sta_cli_cmd_list_networks(cmd, data,STA_BUF_SIZE);

+

+//		char reply_tmp[STA_BUF_SIZE];

+//		memset(reply_tmp,0,STA_BUF_SIZE);

+//		char *reply_ptr = data;

+//		int index = 0;

+//		int pos = 0;

+//		while(*reply_ptr != '\0'){

+//			if(*reply_ptr == ','){

+//				index++;

+//			}

+

+//			if(index == 3){

+//				if(*reply_ptr == '\n'){

+//					index = 0;

+//					reply_tmp[pos++] = '\r';

+//					reply_tmp[pos++] = '\n';

+//				}

+//			}else{

+//				reply_tmp[pos++] = *reply_ptr;

+//			}

+

+//			reply_ptr++;

+//		}

+

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                data);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_REASSOCIATE,strlen(STA_CMD_REASSOCIATE)) == 0){

+        err = sta_cli_cmd_reassociate(cmd);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else if(strncmp(cmd,STA_CMD_REATTACH,strlen(STA_CMD_REATTACH)) == 0){

+        err = sta_cli_cmd_reattach(cmd);

+        if(err == STA_ERR_SUCCESS){

+            snprintf(reply,reply_len,

+                "%s-%s-%s"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_SUCCESS);

+        }else{

+            snprintf(reply,reply_len,

+                "%s-%s-%s:%d"STA_CMD_SEPARATED,

+                STA_TAG_CMD,

+                cmd,

+                STA_TAG_CMD_FAIL,

+                err);

+        }

+    }else{

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

+        return FALSE;

+    }

+    return TRUE;

+}

+

+

diff --git a/mbtk/libmbtk_lib_v2/wifi/sta_ctrl.c b/mbtk/libmbtk_lib_v2/wifi/sta_ctrl.c
new file mode 100755
index 0000000..66c55f5
--- /dev/null
+++ b/mbtk/libmbtk_lib_v2/wifi/sta_ctrl.c
@@ -0,0 +1,599 @@
+#include <string.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <pthread.h>

+#include <unistd.h>

+#include <sys/epoll.h>

+#include <errno.h>

+#include <sys/wait.h>

+#include <sys/types.h>

+

+#include "wpa_ctrl.h"

+#include "sta_ctrl.h"

+//#include "sta_log.h"

+

+#define WPA_SUPPLICANT_LOG_FILE "/data/wpa_supplicant.log"

+

+static void

+sta_ctrl_wpa_req_cb(char *msg, size_t len);

+

+static void*

+sta_ctrl_event_thread_run( void *arg );

+

+static sta_err_enum

+sta_ctrl_close_connection(void);

+

+static sta_err_enum

+sta_ctrl_open_connection(void);

+

+static sta_err_enum

+sta_ctrl_reconnect(void);

+

+static void

+sta_ctrl_recv_event(void);

+

+static sta_err_enum

+sta_ctrl_conf_file_parse

+(

+    const char *key,

+    char *value

+);

+

+extern struct wpa_ctrl;

+

+static struct wpa_ctrl *sta_ctrl_conn;

+static struct wpa_ctrl *sta_mon_conn;

+static int sta_ctrl_attached = 0;

+static pthread_t sta_event_thread_id = -1;

+static int sta_event_thread_is_running = 0;

+static char sta_ctrl_conf_file_path[50];

+static char sta_ctrl_ifname[10];

+static sta_ctrl_msg_cb sta_ctrl_msg = NULL;

+static int sta_ctrl_pipe_fd[2];

+

+static void

+sta_ctrl_wpa_req_cb(char *msg, size_t len)

+{

+	printf("%s\n", msg);

+}

+

+bool

+sta_ctrl_system

+(

+  const char   *command

+)

+{

+    int result = TRUE;

+    FILE *stream = NULL;

+

+    printf("system call: %s\n", command);

+

+    stream = popen( command, "w" );

+    if( stream == NULL )

+    {

+        printf("system command failed\n");

+        result = FALSE;

+    }

+    else if( 0 > pclose( stream ) )

+    {

+        printf("pclose command failed\n");

+    }

+

+    return result;

+}

+

+/*

+* Return TRUE if process <name> is not running after 2 second.

+*/

+bool

+sta_ctrl_kill_check(const char *name)

+{

+#define  PROCESS_KILL_RETRY  40

+    bool result;

+    int tmp = 0;

+    FILE *cmd;

+    char pid_s[STA_BUF_SIZE];

+    int pid;

+    tmp = snprintf(pid_s,STA_BUF_SIZE,

+        "pidof %s",name);

+    pid_s[tmp] = '\0';

+    tmp = 0;

+    while (tmp++ < PROCESS_KILL_RETRY)

+    {

+        usleep(50000);/*50 mili second*/

+        cmd = popen(pid_s, "r");

+        pid = 0;

+        bzero(pid_s, STA_BUF_SIZE);

+        if(cmd)

+        {

+            fgets(pid_s, STA_BUF_SIZE, cmd);

+            pclose(cmd);

+        }

+        pid = atoi(pid_s);

+        printf("%s pid =%d\n", name,pid);

+        /* If pid is zero we break from while*/

+        if(pid == 0)

+        {

+            result = TRUE;

+            goto exit_end;

+        }

+    }

+

+    printf("PID still running after waiting 2 second.\n");

+    result = FALSE;

+exit_end:

+#undef PROCESS_KILL_RETRY

+    return result;

+}

+

+/*

+* Return TRUE if process <name> is running.

+*/

+bool

+sta_ctrl_process_running(const char *name)

+{

+    char pid_s[STA_BUF_SIZE];

+    int tmp = snprintf(pid_s,STA_BUF_SIZE,

+        "pidof %s",name);

+    pid_s[tmp] = '\0';

+    FILE *cmd = popen(pid_s, "r");

+    bzero(pid_s, STA_BUF_SIZE);

+    if(cmd)

+    {

+        fgets(pid_s, STA_BUF_SIZE, cmd);

+        pclose(cmd);

+    }

+

+    int pid = atoi(pid_s);

+    printf("%s pid =%d\n", name,pid);

+    /* If pid is zero we break from while*/

+    if(pid == 0)

+    {

+        printf("%s not runnig.\n",name);

+        return FALSE;

+    }else{

+        printf("%s is runnig.\n",name);

+        return TRUE;

+    }

+}

+

+

+static void*

+sta_ctrl_event_thread_run( void *arg )

+{

+    printf("Thread[%ld] run().\n",pthread_self());

+

+    int nready;

+    struct epoll_event ev_sock,ev_pipe,events[20];

+    int epfd = epoll_create(256);

+    ev_sock.data.fd = wpa_ctrl_get_fd(sta_mon_conn);

+    ev_sock.events = EPOLLIN | EPOLLET;

+    epoll_ctl(epfd,EPOLL_CTL_ADD,wpa_ctrl_get_fd(sta_mon_conn),&ev_sock);

+

+    ev_pipe.data.fd = sta_ctrl_pipe_fd[0];

+    ev_pipe.events = EPOLLIN | EPOLLET;

+    epoll_ctl(epfd,EPOLL_CTL_ADD,sta_ctrl_pipe_fd[0],&ev_pipe);

+

+    for ( ; ; ) {

+        if(!sta_event_thread_is_running){

+            break;

+        }

+		printf("epoll_wait waitting...\n",nready);

+        nready = epoll_wait(epfd,events,20,-1);

+        printf("epoll_wait return.(count = %d)\n",nready);

+        int i;

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

+            if (events[i].events & EPOLLIN) {// Read

+                if (events[i].data.fd < 0)

+                    continue;

+

+                if(sta_mon_conn  // sta_mon_conn can not be NULL

+                    && events[i].data.fd == wpa_ctrl_get_fd(sta_mon_conn)){

+                    sta_ctrl_recv_event();

+                }else if(events[i].data.fd == sta_ctrl_pipe_fd[0]){

+                    printf("Thread end.[fd = %d]\n",events[i].data.fd);

+                    // End thread

+                    char buf_end[10] = {0};

+                    if(read(sta_ctrl_pipe_fd[0],buf_end,10) > 0

+                        && strcmp(buf_end,"0") == 0){

+                        sta_event_thread_is_running = 0;

+                        break;

+                    }

+                }else{

+                    printf("No such fd[%d].\n",events[i].data.fd);

+                }

+            } else {

+                printf("event error.\n");

+            }

+        }

+    }

+

+    close(epfd);

+    printf("Thread exit.\n");

+    return ((void*)0);

+}

+

+static sta_err_enum

+sta_ctrl_close_connection(void)

+{

+    printf("start.\n");

+    if (sta_ctrl_conn == NULL)

+        return STA_ERR_UNKNOWN;

+

+    if (sta_ctrl_attached) {

+        wpa_ctrl_detach(sta_mon_conn);

+        sta_ctrl_attached = 0;

+    }

+    wpa_ctrl_close(sta_ctrl_conn);

+    sta_ctrl_conn = NULL;

+    if (sta_mon_conn) {

+        wpa_ctrl_close(sta_mon_conn);

+        sta_mon_conn = NULL;

+    }

+

+    printf("end.\n");

+    return STA_ERR_SUCCESS;

+}

+

+static sta_err_enum

+sta_ctrl_open_connection(void)

+{

+    sta_err_enum result = STA_ERR_SUCCESS;

+

+    if(sta_ctrl_conn){

+        return STA_ERR_UNKNOWN;

+    }

+

+    char ctrl_path[100] = {0};

+    result = sta_ctrl_conf_file_parse("ctrl_interface", ctrl_path);

+    if(STA_ERR_SUCCESS != result){

+        printf("sta_ctrl_conf_file_parse() fail(%d).\n",result);

+        return result;

+    }

+    snprintf(ctrl_path + strlen(ctrl_path),10,

+        "/%s",

+        sta_ctrl_ifname);

+

+	printf("ctrl_path = \"%s\"\n",ctrl_path);

+

+    sta_ctrl_conn = wpa_ctrl_open(ctrl_path);

+    if (sta_ctrl_conn == NULL) {

+        sleep(1);

+        return sta_ctrl_open_connection();

+    }

+

+    sta_mon_conn = wpa_ctrl_open(ctrl_path);

+    if (sta_mon_conn == NULL) {

+        return STA_ERR_UNKNOWN;

+    }

+

+    if (wpa_ctrl_attach(sta_mon_conn) == 0) {

+        sta_ctrl_attached = 1;

+    } else {

+        printf("Warning: Failed to attach to "

+               "wpa_supplicant.\n");

+        sta_ctrl_close_connection();

+        return STA_ERR_UNKNOWN;

+    }

+

+    if(!sta_event_thread_is_running) {

+        sta_event_thread_is_running = 1;

+        int ret = pthread_create(&sta_event_thread_id,

+            NULL,

+            sta_ctrl_event_thread_run,

+            NULL);

+        if( ret != 0 ) {

+            printf( "Create thread error!\n");

+        }

+    }else{

+        printf("sta_event_thread is running.\n");

+        return STA_ERR_UNKNOWN;

+    }

+    return result;

+}

+

+static sta_err_enum

+sta_ctrl_reconnect(void)

+{

+    if(STA_ERR_SUCCESS == sta_ctrl_close_connection()){

+        return sta_ctrl_open_connection();

+    }else{

+        return STA_ERR_UNKNOWN;

+    }

+}

+

+static void

+sta_ctrl_recv_event(void)

+{

+	printf("start.\n");

+    if (sta_ctrl_conn == NULL) {

+        sta_ctrl_reconnect();

+		printf("sta_ctrl_conn == NULL:end.\n");

+        return;

+    }

+

+    while (wpa_ctrl_pending(sta_mon_conn) > 0) {

+        char buf[4096];

+        size_t len = sizeof(buf) - 1;

+        if (wpa_ctrl_recv(sta_mon_conn, buf, &len) == 0) {

+            buf[len] = '\0';

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

+            if(sta_ctrl_msg)

+                sta_ctrl_msg(buf);

+        } else {

+            printf("Could not read pending message.\n");

+            break;

+        }

+    }

+

+    if (wpa_ctrl_pending(sta_mon_conn) < 0) {

+        printf("Connection to wpa_supplicant lost - trying to "

+               "reconnect\n");

+        sta_ctrl_reconnect();

+    }

+

+	printf("end.\n");

+}

+

+static sta_err_enum

+sta_ctrl_conf_file_parse

+(

+    const char *key,

+    char *value

+)

+{

+    sta_err_enum result = STA_ERR_UNKNOWN;

+    FILE *fd = fopen(sta_ctrl_conf_file_path,"r");

+    if(!fd){

+        printf("Open file(%s) fail(%d).\n",sta_ctrl_conf_file_path,errno);

+        return STA_ERR_UNKNOWN;

+    }

+

+    char buf[1024];

+    while(fgets(buf,1024,fd)){

+        char *start = strstr(buf,key);

+        if(start){ // Find key

+            char *tmp = start + strlen(start) -1;

+            while(*tmp){

+                if(*tmp == '\r'

+                    || *tmp == '\n'){

+                    *tmp = '\0';

+                }else{

+                    break;

+                }

+                *tmp--;

+            }

+

+            int size = snprintf(value,100,

+                "%s",

+                start + strlen(key) + 1);

+            value[size] = '\0';

+            result = STA_ERR_SUCCESS;

+            break;

+        }

+    }

+

+    fclose(fd);

+

+    return result;

+}

+

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

+/************************ Public Fuction ***********************/

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

+sta_err_enum

+sta_ctrl_cmd_process

+(

+    const char *cmd,

+    char *reply,

+    size_t reply_len

+)

+{

+    sta_err_enum result = STA_ERR_SUCCESS;

+    bzero(reply,reply_len);

+    reply_len = reply_len - 1;

+    int ret = wpa_ctrl_request(sta_ctrl_conn,

+        cmd,

+        strlen(cmd),

+        reply,

+        &reply_len,

+        sta_ctrl_wpa_req_cb);

+    if (ret == -2) {

+        printf("command timed out.\n");

+        result = STA_ERR_TIMEOUT;

+        goto end_fail;

+    } else if (ret < 0) {

+        printf("command failed.\n");

+        result = STA_ERR_UNKNOWN;

+        goto end_fail;

+    } else {

+        reply[reply_len] = '\0';

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

+

+        if(reply_len > 0 && reply[reply_len - 1] != '\n')

+            printf("\n");

+    }

+

+end_success:

+

+    return result;

+end_fail:

+

+    return result;

+}

+

+/**

+* Open or close wlan driver.

+*/

+sta_err_enum

+sta_ctrl_driver_init(bool open)

+{

+    sta_err_enum result = STA_ERR_SUCCESS;

+

+    FILE *fd_tmp = NULL;

+    if(open){

+        fd_tmp = popen("/etc/wifi/mbtk_wifi_driver.sh sta start","r");

+    }else{

+        fd_tmp = popen("/etc/wifi/mbtk_wifi_driver.sh driver_rmmod","r");

+    }

+

+    if(fd_tmp){

+        char buf[200] = {0};

+        fgets(buf,200,fd_tmp);

+        pclose(fd_tmp);

+        if(strlen(buf) > 0){

+            printf("Driver %s fail.(%s)\n",(open?"open":"close"),buf);

+            result = STA_ERR_DRIVER;

+        }else{// Open wpa_supplicant

+            printf("Driver %s success.\n",(open?"open":"close"));

+        }

+    }else{

+        printf("Driver %s fail.(%s)\n",(open?"open":"close"));

+        result = STA_ERR_DRIVER;

+    }

+

+    return result;

+}

+

+sta_err_enum

+sta_ctrl_wpa_init

+(

+    const char *conf_file,

+    const char *interface,

+    sta_ctrl_msg_cb cb

+)

+{

+    sta_err_enum result = STA_ERR_SUCCESS;

+    if(!conf_file

+        || strlen(conf_file) == 0){

+        result = STA_ERR_UNKNOWN;

+        goto end_fail;

+    }

+

+    if(!interface

+        || strlen(interface) == 0){

+        result = STA_ERR_UNKNOWN;

+        goto end_fail;

+    }

+

+    sta_ctrl_msg = cb;

+

+    int size = snprintf(sta_ctrl_conf_file_path,

+        50,

+        "%s",

+        conf_file);

+    sta_ctrl_conf_file_path[size] = '\0';

+    size = snprintf(sta_ctrl_ifname,

+        10,

+        "%s",

+        interface);

+    sta_ctrl_ifname[size] = '\0';

+

+    if(pipe(sta_ctrl_pipe_fd)){

+        printf("pipe() fail(%d).\n",errno);

+        result = STA_ERR_UNKNOWN;

+        goto end_fail;

+    }

+

+    FILE *fd_tmp = popen("pidof wpa_supplicant","r");

+    if(fd_tmp){

+        char buf[200] = {0};

+        fgets(buf,200,fd_tmp);

+        pclose(fd_tmp);

+        if(strlen(buf) > 0){

+            printf("wpa_supplicant is running.(%s)\n",buf);

+        }else{// Open wpa_supplicant

+            bzero(buf,200);

+            

+            snprintf(buf,200,

+                "wpa_supplicant -Dnl80211 -c%s -i%s -f%s -ddd &",

+                conf_file,

+                interface,

+                WPA_SUPPLICANT_LOG_FILE);

+            

+            /*

+             snprintf(buf,200,

+                "wpa_supplicant -Dnl80211 -iwlan0 -c/etc/wifi/wpa_supplicant.conf -B");

+                */

+            if (sta_ctrl_system(buf)){

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

+                sleep(1);

+            }else{

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

+                result = STA_ERR_UNKNOWN;

+                goto end_fail;

+            }

+        }

+    }else{

+        printf("\"pidof wpa_supplicant\" fail\n");

+        result = STA_ERR_UNKNOWN;

+        goto end_fail;

+    }

+

+    result = sta_ctrl_open_connection();

+    if(STA_ERR_SUCCESS != result) {

+        printf("sta_ctrl_open_connection() fail(%d).\n",result);

+        goto end_fail;

+    }

+

+end_success:

+

+    return result;

+end_fail:

+

+    return result;

+}

+

+sta_err_enum

+sta_ctrl_wpa_deinit

+(

+    void

+)

+{

+    sta_err_enum result = STA_ERR_SUCCESS;

+    result = sta_ctrl_close_connection();

+    if(STA_ERR_SUCCESS != result){

+        goto end_fail;

+    }

+

+    bzero(sta_ctrl_conf_file_path,50);

+    bzero(sta_ctrl_ifname,10);

+

+    sta_event_thread_is_running = 0;

+    // End thread.

+    write(sta_ctrl_pipe_fd[1],"0",1);

+

+

+    printf("Waitting for thread(%ld) exit.\n",sta_event_thread_id);

+

+    pthread_join(sta_event_thread_id,NULL);

+

+    printf("pthread_join() return.\n");

+

+

+    close(sta_ctrl_pipe_fd[0]);

+    close(sta_ctrl_pipe_fd[1]);

+

+    sta_event_thread_id = -1;

+    sta_ctrl_msg = NULL;

+

+    // Stop process wpa_supplicant

+    if(sta_ctrl_system("killall -15 wpa_supplicant")

+        && sta_ctrl_kill_check("wpa_supplicant")){

+        printf("\"killall -15 wpa_supplicant\" success.\n");

+    }else{

+        if(sta_ctrl_system("killall -9 wpa_supplicant")){

+            printf("\"killall -9 wpa_supplicant\" success.\n");

+        }else{

+            printf("\"killall -9 wpa_supplicant\" fail.\n");

+        }

+    }

+

+end_success:

+    printf("sta_ctrl_wpa_deinit() end(success).\n");

+    return result;

+end_fail:

+    printf("sta_ctrl_wpa_deinit() end(fail)[%s].\n",result);

+    return result;

+}

+

diff --git a/mbtk/mbtk_rild_v2/inc/ril_info.h b/mbtk/mbtk_rild_v2/inc/ril_info.h
index e9cb822..df7c786 100755
--- a/mbtk/mbtk_rild_v2/inc/ril_info.h
+++ b/mbtk/mbtk_rild_v2/inc/ril_info.h
@@ -18,11 +18,10 @@
 #include "mbtk_list.h"
 #include "mbtk_device.h"
 #include "mbtk_queue.h"
+#include "mbtk_ril.h"
 
 #define SOCK_CLIENT_MAX 100
 #define EPOLL_LISTEN_MAX 100
-#define IND_REGISTER_MAX 10
-#define PACK_PROCESS_QUEUE_MAX 20
 
 #if 0
 #define MBTK_APN_PROP       "persist.mbtk.apn"
@@ -50,6 +49,7 @@
 typedef struct {
     mbtk_radio_state_enum radio_state;
     mbtk_sim_state_enum sim_state;
+    mbtk_sim_card_type_enum sim_type;
     int sock_listen_fd;
     int epoll_fd;
     bool at_process;
@@ -66,20 +66,6 @@
     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
@@ -102,7 +88,7 @@
 } ril_data_call_state_enum;
 
 typedef struct {
-    ril_urc_msg_id_enum msg;
+    ril_msg_id_enum msg;
 
     void *data;
     int data_len;
@@ -115,6 +101,19 @@
     bool waitting;
 } ril_cgact_wait_t;
 
+typedef enum {
+    RIL_ACT_STATE_DISCONNECTED = 0,
+    RIL_ACT_STATE_CONNECTING,
+    RIL_ACT_STATE_CONNECTED,
+    RIL_ACT_STATE_CONNECTED_RETRY,   // Network disconnection, retry after network recovery.
+    RIL_ACT_STATE_DISCONNECTING
+} ril_act_state_enum;
+
+typedef struct {
+    mbtk_apn_info_t apn_info;
+    ril_act_state_enum act_state;
+} ril_data_call_info_t;
+
 extern ril_info_t ril_info;
 
 
diff --git a/mbtk/mbtk_rild_v2/src/atchannel.c b/mbtk/mbtk_rild_v2/src/atchannel.c
index bf0384c..316e62a 100755
--- a/mbtk/mbtk_rild_v2/src/atchannel.c
+++ b/mbtk/mbtk_rild_v2/src/atchannel.c
@@ -36,7 +36,7 @@
 #define MAX_AT_RESPONSE (8 * 1024)
 #define HANDSHAKE_RETRY_COUNT 20
 #define HANDSHAKE_TIMEOUT_MSEC 500
-#define AT_BUFF_MAX 100
+#define AT_BUFF_MAX 1024
 
 static pthread_t s_tid_reader;
 static int s_at_fd = -1;    /* fd of the AT channel */
diff --git a/mbtk/mbtk_rild_v2/src/main.c b/mbtk/mbtk_rild_v2/src/main.c
index 5565621..f0dfb60 100755
--- a/mbtk/mbtk_rild_v2/src/main.c
+++ b/mbtk/mbtk_rild_v2/src/main.c
@@ -46,11 +46,13 @@
 #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"

+#define RIL_CALL_NUM_MAX 10

 

 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;

+static mbtk_ril_call_state_info_t call_list[RIL_CALL_NUM_MAX];

 extern mbtk_cell_pack_info_t cell_info;

 extern ril_cgact_wait_t cgact_wait;

 

@@ -61,8 +63,13 @@
 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 data_call_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);

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

+

+void data_call_state_change_cb(int cid, bool action, bool auto_change, int reason);

+static int send_pack_to_queue(sock_cli_info_t* cli_info, void* pack);

 

 /* Called on command thread */

 static void onATTimeout()

@@ -283,7 +290,401 @@
     }
 }

 

-static void urc_pdp_state_process(const char *s, const char *sms_pdu)

+static void ril_state_change(ril_msg_id_enum msg_id, void *data, int data_len)

+{
+    sock_cli_info_t *cli = NULL;

+    list_first(ril_info.sock_client_list);

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

+    {
+        if(cli->ind_num > 0) {
+            int i;
+            for(i = 0; i < IND_REGISTER_MAX; i++) {
+                if(cli->ind_register[i] == msg_id) {

+                    ril_ind_pack_send(cli->fd, msg_id, data, data_len);

+                    break;
+                }
+            }
+        }
+    }
+}

+

+static int urc_msg_distribute(bool async_process, ril_msg_id_enum msg_id, void *data, int data_len)

+{

+    // Send urc msg to client.

+    if(msg_id > RIL_MSG_ID_IND_BEGIN && msg_id < RIL_MSG_ID_IND_END) {

+        ril_state_change(msg_id, data, data_len);

+    }

+

+    // Async process urc msg.

+    if(async_process) {
+        ril_urc_msg_info_t *msg = (ril_urc_msg_info_t*)malloc(sizeof(ril_urc_msg_info_t));

+        if(msg) {

+            msg->msg = msg_id;

+            msg->data = mbtk_memcpy(data, data_len);

+            msg->data_len = data_len;

+            if(msg->data == NULL) {

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

+                return -1;

+            }

+

+            return send_pack_to_queue(NULL, msg);

+        } else {

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

+            return -1;

+        }

+    }

+

+    return 0;

+}

+

+// *SIMDETEC:1,SIM

+// *EUICC:1

+// +CPIN: SIM PIN

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

+{

+    mbtk_ril_sim_state_info_t state;

+    memset(&state, 0, sizeof(mbtk_ril_sim_state_info_t));

+    state.sim_type = MBTK_UNKNOWN;

+

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

+    char *line = tmp_s;

+    int tmp_int;

+    char *tmp_str;

+

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

+        if (at_tok_start(&line) < 0)

+        {

+            goto SIM_STATE_EXIT;

+        }

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

+        {

+            goto SIM_STATE_EXIT;

+        }

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

+        {

+            goto SIM_STATE_EXIT;

+        }

+

+        if(tmp_str) {

+            if(strcmp(tmp_str, "NOS") == 0) {

+                state.sim_type = ril_info.sim_type;

+                state.sim_state = MBTK_SIM_STATE_ABSENT;

+                ril_info.sim_state = MBTK_SIM_STATE_ABSENT;

+                urc_msg_distribute(false, RIL_MSG_ID_IND_SIM_STATE_CHANGE, &state, sizeof(mbtk_ril_sim_state_info_t));

+            } else if(strcmp(tmp_str, "SIM") == 0) {

+                state.sim_type = ril_info.sim_type;

+                state.sim_state = MBTK_SIM_STATE_NOT_READY;

+                ril_info.sim_state = MBTK_SIM_STATE_NOT_READY;

+                urc_msg_distribute(false, RIL_MSG_ID_IND_SIM_STATE_CHANGE, &state, sizeof(mbtk_ril_sim_state_info_t));

+            }

+        }

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

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

+        {

+            state.sim_state = MBTK_SIM_STATE_READY;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_SIM_PIN;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_SIM_PUK;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_PH_SIMLOCK_PIN;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_PH_SIMLOCK_PUK;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_PH_FSIM_PIN;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_PH_FSIM_PUK;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_SIM_PIN2;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_SIM_PUK2;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_PH_NET_PIN;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_PH_NET_PUK;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_PH_NETSUB_PIN;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_PH_NETSUB_PUK;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_PH_SP_PIN;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_PH_SP_PUK;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_PH_CORP_PIN;

+        }

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

+        {

+            state.sim_state = MBTK_SIM_STATE_PH_CORP_PUK;

+        }

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

+        {

+             state.sim_state = MBTK_SIM_STATE_ABSENT;

+        }

+

+        state.sim_type = ril_info.sim_type;

+        ril_info.sim_state = state.sim_state;

+

+        urc_msg_distribute(false, RIL_MSG_ID_IND_SIM_STATE_CHANGE, &state, sizeof(mbtk_ril_sim_state_info_t));

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

+        if (at_tok_start(&line) < 0)

+        {

+            goto SIM_STATE_EXIT;

+        }

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

+        {

+            goto SIM_STATE_EXIT;

+        }

+        ril_info.sim_type = (mbtk_sim_card_type_enum)tmp_int;

+    } else {

+        LOGW("Unknown URC.");

+    }

+

+SIM_STATE_EXIT:

+    free(tmp_s);

+}

+

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

+// +CALLDISCONNECT: 1

+// +CPAS: 4

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

+{

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

+    char *line = tmp_s;

+    int tmp_int;

+    char *tmp_str;

+

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

+        if (at_tok_start(&line) < 0)

+        {

+            goto CALL_STATE_EXIT;

+        }

+        if (at_tok_nextint(&line, &tmp_int) < 0) // call id

+        {

+            goto CALL_STATE_EXIT;

+        }

+

+        int i = 0;

+        while(i < RIL_CALL_NUM_MAX) {

+            if(call_list[i].call_id == tmp_int)

+                break;

+            i++;

+        }

+        if(i == RIL_CALL_NUM_MAX) { // No found this call id.

+            i = 0;

+            while(i < RIL_CALL_NUM_MAX) { // Find next empty call item.

+                if(call_list[i].call_id == 0)

+                    break;

+                i++;

+            }

+            call_list[i].call_id = tmp_int;

+        }

+

+        LOGD("Found call id : %d", call_list[i].call_id);

+

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

+        {

+            goto CALL_STATE_EXIT;

+        }

+        call_list[i].dir = (mbtk_ril_call_dir_enum)tmp_int;

+

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

+        {

+            goto CALL_STATE_EXIT;

+        }

+        call_list[i].state = (mbtk_ril_call_state_enum)tmp_int;

+

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

+        {

+            goto CALL_STATE_EXIT;

+        }

+

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

+        {

+            goto CALL_STATE_EXIT;

+        }

+

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

+        {

+            goto CALL_STATE_EXIT;

+        }

+        memset(call_list[i].call_number, 0, sizeof(call_list[i].call_number));

+        if(tmp_str && strlen(tmp_str) > 0) {

+            memcpy(call_list[i].call_number, tmp_str, strlen(tmp_str));

+        }

+

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

+        {

+            goto CALL_STATE_EXIT;

+        }

+        call_list[i].num_type = (mbtk_ril_call_num_type_enum)tmp_int;

+

+        urc_msg_distribute(false, RIL_MSG_ID_IND_CALL_STATE_CHANGE, &(call_list[i]), sizeof(mbtk_ril_call_state_info_t));

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

+        if (at_tok_start(&line) < 0)

+        {

+            goto CALL_STATE_EXIT;

+        }

+        if (at_tok_nextint(&line, &tmp_int) < 0) // call id

+        {

+            goto CALL_STATE_EXIT;

+        }

+

+        int i = 0;

+        while(i < RIL_CALL_NUM_MAX) {

+            if(call_list[i].call_id == tmp_int)

+                break;

+            i++;

+        }

+

+        if(i == RIL_CALL_NUM_MAX) { // No found this call id.

+            LOGE("No found this call id : %d", tmp_int);

+            goto CALL_STATE_EXIT;

+        }

+

+        call_list[i].state = MBTK_RIL_CALL_STATE_DISCONNECT;

+

+        urc_msg_distribute(false, RIL_MSG_ID_IND_CALL_STATE_CHANGE, &(call_list[i]), sizeof(mbtk_ril_call_state_info_t));

+

+        // Reset after call disconnect.

+        memset(&(call_list[i]), 0, sizeof(mbtk_ril_call_state_info_t));

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

+

+    } else {

+        LOGW("Unknown URC.");

+    }

+

+CALL_STATE_EXIT:

+    free(tmp_s);

+}

+

+// *ECALLDATA: <urc_id>[,<urc_data>]

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

+{

+    mbtk_ril_ecall_state_info_t ecall_state;

+    memset(&ecall_state, 0, sizeof(mbtk_ril_ecall_state_info_t));

+

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

+    char *line = tmp_s;

+    int tmp_int;

+    char *tmp_str;

+    if (at_tok_start(&line) < 0)

+    {

+        goto ECALLDATA_EXIT;

+    }

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

+    {

+        goto ECALLDATA_EXIT;

+    }

+    ecall_state.urc_id = (uint8)tmp_int; // urc_id

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

+    {

+        goto ECALLDATA_EXIT;

+    }

+

+    if(tmp_str && strlen(tmp_str) > 0) {

+        memcpy(ecall_state.urc_data, tmp_str, strlen(tmp_str));

+    }

+

+    urc_msg_distribute(false, RIL_MSG_ID_IND_ECALL_STATE_CHANGE, &ecall_state, sizeof(mbtk_ril_ecall_state_info_t));

+ECALLDATA_EXIT:

+    free(tmp_s);

+}

+

+// +CMT: ,23

+// 0891683108200855F6240D91688189911196F10000221130717445230331D90C

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

+{

+

+}

+

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

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

+{

+    mbtk_ril_net_reg_state_info_t state;

+    memset(&state, 0, sizeof(mbtk_ril_net_reg_state_info_t));

+    state.tech = MBTK_RADIO_TECH_UNKNOWN;

+

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

+    {

+        state.type = MBTK_NET_REG_TYPE_CALL;

+    } else if(strStartsWith(s, "+CGREG:")) {

+        state.type = MBTK_NET_REG_TYPE_DATA_GSM_WCDMA;

+    } else {

+        state.type = MBTK_NET_REG_TYPE_DATA_LTE;

+    }

+

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

+    char *line = tmp_s;

+    int tmp_int;

+    char *tmp_str;

+    if (at_tok_start(&line) < 0)

+    {

+        goto CGREG_EXIT;

+    }

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

+    {

+        goto CGREG_EXIT;

+    }

+    state.reg_state = (mbtk_net_reg_state_enum)tmp_int; // Reg State.

+    if (state.reg_state) // Reg

+    {

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

+        {

+            goto CGREG_EXIT;

+        }

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

+        {

+            goto CGREG_EXIT;

+        }

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

+        {

+            goto CGREG_EXIT;

+        }

+        state.tech = (mbtk_radio_technology_enum)tmp_int; // AcT

+    }

+

+    urc_msg_distribute(false, RIL_MSG_ID_IND_NET_REG_STATE_CHANGE, &state, sizeof(mbtk_ril_net_reg_state_info_t));

+CGREG_EXIT:

+    free(tmp_s);

+}

+

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

 {

     // "CONNECT"

     if(strStartsWith(s, "CONNECT"))

@@ -346,41 +747,47 @@
         // "+CGEV: EPS PDN ACT ")) { // +CGEV: EPS PDN ACT <cid>

         // "+CGEV: ME PDN DEACT ")) { // +CGEV: EPS PDN DEACT <cid>

         // "+CGEV: ME PDN ACT ")) { // +CGEV: ME PDN ACT <cid>,1

-        int cid = -1;

-        int reason = -1;

-        bool act = FALSE;

-        if (sscanf(s, "+CGEV: NW PDN DEACT %d", &cid) == 1) {

-            act = FALSE;

-        } else if (sscanf(s, "+CGEV: ME PDN DEACT %d", &cid) == 1) {

-            act = FALSE;

-        } else if(sscanf(s, "+CGEV: ME PDN ACT %d,%d", &cid, &reason) == 2

-                || sscanf(s, "+CGEV: ME PDN ACT %d", &cid) == 1) {

-            act = TRUE;

+        mbtk_ril_pdp_state_info_t cgev_info;

+        memset(&cgev_info, 0, sizeof(mbtk_ril_pdp_state_info_t));

+        if (sscanf(s, "+CGEV: NW PDN DEACT %d", &(cgev_info.cid)) == 1) {

+            cgev_info.action = FALSE;

+        } else if (sscanf(s, "+CGEV: ME PDN DEACT %d", &(cgev_info.cid)) == 1) {

+            cgev_info.action = FALSE;

+        } else if(sscanf(s, "+CGEV: ME PDN ACT %d,%d", &(cgev_info.cid), &(cgev_info.reason)) == 2

+                || sscanf(s, "+CGEV: ME PDN ACT %d", &(cgev_info.cid)) == 1) {

+            cgev_info.action = TRUE;

         } else if (!strcmp(s, "+CGEV: ME DETACH")) {

             if(cgact_wait.waitting) {

-                cid = cgact_wait.cid;

+                cgev_info.cid = cgact_wait.cid;

             }

-            act = FALSE;

-        } else if (sscanf(s, "+CGEV: NW MODIFY %d,%d", &cid, &reason) == 2) {

-            act = TRUE;

-        } else if(sscanf(s, "+CGEV: EPS PDN ACT %d", &cid) == 1) {

-            act = TRUE;

+            cgev_info.action = FALSE;

+        } else if (sscanf(s, "+CGEV: NW MODIFY %d,%d", &(cgev_info.cid), &(cgev_info.reason)) == 2) {

+            cgev_info.action = TRUE;

+        } else if(sscanf(s, "+CGEV: EPS PDN ACT %d", &(cgev_info.cid)) == 1) {

+            cgev_info.action = TRUE;

         } else {

             LOGD(">>>>>>>>>No process +CGEV <<<<<<<<<");

             return;

         }

+        cgev_info.auto_change = !cgact_wait.waitting;

 

         if(cgact_wait.act) {

-            if(cgact_wait.waitting && act && cgact_wait.cid == cid) {

+            if(cgact_wait.waitting && cgev_info.action && cgact_wait.cid == cgev_info.cid) {

                 cgact_wait.waitting = false;

             }

         } else {

-            if(cgact_wait.waitting && !act && cgact_wait.cid == cid) {

+            if(cgact_wait.waitting && !cgev_info.action && cgact_wait.cid == cgev_info.cid) {

                 cgact_wait.waitting = false;

             }

         }

 

-        LOGD("+CGEV:cid - %d, act - %d, reason - %d", cid, act, reason);

+        LOGD("+CGEV:cid - %d, act - %d, auto_change - %d, reason - %d", cgev_info.cid, cgev_info.action,

+            cgev_info.auto_change, cgev_info.reason);

+

+        if(cgev_info.cid >= MBTK_APN_CID_MIN && cgev_info.cid <= MBTK_APN_CID_MAX) {

+            urc_msg_distribute(false, RIL_MSG_ID_IND_PDP_STATE_CHANGE, &cgev_info, sizeof(mbtk_ril_pdp_state_info_t));

+        }

+

 #else

         if(at_process) {

             if(cgact_wait.act) {

@@ -1217,7 +1624,7 @@
     {

 

     } else if(strStartsWith(s, "CONNECT") || strStartsWith(s, "+CGEV:")) {

-        urc_pdp_state_process(s, sms_pdu);

+        urc_pdp_state_change_process(s, sms_pdu);

     } else if(strStartsWith(s, "+EEMLTESVC:") || strStartsWith(s, "+EEMLTEINTER:")

         || strStartsWith(s, "+EEMLTEINTRA:") || strStartsWith(s, "+EEMLTEINTERRAT:")

         || strStartsWith(s, "+EEMUMTSSVC:") || strStartsWith(s, "+EEMUMTSINTRA:")

@@ -1226,7 +1633,6 @@
         || strStartsWith(s, "+EEMGINFONC:")) {

         urc_cell_info_process(s, sms_pdu);

     }

-#if 0

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

     {

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

@@ -1235,114 +1641,14 @@
             ptr++;

         }

 

-        uint8 state;

+        mbtk_ril_radio_state_info_t state;

+        memset(&state, 0, sizeof(mbtk_ril_radio_state_info_t));

         if(*ptr == '1') {

-            //net_info.radio_state = MBTK_RADIO_STATE_ON;

-            // mbtk_radio_ready_cb();

-            state = (uint8)1;

+            state.radio_state = MBTK_RADIO_STATE_FULL_FUNC;

         } else {

-            //net_info.radio_state = MBTK_RADIO_STATE_OFF;

-            state = (uint8)0;

+            state.radio_state = MBTK_RADIO_STATE_MINI_FUNC;

         }

-        urc_msg_distribute(true, INFO_URC_MSG_RADIO_STATE, &state, 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);

-        }

+        urc_msg_distribute(true, RIL_MSG_ID_IND_RADIO_STATE_CHANGE, &state, sizeof(mbtk_ril_radio_state_info_t));

     }

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

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

@@ -1351,105 +1657,33 @@
     // $CREG: 1, "8010", "000060a7", 0,, 2, 0

     // +CGREG: 1

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

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

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

+         || strStartsWith(s, "+CREG:"))     // GMS/WCDMA/LTE CS 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);

+        urc_net_reg_state_change_process(s, sms_pdu);

     }

-    // +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.

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

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

+        || strStartsWith(s, "+CPAS:")

+        || strStartsWith(s, "+CALLDISCONNECT:"))

     {

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

+        urc_call_state_change_process(s, sms_pdu);

     }

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

+        || strStartsWith(s, "*EUICC:")

+        || strStartsWith(s, "+CPIN:"))

+    {

+        urc_sim_state_change_process(s, sms_pdu);

+    }

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

+    {

+        urc_sms_state_change_process(s, sms_pdu);

+    }

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

+    {

+        urc_ecall_state_change_process(s, sms_pdu);

+    }

+#if 0

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

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

     {

@@ -1742,32 +1976,6 @@
         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

-

 #endif

     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"

     {

@@ -1886,37 +2094,40 @@
 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);
-    }
+    if(pack->msg_type == RIL_MSG_TYPE_REQ)

+    {

+        if(pack->msg_id > RIL_MSG_ID_IND_BEGIN

+            && pack->msg_id < RIL_MSG_ID_IND_END) {

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

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

+        }

+    } else {

+        LOGE("Pack type error : %d", pack->msg_type);

+    }

 }

 

 // Return MBTK_INFO_ERR_SUCCESS,will call pack_error_send() to send RSP.
@@ -1929,12 +2140,16 @@
         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_DATA_CALL_BEGIN && pack->msg_id < RIL_MSG_ID_DATA_CALL_END) {

+        return data_call_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 if(pack->msg_id > RIL_MSG_ID_ECALL_BEGIN && pack->msg_id < RIL_MSG_ID_ECALL_END) {

+        return ecall_pack_req_process(cli_info, pack);

     } else {

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

         return MBTK_RIL_ERR_FORMAT;

@@ -1943,15 +2158,18 @@
 

 static void urc_msg_process(ril_urc_msg_info_t *msg)

 {
-    uint8 *data = NULL;
-    if(msg->data) {
-        data = (uint8*)msg->data;
-    }
+    if(!msg->data || msg->data_len <= 0) {

+        LOGE("URC data is NULL.");

+        return;

+    }

+

     switch(msg->msg) {
-        case RIL_URC_MSG_RADIO_STATE:

-        {
+        case RIL_MSG_ID_IND_RADIO_STATE_CHANGE:

+        {

+            mbtk_ril_radio_state_info_t *state = (mbtk_ril_radio_state_info_t*)msg->data;

+            LOGD("Radio state : %d", state->radio_state);

             break;
-        }
+        }

         default:
         {
             LOGE("Unknown URC : %d", msg->msg);
@@ -2046,8 +2264,9 @@
                                 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);

+                                // Send msg RIL_MSG_ID_IND_SER_STATE_CHANGE to client.

+                                mbtk_ril_ser_state_enum state = MBTK_RIL_SER_STATE_READY;

+                                ril_ind_pack_send(client_fd, RIL_MSG_ID_IND_SER_STATE_CHANGE, &state, 1);

                             }
                             else
                             {
@@ -2135,13 +2354,15 @@
                 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);
+            } else { // REQ from myself.

+                if(item->pack) {

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

+                }

             }
         }
     }
diff --git a/mbtk/mbtk_rild_v2/src/ril_data_call.c b/mbtk/mbtk_rild_v2/src/ril_data_call.c
index 97ff338..14d1128 100755
--- a/mbtk/mbtk_rild_v2/src/ril_data_call.c
+++ b/mbtk/mbtk_rild_v2/src/ril_data_call.c
@@ -17,6 +17,13 @@
 #include "mbtk_utils.h"
 #include "ril_info.h"
 
+ril_cgact_wait_t cgact_wait;
+static ril_data_call_info_t info_list[MBTK_APN_CID_MAX];
+
+static int req_apn_get(bool get_def_cid, 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(mbtk_apn_info_array_t *apns);
+
 /*
 IPv4 : 10.255.74.26
 IPv6 : 254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239
@@ -200,3 +207,1140 @@
     return net_ifc_config(cid, def_route, as_dns, ip_info);
 }
 
+static int apn_file_save(const char *file, char *data, int data_len)
+{
+    if(!file) {
+        return -1;
+    }
+
+    if(str_empty(data) || data_len <= 0) { // Delete file
+        return unlink(file);
+    } else {
+        int fd = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0644);
+        if(fd < 0) {
+            LOGE("open(%s) fail:%d", file, errno);
+            return -1;
+        }
+
+        if(write(fd, data, data_len) != data_len) {
+            LOGE("write fail:%d", errno);
+            close(fd);
+            return -1;
+        }
+        close(fd);
+        return 0;
+    }
+}
+
+static int apn_file_read(const char *file, char *data, int data_len)
+{
+    if(!file) {
+        LOGE("file is null");
+        return -1;
+    }
+
+    if(data == NULL || data_len <= 100) {
+        LOGE("apn_file_read() arg error.");
+        return -1;
+    } else {
+        int len = -1;
+        int fd = open(file, O_RDONLY, 0644);
+        if(fd < 0) {
+            LOGE("open(%s) fail:%d", file, errno);
+            return -1;
+        }
+
+        memset(data, 0, data_len);
+        if((len = read(fd, data, data_len)) < 0) {
+            LOGE("read fail:%d", errno);
+            close(fd);
+            return -1;
+        }
+        close(fd);
+        return len;
+    }
+}
+
+
+void apn_auto_conf_from_prop()
+{
+    mbtk_apn_info_array_t apns;
+    int i = 0;
+    memset(&apns, 0, sizeof(mbtk_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_check_and_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;
+
+        // The cid no use,so can not delete.
+        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(FALSE, &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 { // Add or change APN.
+        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(TRUE, &apns, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+        {
+            LOGW("Get APN fail.");
+            if(apn->cid == MBTK_RIL_CID_NUL) {
+                apn->cid = start_cid;
+            }
+        }
+        else
+        {
+            int index = 0;
+            bool is_change = FALSE;  // Is add APN default.
+
+            if(apn->cid == MBTK_RIL_CID_NUL) { // Is add (auto set cid).
+                for(; start_cid <= MBTK_APN_CID_MAX; start_cid++) {
+                    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;
+                        break;
+                    }
+                }
+
+                if(start_cid > MBTK_APN_CID_MAX) {
+                    LOGE("APN full.");
+                    return -1;
+                }
+                is_change = FALSE;
+            } else {
+                index = 0;
+                while(index < apns.num) {
+                    if(apns.apns[index].cid == apn->cid) {
+                        is_change = TRUE;
+                        break;
+                    }
+                    index++;
+                }
+            }
+
+            // Is add,the APN can't same.
+            if(!is_change) {
+                index = 0;
+                while(index < apns.num) {
+                    if(strcmp(apns.apns[index].apn,apn->apn) == 0) {
+                        LOGW("APN : %s exist.", apn->apn);
+                        return -1;
+                    }
+                    index++;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+static void apn_prop_get(mbtk_apn_info_array_t *apns)
+{
+    char prop_name[128] = {0};
+    char prop_data[1024] = {0};
+    int cid;
+    memset(apns, 0, sizeof(mbtk_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;
+        //apns->cid_for_def_dns = MBTK_RIL_CID_DEF;
+        cid = MBTK_RIL_CID_2;
+    } else {
+        cid = MBTK_APN_CID_MIN;
+    }
+
+    char def_cid[10] = {0};
+    sprintf(def_cid, "%d", MBTK_RIL_CID_DEF);
+    if(property_get(MBTK_DEF_ROUTE_CID, prop_data, def_cid) > 0 && !str_empty(prop_data)) {
+        apns->cid_for_def_route = (mbtk_ril_cid_enum)atoi(prop_data);
+    }
+    memset(prop_data, 0, sizeof(prop_data));
+    if(property_get(MBTK_DEF_DNS_CID, prop_data, def_cid) > 0 && !str_empty(prop_data)) {
+        apns->cid_for_def_dns = (mbtk_ril_cid_enum)atoi(prop_data);
+    }
+
+    for(; cid <= MBTK_APN_CID_MAX; cid++) {
+        memset(prop_name, 0, sizeof(prop_name));
+        memset(prop_data, 0, sizeof(prop_data));
+
+        sprintf(prop_name, "%s_%d",MBTK_APN_PROP,cid);
+        // ip_type,auth,auto_data_call,apn,user,pass
+#if 0
+        if(property_get(prop_name, prop_data, "") > 0 && !str_empty(prop_data)) {
+#else
+        if(apn_file_read(prop_name, prop_data, sizeof(prop_data)) > 0 && !str_empty(prop_data)) {
+#endif
+            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
+            ptr_2 = strstr(ptr_1, ",");
+            if(!ptr_2) {
+                continue;
+            }
+            if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+                memcpy(apns->apns[apns->num].pass, ptr_1, ptr_2 - ptr_1); // pass
+            }
+
+            ptr_2++; // Jump ',' to type
+            if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+                memcpy(apns->apns[apns->num].type, ptr_2, strlen(ptr_2)); // type
+            }
+
+            apns->num++;
+        }
+    }
+}
+
+static int apn_prop_get_by_cid(mbtk_ril_cid_enum cid, mbtk_apn_info_t *apn)
+{
+    char prop_name[128] = {0};
+    char prop_data[1024] = {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 0
+    if(property_get(prop_name, prop_data, "") > 0 && !str_empty(prop_data)) {
+#else
+    if(apn_file_read(prop_name, prop_data, sizeof(prop_data)) > 0 && !str_empty(prop_data)) {
+#endif
+        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
+        ptr_2 = strstr(ptr_1, ",");
+        if(!ptr_2) {
+            return -1;
+        }
+        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+            memcpy(apn->user, ptr_1, ptr_2 - ptr_1); // pass
+        }
+
+        ptr_2++; // Jump ',' to type
+        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+            memcpy(apn->type, ptr_2, strlen(ptr_2)); // pass
+        }
+        return 0;
+    }
+    return -1;
+}
+
+static int apn_prop_get_by_cid_without_cgdcont(mbtk_ril_cid_enum cid, mbtk_apn_info_t *apn)
+{
+    char prop_name[128] = {0};
+    char prop_data[1024] = {0};
+
+    sprintf(prop_name, "%s_%d",MBTK_APN_PROP,cid);
+    // ip_type,auth,auto_data_call,apn,user,pass
+#if 0
+    if(property_get(prop_name, prop_data, "") > 0 && !str_empty(prop_data)) {
+#else
+    if(apn_file_read(prop_name, prop_data, sizeof(prop_data)) > 0 && !str_empty(prop_data)) {
+#endif
+        LOGD("APN : %s", prop_data);
+        char *ptr_1 = prop_data;
+        apn->auto_save = (uint8)1;
+        //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 0
+        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+            memcpy(apn->apn, ptr_1, ptr_2 - ptr_1); // apn
+        }
+#endif
+
+        ptr_2++; // Jump ',' to user
+        ptr_1 = strstr(ptr_2, ",");
+        if(!ptr_1) {
+            return -1;
+        }
+        if(memcmp(ptr_2, "NULL", 4)) { // Not "NULL"
+            memcpy(apn->user, ptr_2, ptr_1 - ptr_2); // user
+        }
+
+        ptr_1++; // Jump ',' to pass
+        ptr_2 = strstr(ptr_1, ",");
+        if(!ptr_2) {
+            return -1;
+        }
+        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+            memcpy(apn->user, ptr_1, ptr_2 - ptr_1); // pass
+        }
+
+        ptr_2++; // Jump ',' to type
+        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
+            memcpy(apn->type, ptr_2, strlen(ptr_2)); // pass
+        }
+        return 0;
+    } else {
+        apn->auto_save = (uint8)0;
+    }
+    return -1;
+}
+
+static int apn_prop_set(mbtk_apn_info_t *apn)
+{
+    char prop_name[20] = {0};
+    char prop_data[1024] = {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, 1024, "%d,%d,%d,%s,%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,
+                str_empty(apn->pass) ? "NULL" : apn->type);
+        }
+
+#if 0
+        ret = property_set(prop_name, prop_data);
+#else
+        if(str_empty(apn->apn)) { // Delete APN
+            ret = apn_file_save(prop_name, NULL, 0);
+        } else {
+            ret = apn_file_save(prop_name, prop_data, strlen(prop_data));
+        }
+#endif
+    }
+
+    if(!ret && 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);
+    }
+    if(!ret && apn->as_dns) {
+        memset(prop_data, 0, sizeof(prop_data));
+        prop_data[0] = '0' + apn->cid;
+        ret = property_set(MBTK_DEF_DNS_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;
+        apn.as_dns = data_info->as_dns;
+        return apn_prop_set(&apn);
+    }
+}
+
+static int wait_cgact_complete(int timeout)
+{
+    int count = timeout * 10; // timeout * 1000 / 100
+    int i = 0;
+
+    while(cgact_wait.waitting && i < count) {
+        i++;
+        usleep(100000); // 100ms
+    }
+
+    memset(&cgact_wait, 0, sizeof(ril_cgact_wait_t));
+    if(i == count) { // Timeout
+        return -1;
+    } else {
+        return 0;
+    }
+}
+
+/*
+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(bool get_def_cid, 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;
+    int cid_start;
+    if(apn_conf_support(MBTK_RIL_CID_DEF)) {
+        cid_start = MBTK_RIL_CID_DEF;
+    } else {
+        if(get_def_cid) {
+            cid_start = MBTK_RIL_CID_DEF;
+        } else {
+            cid_start = MBTK_RIL_CID_2;
+        }
+    }
+    /*
+    <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 >= cid_start && 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));
+            }
+
+            // Get other arg from proc or file.
+            apn_prop_get_by_cid_without_cgdcont(apns->apns[apns->num].cid, &(apns->apns[apns->num]));
+
+            apns->num++;
+        }
+
+        lines_ptr = lines_ptr->p_next;
+    }
+
+    char prop_name[128] = {0};
+    char prop_data[1024] = {0};
+    char def_cid[10] = {0};
+    sprintf(def_cid, "%d", MBTK_RIL_CID_DEF);
+
+    if(property_get(MBTK_DEF_ROUTE_CID, prop_data, def_cid) > 0 && !str_empty(prop_data)) {
+        apns->cid_for_def_route = (mbtk_ril_cid_enum)atoi(prop_data);
+    }
+    memset(prop_data, 0, sizeof(prop_data));
+    if(property_get(MBTK_DEF_DNS_CID, prop_data, def_cid) > 0 && !str_empty(prop_data)) {
+        apns->cid_for_def_dns = (mbtk_ril_cid_enum)atoi(prop_data);
+    }
+
+    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, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[400] = {0};
+    int err = 0;
+    memset(&cgact_wait, 0, sizeof(ril_cgact_wait_t));
+    cgact_wait.waitting = true;
+    cgact_wait.cid = cid;
+    cgact_wait.act = true;
+
+    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;
+
+    memset(&cgact_wait, 0, sizeof(ril_cgact_wait_t));
+    cgact_wait.waitting = true;
+    cgact_wait.cid = cid;
+    cgact_wait.act = false;
+
+    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 data_call_state_change_cb(int cid, bool action, bool auto_change, int reason)
+{
+    if(auto_change && !action) {
+        info_list[cid - 1].act_state = RIL_ACT_STATE_CONNECTED_RETRY;
+    }
+}
+
+//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 data_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_DATA_CALL_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(FALSE, &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_check_and_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.");
+                            }
+
+                            memcpy(&(info_list[apn->cid - 1].apn_info), apn, sizeof(mbtk_apn_info_t));
+
+                            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_DATA_CALL_OPT:
+        {
+            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;
+                // Check for cid 1.
+                if(!apn_conf_support(call_info->cid)) {
+                    err = MBTK_RIL_ERR_UNSUPPORTED;
+                    LOGD("Can not data call for CID : %d", call_info->cid);
+                } else {
+                    if(call_info->type == MBTK_DATA_CALL_START) {
+                        mbtk_ip_info_t ip_info;
+                        memset(&ip_info, 0, sizeof(ip_info));
+#if 0
+                        if(apn_prop_reset(call_info)) {
+                            err = MBTK_RIL_ERR_REQ_UNKNOWN;
+                            LOG("apn_prop_reset() fail.");
+                        } else
+#else
+                        if(apn_prop_reset(call_info)) {
+                            LOG("apn_prop_reset() fail.");
+                        }
+#endif
+                        {
+                            int index = 0;
+                            info_list[call_info->cid - 1].act_state = RIL_ACT_STATE_CONNECTING;
+data_call_retry:
+                            if(req_data_call_start(call_info->cid, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                            {
+                                if(call_info->retry_interval[index] > 0) {
+                                    LOGD("Start data call fail, will retry in %d s.", call_info->retry_interval[index]);
+                                    sleep(call_info->retry_interval[index]);
+                                    index++;
+                                    goto data_call_retry;
+                                } else {
+                                    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
+                            {
+                                // Wait for "CONNECT" or "+CGEV:"
+                                if(wait_cgact_complete(call_info->timeout)) { // Timeout
+                                    err = MBTK_RIL_ERR_TIMEOUT;
+                                    break;
+                                }
+
+                                // Get Ip informations.
+                                cme_err = MBTK_RIL_ERR_CME_NON;
+                                if(req_data_call_state_get(call_info->cid ,&ip_info, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
+                                {
+                                    LOGD("Get net informations fail.");
+                                    err = MBTK_RIL_ERR_NET_CONF;
+                                }
+                                else
+                                {
+                                    // Config network informations.
+                                    if(net_ifc_reconfig(call_info->cid, call_info->def_route, call_info->as_dns, &ip_info)) {
+                                        err = MBTK_RIL_ERR_NET_CONF;
+                                        break;
+                                    }
+
+                                    info_list[call_info->cid - 1].act_state = RIL_ACT_STATE_CONNECTED;
+
+                                    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) {
+                        info_list[call_info->cid - 1].act_state = RIL_ACT_STATE_DISCONNECTING;
+                        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
+                        {
+                            // Wait for "CONNECT" or "+CGEV:"
+                            if(wait_cgact_complete(call_info->timeout)) { // Timeout
+                                err = MBTK_RIL_ERR_TIMEOUT;
+                                break;
+                            }
+
+                            // Clean network config.
+                            if(net_ifc_config(call_info->cid, FALSE, FALSE, NULL)) {
+                                err = MBTK_RIL_ERR_NET_CONF;
+                                break;
+                            }
+
+                            info_list[call_info->cid - 1].act_state = RIL_ACT_STATE_DISCONNECTED;
+                            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_ecall.c b/mbtk/mbtk_rild_v2/src/ril_ecall.c
new file mode 100755
index 0000000..dfb4ace
--- /dev/null
+++ b/mbtk/mbtk_rild_v2/src/ril_ecall.c
@@ -0,0 +1,1141 @@
+#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"
+
+static mbtk_ecall_mode_type_enum ecall_mode = MBTK_ECALL_MODE_TYPE_EU;
+
+void ril_rsp_pack_send(int fd, int ril_id, int msg_index, const void* data, int data_len);
+
+static int req_ecall_msdcfg(mbtk_ecall_msd_cfg_info_t *cfg_info, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[1024] = {0};
+    sprintf(cmd, "AT*ECALLMSDCFG=%d,\"%s\",0", cfg_info->item_type, cfg_info->data);
+    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;
+}
+
+static int req_ecall_msdgen(int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command("AT*ECALLMSDGEN", &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+static int req_ecall_msd_set(const uint8 *msd, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[1024] = {0};
+    sprintf(cmd, "AT*ECALLMSD=\"%s\"", msd);
+    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;
+}
+
+static int req_ecall_msd_get(uint8 *msd, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT*ECALLMSD?", "*ECALLMSD:", &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;
+    }
+
+    if(tmp_ptr && strlen(tmp_ptr) > 0) {
+        memcpy(msd, tmp_ptr, strlen(tmp_ptr));
+    }
+
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+static int req_ecall_push(int *cme_err)
+{
+    ATResponse *response = NULL;
+    int err = at_send_command("AT*ECALLPUSH", &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT*ECALLONLY?
+*ECALLONLY: 0,0,18981911691,18981911691
+
+OK
+
+*/
+static int req_ecall_only_get(mbtk_ecall_only_info_t *only_info, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int tmp_int;
+    int err = at_send_command_singleline("AT*ECALLONLY?", "*ECALLONLY:", &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;
+    }
+    only_info->active = (mbtk_ecall_only_type_enum)tmp_int;
+
+    err = at_tok_nextint(&line, &tmp_int);
+    if (err < 0)
+    {
+        goto exit;
+    }
+    only_info->sim_type = (mbtk_ecall_sim_type_enum)tmp_int;
+
+    err = at_tok_nextstr(&line, &tmp_ptr);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    if(tmp_ptr && strlen(tmp_ptr) > 0) {
+        memcpy(only_info->test_num, tmp_ptr, strlen(tmp_ptr));
+    }
+
+    err = at_tok_nextstr(&line, &tmp_ptr);
+    if (err < 0)
+    {
+        goto exit;
+    }
+
+    if(tmp_ptr && strlen(tmp_ptr) > 0) {
+        memcpy(only_info->reconfig_num, tmp_ptr, strlen(tmp_ptr));
+    }
+
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT*ECALLONLY?
+*ECALLONLY: 0,0,18981911691,18981911691
+
+OK
+
+*/
+static int req_ecall_only_set(const mbtk_ecall_only_info_t *only_info, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[1024] = {0};
+    sprintf(cmd, "AT*ECALLONLY=%d,%s,%s", only_info->active,only_info->test_num,only_info->reconfig_num);
+    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*ECALLREG=0/1
+
+*/
+static int req_ecall_reg_set(uint8 reg, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[30] = {0};
+    sprintf(cmd, "AT*ECALLREG=%d", reg);
+    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+CECALL?
++CECALL: 4
+
+OK
+
+*/
+static int req_ecall_dial_state_get(mbtk_ecall_dial_type_enum *type, int *cme_err)
+{
+    ATResponse *response = NULL;
+    int tmp_int;
+    int err = at_send_command_singleline("AT+CECALL?", "+CECALL:", &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;
+    }
+    *type = (mbtk_ecall_dial_type_enum)tmp_int;
+
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT+CECALL=<ecalltype>
+OK
+*/
+static int req_ecall_dial_start(mbtk_ecall_dial_type_enum type, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[1024] = {0};
+    sprintf(cmd, "AT+CECALL=%d", type);
+    int err = at_send_command(cmd, &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+
+/*
+AT*ECALLMODE?
+*ECALLMODE: "ERA"
+
+OK
+
+*/
+static int req_ecall_mode_get(mbtk_ecall_mode_type_enum *mode, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT*ECALLMODE?", "*ECALLMODE:", &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;
+    }
+
+    if(tmp_ptr && strlen(tmp_ptr) > 0) {
+        if(strcmp(tmp_ptr, "ERA") == 0) {
+            *mode = MBTK_ECALL_MODE_TYPE_ERA;
+        } else {
+            *mode = MBTK_ECALL_MODE_TYPE_EU;
+        }
+
+        ecall_mode = *mode;
+    } else {
+        err =  -1;
+    }
+
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT*ECALLMODE="ERA"
+OK
+
+*/
+static int req_ecall_mode_set(mbtk_ecall_mode_type_enum mode, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[1024] = {0};
+    if(mode == MBTK_ECALL_MODE_TYPE_EU) {
+        sprintf(cmd, "AT*ECALLMODE=\"EU\"");
+    } else {
+        sprintf(cmd, "AT*ECALLMODE=\"ERA\"");
+    }
+    int err = at_send_command(cmd, &response);
+    if (err < 0 || response->success == 0){
+        *cme_err = at_get_cme_error(response);
+        goto exit;
+    }
+
+    ecall_mode = mode;
+
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT*ECALLDATA=5,2
+*ECALLDATA: 5,2,250
+
+OK
+
+AT*ECALLTIMER?
+*ECALLTIMER: ERA mode, callback timer: 1200s, dial setup timer: 30s, NAD deregister timer: 7200s, cleardown timer: 3600s, redial attempts count: 10, redial wait timer: 30s, smsprocess: 1, SMS resend timer: 3600s, sms msd send count: 10.
+
+OK
+
+*/
+static int req_ecall_cfg_get(mbtk_ecall_cfg_item_enum type, mbtk_ecall_cfg_info_t *cfg, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int tmp_int;
+    char cmd[1024] = {0};
+    int err = 0;
+
+    cfg->type = type;
+    switch(type)
+    {
+        case MBTK_ECALL_CFG_ITEM_T3:
+        case MBTK_ECALL_CFG_ITEM_T5:
+        case MBTK_ECALL_CFG_ITEM_T6:
+        case MBTK_ECALL_CFG_ITEM_T7:
+        case MBTK_ECALL_CFG_ITEM_TH:
+            snprintf(cmd, sizeof(cmd), "AT*ECALLDATA=5,%d", type);
+
+            err = at_send_command_singleline(cmd, "*ECALLDATA:", &response);
+            break;
+        default:
+            snprintf(cmd, sizeof(cmd), "AT*ECALLTIMER?");
+
+            err = at_send_command_singleline(cmd, "*ECALLTIMER:", &response);
+            break;
+    }
+
+    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;
+    }
+
+    if(strstr(cmd, "AT*ECALLDATA")) {
+        err = at_tok_nextint(&line, &tmp_int);
+        if (err < 0)
+        {
+            goto exit;
+        }
+
+        err = at_tok_nextint(&line, &tmp_int);
+        if (err < 0)
+        {
+            goto exit;
+        }
+
+        err = at_tok_nextint(&line, &tmp_int);
+        if (err < 0)
+        {
+            goto exit;
+        }
+
+        cfg->data = (uint32)(tmp_int * 20);   // ms
+    } else {
+        // *ECALLTIMER: ERA mode, callback timer: 1200s,
+        // dial setup timer: 30s, NAD deregister timer: 7200s,
+        // cleardown timer: 3600s, redial attempts count: 10,
+        // redial wait timer: 30s, smsprocess: 1, SMS resend timer: 3600s,
+        // sms msd send count: 10.
+
+        if(strstr(line, "ERA mode") != NULL) {
+            ecall_mode = MBTK_ECALL_MODE_TYPE_ERA;
+        } else {
+            ecall_mode = MBTK_ECALL_MODE_TYPE_EU;
+        }
+
+        switch(type)
+        {
+            case MBTK_ECALL_CFG_ITEM_TIMER_CALLBACK:
+            {
+                if((tmp_ptr = strstr(line, "callback timer: ")) != NULL) {
+                    cfg->data = (uint32)atoi(tmp_ptr + 16);   // s
+                    cfg->data *= 1000; // s -> ms
+                }
+                break;
+            }
+            case MBTK_ECALL_CFG_ITEM_TIMER_CLEARDOWN:
+            {
+                if((tmp_ptr = strstr(line, "cleardown timer: ")) != NULL) {
+                    cfg->data = (uint32)atoi(tmp_ptr + 17);   // s
+                    cfg->data *= 1000; // s -> ms
+                }
+                break;
+            }
+            case MBTK_ECALL_CFG_ITEM_TIMER_DEREG:
+            {
+                if((tmp_ptr = strstr(line, "deregister timer: ")) != NULL) {
+                    cfg->data = (uint32)atoi(tmp_ptr + 18);   // s
+                    cfg->data *= 1000; // s -> ms
+                }
+                break;
+            }
+            case MBTK_ECALL_CFG_ITEM_TIMER_DIAL:
+            {
+                if((tmp_ptr = strstr(line, "dial setup timer: ")) != NULL) {
+                    cfg->data = (uint32)atoi(tmp_ptr + 18);   // s
+                }
+                break;
+            }
+            case MBTK_ECALL_CFG_ITEM_TIMER_REDIAL:
+            {
+                if((tmp_ptr = strstr(line, "redial wait timer: ")) != NULL) {
+                    cfg->data = (uint32)atoi(tmp_ptr + 19);   // s
+                    cfg->data *= 1000; // s -> ms
+                }
+                break;
+            }
+            case MBTK_ECALL_CFG_ITEM_TIMER_SMS:
+            {
+                if((tmp_ptr = strstr(line, "SMS resend timer: ")) != NULL) {
+                    cfg->data = (uint32)atoi(tmp_ptr + 18);
+                    cfg->data *= 1000; // s -> ms
+                }
+                break;
+            }
+            case MBTK_ECALL_CFG_ITEM_REDIALCNT:
+            {
+                if((tmp_ptr = strstr(line, "redial attempts count: ")) != NULL) {
+                    cfg->data = (uint32)atoi(tmp_ptr + 23);
+                }
+                break;
+            }
+            case MBTK_ECALL_CFG_ITEM_SMSPROCESS:
+            {
+                if((tmp_ptr = strstr(line, "smsprocess: ")) != NULL) {
+                    cfg->data = (uint32)atoi(tmp_ptr + 12);
+                }
+                break;
+            }
+            case MBTK_ECALL_CFG_ITEM_SMSMSDCNT:
+            {
+                if((tmp_ptr = strstr(line, "sms msd send count: ")) != NULL) {
+                    cfg->data = (uint32)atoi(tmp_ptr + 20);
+                }
+                break;
+            }
+            default:
+                LOGE("Unknown config item : %d", type);
+                err = -1;
+                break;
+        }
+    }
+
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT*ECALLDATA=5,2,250
+OK
+
+AT*ECALLTIMER=dereg,300
+OK
+*/
+static int req_ecall_cfg_set(const mbtk_ecall_cfg_info_t *cfg_info, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[1024] = {0};
+    int err = 0;
+
+    if(ecall_mode == MBTK_ECALL_MODE_TYPE_EU) {
+        if(cfg_info->type != MBTK_ECALL_CFG_ITEM_TIMER_CALLBACK
+            && cfg_info->type != MBTK_ECALL_CFG_ITEM_TIMER_DIAL
+            && cfg_info->type != MBTK_ECALL_CFG_ITEM_TIMER_DEREG
+            && cfg_info->type != MBTK_ECALL_CFG_ITEM_TIMER_CLEARDOWN){
+            LOGW("No support for EU.");
+            return -1;
+        }
+    }
+
+    switch(cfg_info->type)
+    {
+        case MBTK_ECALL_CFG_ITEM_T3:
+        case MBTK_ECALL_CFG_ITEM_T5:
+        case MBTK_ECALL_CFG_ITEM_T6:
+        case MBTK_ECALL_CFG_ITEM_T7:
+        case MBTK_ECALL_CFG_ITEM_TH:
+            snprintf(cmd, sizeof(cmd), "AT*ECALLDATA=5,%d,%d", cfg_info->type, cfg_info->data / 20);
+            break;
+        case MBTK_ECALL_CFG_ITEM_TIMER_CALLBACK:
+        {
+            snprintf(cmd, sizeof(cmd), "AT*ECALLTIMER=callback,%d", cfg_info->data / 1000);
+            break;
+        }
+        case MBTK_ECALL_CFG_ITEM_TIMER_CLEARDOWN:
+        {
+            snprintf(cmd, sizeof(cmd), "AT*ECALLTIMER=cleardown,%d", cfg_info->data / 1000);
+            break;
+        }
+        case MBTK_ECALL_CFG_ITEM_TIMER_DEREG:
+        {
+            snprintf(cmd, sizeof(cmd), "AT*ECALLTIMER=dereg,%d", cfg_info->data / 1000);
+            break;
+        }
+        case MBTK_ECALL_CFG_ITEM_TIMER_DIAL:
+        {
+            snprintf(cmd, sizeof(cmd), "AT*ECALLTIMER=dial,%d", cfg_info->data / 1000);
+            break;
+        }
+        case MBTK_ECALL_CFG_ITEM_TIMER_REDIAL:
+        {
+            snprintf(cmd, sizeof(cmd), "AT*ECALLTIMER=redialtmr,%d", cfg_info->data / 1000);
+            break;
+        }
+        case MBTK_ECALL_CFG_ITEM_TIMER_SMS:
+        {
+            snprintf(cmd, sizeof(cmd), "AT*ECALLTIMER=sms,%d", cfg_info->data / 1000);
+            break;
+        }
+        case MBTK_ECALL_CFG_ITEM_REDIALCNT:
+        {
+            snprintf(cmd, sizeof(cmd), "AT*ECALLTIMER=redialcnt,%d", cfg_info->data);
+            break;
+        }
+        case MBTK_ECALL_CFG_ITEM_SMSPROCESS:
+        {
+            snprintf(cmd, sizeof(cmd), "AT*ECALLTIMER=smsprocess,%d", cfg_info->data);
+            break;
+        }
+        case MBTK_ECALL_CFG_ITEM_SMSMSDCNT:
+        {
+            snprintf(cmd, sizeof(cmd), "AT*ECALLTIMER=smsmsdcnt,%d", cfg_info->data);
+            break;
+        }
+        default:
+            LOGE("Unknown config item : %d", cfg_info->type);
+            err = -1;
+            goto exit;
+    }
+
+    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*ECALLMUTESPK=1
+OK
+
+*/
+static int req_ecall_spkmute_set(int mute, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[100] = {0};
+    sprintf(cmd, "AT*ECALLMUTESPK=%d", mute);
+    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*ECALLSMSNUM?
+*ECALLSMSNUM: "18981991452"
+
+OK
+
+*/
+static int req_ecall_sms_num_get(uint8 *number, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char *tmp_ptr = NULL;
+    int err = at_send_command_singleline("AT*ECALLSMSNUM?", "*ECALLSMSNUM:", &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;
+    }
+
+    if(tmp_ptr && strlen(tmp_ptr) > 0) {
+        memcpy(number, tmp_ptr, strlen(tmp_ptr));
+    }
+
+    goto exit;
+exit:
+    at_response_free(response);
+    return err;
+}
+
+/*
+AT*ECALLSMSNUM=18981991452
+OK
+
+*/
+static int req_ecall_sms_num_set(const uint8 *number, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[100] = {0};
+    sprintf(cmd, "AT*ECALLSMSNUM=%s", 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*AUDGAIN=8,1 // Set Rx voice gain = 8dB
+OK
+
+*/
+static int req_ecall_gain_set(mbtk_ecall_gain_info_t *gain, int *cme_err)
+{
+    ATResponse *response = NULL;
+    char cmd[100] = {0};
+    sprintf(cmd, "AT*AUDGAIN=%d,%d", gain->gain, gain->mode);
+    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 ecall_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_ECALL_MSDCFG:       // mbtk_ecall_msd_cfg_info_t
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set
+            {
+                mbtk_ecall_msd_cfg_info_t *cfg_info = (mbtk_ecall_msd_cfg_info_t*)(pack->data);
+                if(req_ecall_msdcfg(cfg_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("AT*ECALLMSDCFG fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_ECALL_MSDGEN:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                if(req_ecall_msdgen(&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("AT*ECALLMSDGEN fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            break;
+        }
+        case RIL_MSG_ID_ECALL_MSD: // uint8[]
+        {
+            uint8 msd[MBTK_ECALL_MSD_LEN_MAX];
+            memset(msd, 0, sizeof(msd));
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                if(req_ecall_msd_get(msd, &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 MSD fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, msd, strlen(msd));
+                }
+            }
+            else     // Set
+            {
+                memcpy(msd, pack->data, pack->data_len);
+                if(req_ecall_msd_set(msd, &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("AT*ECALLMSD fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_ECALL_PUSH:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                if(req_ecall_push(&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("AT*ECALLPUSH fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            else     // Set
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            break;
+        }
+        case RIL_MSG_ID_ECALL_ONLY:     // mbtk_ecall_only_info_t
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_ecall_only_info_t only_info;
+                memset(&only_info, 0, sizeof(mbtk_ecall_only_info_t));
+                if(req_ecall_only_get(&only_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 ecall only mode fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &only_info, sizeof(mbtk_ecall_only_info_t));
+                }
+            }
+            else     // Set
+            {
+                mbtk_ecall_only_info_t *only_info = (mbtk_ecall_only_info_t*)(pack->data);
+                if(req_ecall_only_set(only_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("AT*ECALLONLY fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_ECALL_REG:  // reg <uint8>
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else
+            {
+                uint8 reg = pack->data[0];
+                if(req_ecall_reg_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("ecall reg(%d) fail.", reg);
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_ECALL_DIAL: // mbtk_ecall_dial_type_enum
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_ecall_dial_type_enum type;
+                if(req_ecall_dial_state_get(&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 ecall type fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &type, sizeof(uint8));
+                }
+            }
+            else
+            {
+                mbtk_ecall_dial_type_enum type = (mbtk_ecall_dial_type_enum)pack->data[0];
+                if(req_ecall_dial_start(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("Start ecall %d fail.", type);
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_ECALL_MODE:  // mbtk_ecall_cfg_item_enum / mbtk_ecall_cfg_info_t
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                mbtk_ecall_mode_type_enum mode;
+                if(req_ecall_mode_get(&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("Get ecall mode fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &mode, sizeof(uint8));
+                }
+            }
+            else
+            {
+                mbtk_ecall_mode_type_enum mode = (mbtk_ecall_mode_type_enum)pack->data[0];
+                if(req_ecall_mode_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 ecall mode %d fail.", mode);
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_ECALL_CFG:  // mbtk_ecall_cfg_item_enum / mbtk_ecall_cfg_info_t
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else
+            {
+                if(pack->data_len == sizeof(mbtk_ecall_cfg_info_t)) { // Set
+                    mbtk_ecall_cfg_info_t *cfg_info = (mbtk_ecall_cfg_info_t*)pack->data;
+                    if(req_ecall_cfg_set(cfg_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 ecall config[%d] fail.", cfg_info->type);
+                    }
+                    else
+                    {
+                        ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                    }
+                } else { // Get
+                    mbtk_ecall_cfg_info_t cfg_info;
+                    memset(&cfg_info, 0, sizeof(mbtk_ecall_cfg_info_t));
+                    mbtk_ecall_cfg_item_enum type = (mbtk_ecall_cfg_item_enum)pack->data[0];
+                    if(req_ecall_cfg_get(type, &cfg_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 ecall config[%d] fail.", type);
+                    }
+                    else
+                    {
+                        ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, &cfg_info, sizeof(mbtk_ecall_cfg_info_t));
+                    }
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_ECALL_SMS_NUM: // uint8[]
+        {
+            uint8 number[RIL_MAX_NUMBER_LEN];
+            memset(number, 0, sizeof(number));
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                if(req_ecall_sms_num_get(number, &cme_err) || strlen(number) == 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 ecall sms number fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, number, strlen(number));
+                }
+            }
+            else     // Set
+            {
+                memcpy(number, pack->data, pack->data_len);
+                if(req_ecall_sms_num_set(number, &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 ecall sms number fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_ECALL_MUTESPK:
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set mute state.
+            {
+                uint8 mute = pack->data[0];
+                if(pack->data_len != sizeof(uint8) || (mute != 0 && mute != 1))
+                {
+                    err = MBTK_RIL_ERR_REQ_PARAMETER;
+                    LOG("Set spk mute parameter error.");
+                    break;
+                }
+
+                if(req_ecall_spkmute_set(mute, &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 spk mute state fail.");
+                }
+                else
+                {
+                    ril_rsp_pack_send(cli_info->fd, pack->msg_id, pack->msg_index, NULL, 0);
+                }
+            }
+            break;
+        }
+        case RIL_MSG_ID_ECALL_DSP_GAIN: // mbtk_ecall_gain_info_t
+        {
+            if(pack->data_len == 0 || pack->data == NULL)
+            {
+                err = MBTK_RIL_ERR_UNSUPPORTED;
+            }
+            else     // Set
+            {
+                mbtk_ecall_gain_info_t *gain_info = (mbtk_ecall_gain_info_t *)pack->data;
+                if(req_ecall_gain_set(gain_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;
+                    }
+                    LOGE("Set ecall gain 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_net.c b/mbtk/mbtk_rild_v2/src/ril_net.c
index 6ca5d65..16d3118 100755
--- a/mbtk/mbtk_rild_v2/src/ril_net.c
+++ b/mbtk/mbtk_rild_v2/src/ril_net.c
@@ -21,523 +21,9 @@
 #include "mbtk_str.h"
 
 mbtk_cell_pack_info_t cell_info;
-ril_cgact_wait_t cgact_wait;
 
 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(bool get_def_cid, 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(mbtk_apn_info_array_t *apns);
-
-static int apn_file_save(const char *file, char *data, int data_len)
-{
-    if(!file) {
-        return -1;
-    }
-
-    if(str_empty(data) || data_len <= 0) { // Delete file
-        return unlink(file);
-    } else {
-        int fd = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0644);
-        if(fd < 0) {
-            LOGE("open(%s) fail:%d", file, errno);
-            return -1;
-        }
-
-        if(write(fd, data, data_len) != data_len) {
-            LOGE("write fail:%d", errno);
-            close(fd);
-            return -1;
-        }
-        close(fd);
-        return 0;
-    }
-}
-
-static int apn_file_read(const char *file, char *data, int data_len)
-{
-    if(!file) {
-        LOGE("file is null");
-        return -1;
-    }
-
-    if(data == NULL || data_len <= 100) {
-        LOGE("apn_file_read() arg error.");
-        return -1;
-    } else {
-        int len = -1;
-        int fd = open(file, O_RDONLY, 0644);
-        if(fd < 0) {
-            LOGE("open(%s) fail:%d", file, errno);
-            return -1;
-        }
-
-        memset(data, 0, data_len);
-        if((len = read(fd, data, data_len)) < 0) {
-            LOGE("read fail:%d", errno);
-            close(fd);
-            return -1;
-        }
-        close(fd);
-        return len;
-    }
-}
-
-
-void apn_auto_conf_from_prop()
-{
-    mbtk_apn_info_array_t apns;
-    int i = 0;
-    memset(&apns, 0, sizeof(mbtk_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_check_and_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;
-
-        // The cid no use,so can not delete.
-        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(FALSE, &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 { // Add or change APN.
-        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(TRUE, &apns, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
-        {
-            LOGW("Get APN fail.");
-            if(apn->cid == MBTK_RIL_CID_NUL) {
-                apn->cid = start_cid;
-            }
-        }
-        else
-        {
-            int index = 0;
-            bool is_change = FALSE;  // Is add APN default.
-
-            if(apn->cid == MBTK_RIL_CID_NUL) { // Is add (auto set cid).
-                for(; start_cid <= MBTK_APN_CID_MAX; start_cid++) {
-                    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;
-                        break;
-                    }
-                }
-
-                if(start_cid > MBTK_APN_CID_MAX) {
-                    LOGE("APN full.");
-                    return -1;
-                }
-                is_change = FALSE;
-            } else {
-                index = 0;
-                while(index < apns.num) {
-                    if(apns.apns[index].cid == apn->cid) {
-                        is_change = TRUE;
-                        break;
-                    }
-                    index++;
-                }
-            }
-
-            // Is add,the APN can't same.
-            if(!is_change) {
-                index = 0;
-                while(index < apns.num) {
-                    if(strcmp(apns.apns[index].apn,apn->apn) == 0) {
-                        LOGW("APN : %s exist.", apn->apn);
-                        return -1;
-                    }
-                    index++;
-                }
-            }
-        }
-    }
-    return 0;
-}
-
-static void apn_prop_get(mbtk_apn_info_array_t *apns)
-{
-    char prop_name[128] = {0};
-    char prop_data[1024] = {0};
-    int cid;
-    memset(apns, 0, sizeof(mbtk_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;
-        //apns->cid_for_def_dns = MBTK_RIL_CID_DEF;
-        cid = MBTK_RIL_CID_2;
-    } else {
-        cid = MBTK_APN_CID_MIN;
-    }
-
-    char def_cid[10] = {0};
-    sprintf(def_cid, "%d", MBTK_RIL_CID_DEF);
-    if(property_get(MBTK_DEF_ROUTE_CID, prop_data, def_cid) > 0 && !str_empty(prop_data)) {
-        apns->cid_for_def_route = (mbtk_ril_cid_enum)atoi(prop_data);
-    }
-    memset(prop_data, 0, sizeof(prop_data));
-    if(property_get(MBTK_DEF_DNS_CID, prop_data, def_cid) > 0 && !str_empty(prop_data)) {
-        apns->cid_for_def_dns = (mbtk_ril_cid_enum)atoi(prop_data);
-    }
-
-    for(; cid <= MBTK_APN_CID_MAX; cid++) {
-        memset(prop_name, 0, sizeof(prop_name));
-        memset(prop_data, 0, sizeof(prop_data));
-
-        sprintf(prop_name, "%s_%d",MBTK_APN_PROP,cid);
-        // ip_type,auth,auto_data_call,apn,user,pass
-#if 0
-        if(property_get(prop_name, prop_data, "") > 0 && !str_empty(prop_data)) {
-#else
-        if(apn_file_read(prop_name, prop_data, sizeof(prop_data)) > 0 && !str_empty(prop_data)) {
-#endif
-            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
-            ptr_2 = strstr(ptr_1, ",");
-            if(!ptr_2) {
-                continue;
-            }
-            if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
-                memcpy(apns->apns[apns->num].pass, ptr_1, ptr_2 - ptr_1); // pass
-            }
-
-            ptr_2++; // Jump ',' to type
-            if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
-                memcpy(apns->apns[apns->num].type, ptr_2, strlen(ptr_2)); // type
-            }
-
-            apns->num++;
-        }
-    }
-}
-
-static int apn_prop_get_by_cid(mbtk_ril_cid_enum cid, mbtk_apn_info_t *apn)
-{
-    char prop_name[128] = {0};
-    char prop_data[1024] = {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 0
-    if(property_get(prop_name, prop_data, "") > 0 && !str_empty(prop_data)) {
-#else
-    if(apn_file_read(prop_name, prop_data, sizeof(prop_data)) > 0 && !str_empty(prop_data)) {
-#endif
-        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
-        ptr_2 = strstr(ptr_1, ",");
-        if(!ptr_2) {
-            return -1;
-        }
-        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
-            memcpy(apn->user, ptr_1, ptr_2 - ptr_1); // pass
-        }
-
-        ptr_2++; // Jump ',' to type
-        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
-            memcpy(apn->type, ptr_2, strlen(ptr_2)); // pass
-        }
-        return 0;
-    }
-    return -1;
-}
-
-static int apn_prop_get_by_cid_without_cgdcont(mbtk_ril_cid_enum cid, mbtk_apn_info_t *apn)
-{
-    char prop_name[128] = {0};
-    char prop_data[1024] = {0};
-
-    sprintf(prop_name, "%s_%d",MBTK_APN_PROP,cid);
-    // ip_type,auth,auto_data_call,apn,user,pass
-#if 0
-    if(property_get(prop_name, prop_data, "") > 0 && !str_empty(prop_data)) {
-#else
-    if(apn_file_read(prop_name, prop_data, sizeof(prop_data)) > 0 && !str_empty(prop_data)) {
-#endif
-        LOGD("APN : %s", prop_data);
-        char *ptr_1 = prop_data;
-        apn->auto_save = (uint8)1;
-        //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 0
-        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
-            memcpy(apn->apn, ptr_1, ptr_2 - ptr_1); // apn
-        }
-#endif
-
-        ptr_2++; // Jump ',' to user
-        ptr_1 = strstr(ptr_2, ",");
-        if(!ptr_1) {
-            return -1;
-        }
-        if(memcmp(ptr_2, "NULL", 4)) { // Not "NULL"
-            memcpy(apn->user, ptr_2, ptr_1 - ptr_2); // user
-        }
-
-        ptr_1++; // Jump ',' to pass
-        ptr_2 = strstr(ptr_1, ",");
-        if(!ptr_2) {
-            return -1;
-        }
-        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
-            memcpy(apn->user, ptr_1, ptr_2 - ptr_1); // pass
-        }
-
-        ptr_2++; // Jump ',' to type
-        if(memcmp(ptr_1, "NULL", 4)) { // Not "NULL"
-            memcpy(apn->type, ptr_2, strlen(ptr_2)); // pass
-        }
-        return 0;
-    } else {
-        apn->auto_save = (uint8)0;
-    }
-    return -1;
-}
-
-static int apn_prop_set(mbtk_apn_info_t *apn)
-{
-    char prop_name[20] = {0};
-    char prop_data[1024] = {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, 1024, "%d,%d,%d,%s,%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,
-                str_empty(apn->pass) ? "NULL" : apn->type);
-        }
-
-#if 0
-        ret = property_set(prop_name, prop_data);
-#else
-        if(str_empty(apn->apn)) { // Delete APN
-            ret = apn_file_save(prop_name, NULL, 0);
-        } else {
-            ret = apn_file_save(prop_name, prop_data, strlen(prop_data));
-        }
-#endif
-    }
-
-    if(!ret && 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);
-    }
-    if(!ret && apn->as_dns) {
-        memset(prop_data, 0, sizeof(prop_data));
-        prop_data[0] = '0' + apn->cid;
-        ret = property_set(MBTK_DEF_DNS_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;
-        apn.as_dns = data_info->as_dns;
-        return apn_prop_set(&apn);
-    }
-}
-
-static int wait_cgact_complete(int timeout)
-{
-    int count = timeout * 10; // timeout * 1000 / 100
-    int i = 0;
-
-    while(cgact_wait.waitting && i < count) {
-        i++;
-        usleep(100000); // 100ms
-    }
-
-    memset(&cgact_wait, 0, sizeof(ril_cgact_wait_t));
-    if(i == count) { // Timeout
-        return -1;
-    } else {
-        return 0;
-    }
-}
 
 /*
 AT+COPS=?
@@ -1701,428 +1187,6 @@
     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(bool get_def_cid, 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;
-    int cid_start;
-    if(apn_conf_support(MBTK_RIL_CID_DEF)) {
-        cid_start = MBTK_RIL_CID_DEF;
-    } else {
-        if(get_def_cid) {
-            cid_start = MBTK_RIL_CID_DEF;
-        } else {
-            cid_start = MBTK_RIL_CID_2;
-        }
-    }
-    /*
-    <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 >= cid_start && 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));
-            }
-
-            // Get other arg from proc or file.
-            apn_prop_get_by_cid_without_cgdcont(apns->apns[apns->num].cid, &(apns->apns[apns->num]));
-
-            apns->num++;
-        }
-
-        lines_ptr = lines_ptr->p_next;
-    }
-
-    char prop_name[128] = {0};
-    char prop_data[1024] = {0};
-    char def_cid[10] = {0};
-    sprintf(def_cid, "%d", MBTK_RIL_CID_DEF);
-
-    if(property_get(MBTK_DEF_ROUTE_CID, prop_data, def_cid) > 0 && !str_empty(prop_data)) {
-        apns->cid_for_def_route = (mbtk_ril_cid_enum)atoi(prop_data);
-    }
-    memset(prop_data, 0, sizeof(prop_data));
-    if(property_get(MBTK_DEF_DNS_CID, prop_data, def_cid) > 0 && !str_empty(prop_data)) {
-        apns->cid_for_def_dns = (mbtk_ril_cid_enum)atoi(prop_data);
-    }
-
-    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, bool as_dns,
-                int retry_interval, int timeout, int *cme_err)
-{
-    ATResponse *response = NULL;
-    char cmd[400] = {0};
-    int err = 0;
-    memset(&cgact_wait, 0, sizeof(ril_cgact_wait_t));
-    cgact_wait.waitting = true;
-    cgact_wait.cid = cid;
-    cgact_wait.act = true;
-
-    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;
-
-    memset(&cgact_wait, 0, sizeof(ril_cgact_wait_t));
-    cgact_wait.waitting = true;
-    cgact_wait.cid = cid;
-    cgact_wait.act = false;
-
-    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().
@@ -2346,169 +1410,6 @@
             }
             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(FALSE, &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_check_and_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(!apn_conf_support(call_info->cid)) {
-                    err = MBTK_RIL_ERR_UNSUPPORTED;
-                    LOGD("Can not data call for CID : %d", call_info->cid);
-                } else {
-                    if(call_info->type == MBTK_DATA_CALL_START) {
-                        mbtk_ip_info_t ip_info;
-                        memset(&ip_info, 0, sizeof(ip_info));
-#if 0
-                        if(apn_prop_reset(call_info)) {
-                            err = MBTK_RIL_ERR_REQ_UNKNOWN;
-                            LOG("apn_prop_reset() fail.");
-                        } else
-#else
-                        if(apn_prop_reset(call_info)) {
-                            LOG("apn_prop_reset() fail.");
-                        }
-#endif
-                        {
-                            if(req_data_call_start(call_info->cid, call_info->def_route, call_info->as_dns,
-                                    call_info->retry_interval, 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("Start data call fail.");
-                            }
-                            else
-                            {
-                                // Wait for "CONNECT" or "+CGEV:"
-                                if(wait_cgact_complete(call_info->timeout)) { // Timeout
-                                    err = MBTK_RIL_ERR_TIMEOUT;
-                                    break;
-                                }
-
-                                // Get Ip informations.
-                                cme_err = MBTK_RIL_ERR_CME_NON;
-                                if(req_data_call_state_get(call_info->cid ,&ip_info, &cme_err) || cme_err != MBTK_RIL_ERR_CME_NON)
-                                {
-                                    LOGD("Get net informations fail.");
-                                    err = MBTK_RIL_ERR_NET_CONF;
-                                }
-                                else
-                                {
-                                    // Config network informations.
-                                    if(net_ifc_reconfig(call_info->cid, call_info->def_route, call_info->as_dns, &ip_info)) {
-                                        err = MBTK_RIL_ERR_NET_CONF;
-                                        break;
-                                    }
-
-                                    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
-                        {
-                            // Wait for "CONNECT" or "+CGEV:"
-                            if(wait_cgact_complete(call_info->timeout)) { // Timeout
-                                err = MBTK_RIL_ERR_TIMEOUT;
-                                break;
-                            }
-
-                            // Clean network config.
-                            if(net_ifc_config(call_info->cid, FALSE, FALSE, NULL)) {
-                                err = MBTK_RIL_ERR_NET_CONF;
-                                break;
-                            }
-
-                            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;
diff --git a/mbtk/test/libmbtk_ecall/mbtk_ecall_test_v2.c b/mbtk/test/libmbtk_ecall/mbtk_ecall_test_v2.c
new file mode 100755
index 0000000..6f8149a
--- /dev/null
+++ b/mbtk/test/libmbtk_ecall/mbtk_ecall_test_v2.c
@@ -0,0 +1,424 @@
+#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("msdcfg <item> <value>: Set MSD item value.\n");
+    printf("msdgen: Generate MSD by items.\n");
+    printf("msd <MSD>: Get/Set MSD.\n");
+    printf("msdpush: PUSH MSD.\n");
+    printf("only <0-5> <test_num> <reconfig_num>: Get/Set ecall only mode.\n");
+    printf("reg 0/1: Set ecall reg mode.\n");
+    printf("dial <0-5>: Get/Start ecall dial.\n");
+    printf("mode EU/ERA: Get/Set ecall mode\n");
+    printf("cfg <type> <value>: Get/Set ecall config item.\n");
+    printf("sms_num <number>: Get/Set sms number.\n");
+    printf("mute_spk <0/1>: Set spk mute or not.\n");
+    printf("gain <0/1/2> <gain>: Set ecall DSP gain.\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 ecall_state_change_cb(const void* data, int data_len)
+{
+    if(data)
+    {
+        mbtk_ril_ecall_state_info_t *ecall_data = (mbtk_ril_ecall_state_info_t*)data;
+        printf("ecall state change : urc_id - %d, urc_data - %s\n", ecall_data->urc_id, ecall_data->urc_data);
+    }
+}
+
+
+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","ECALL_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;
+    }
+
+    mbtk_ecall_state_change_cb_reg(ecall_state_change_cb);
+
+    printf(">>>>>>>>>>>>>>>>>>>>>>>>Enter cmd:\n");
+    char cmd[1024];
+    while(1)
+    {
+        memset(cmd, 0, sizeof(cmd));
+        mbtk_ril_err_enum err;
+        if(fgets(cmd, sizeof(cmd), stdin))
+        {
+            char *ptr = cmd + strlen(cmd) - 1;
+            while(ptr >= cmd && (*ptr == '\r' || *ptr == '\n'))
+            {
+                *ptr-- = '\0';
+            }
+
+            if(!strncasecmp(cmd, "msdcfg", 6)) // msdcfg <item> <value>
+            {
+                mbtk_ecall_msd_cfg_info_t cfg;
+                memset(&cfg, 0, sizeof(mbtk_ecall_msd_cfg_info_t));
+                int item;
+                int count = sscanf(cmd, "msdcfg %d %s", &item, cfg.data);
+                if(count == 2 && strlen(cfg.data) > 0) {
+                    cfg.item_type = (mbtk_ecall_msd_item_enum)item;
+                    err = mbtk_ecall_msd_item_set(&cfg);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("MSD item set success\n");
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "msdgen", 6)){
+                err = mbtk_ecall_msd_gen();
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("MSD gen success\n");
+                }
+            } else if(!strncasecmp(cmd, "msdpush", 7)){
+                err = mbtk_ecall_push();
+                if(err != MBTK_RIL_ERR_SUCCESS) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("MSD PUSH success\n");
+                }
+            } else if(!strncasecmp(cmd, "msd", 3)){ // msd <MSD>
+                uint8 msd[500] = {0};
+                if(!strcasecmp(cmd, "msd")) { // Get
+                    err = mbtk_ecall_msd_get(msd);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("MSD : %s\n", msd);
+                    }
+                } else { // Set
+                    int count = sscanf(cmd, "msd %s", msd);
+                    if(count == 1 && strlen(msd) > 0) { // set
+                        err = mbtk_ecall_msd_set(msd);
+                        if(err != MBTK_RIL_ERR_SUCCESS) {
+                            printf("Error : %d\n", err);
+                        } else {
+                            printf("MSD set success\n");
+                        }
+                    }
+                }
+            } else if(!strncasecmp(cmd, "only", 4)){ // only <0-5> <test_num> <reconfig_num>
+                mbtk_ecall_only_info_t only_info;
+                if(strcasecmp(cmd, "only") == 0) { // Get
+                    memset(&only_info, 0, sizeof(mbtk_ecall_only_info_t));
+                    err = mbtk_ecall_only_get(&only_info);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Only : active-%d,sim_type-%d,test_num-%s,reconfig_num-%s\n", only_info.active, only_info.sim_type, only_info.test_num, only_info.reconfig_num);
+                    }
+                } else { // Set
+                    memset(&only_info, 0, sizeof(mbtk_ecall_only_info_t));
+                    int tmp_int = -1;
+                    int count = sscanf(cmd, "only %d %s %s", &tmp_int, only_info.test_num, only_info.reconfig_num);
+                    if(count > 0 && tmp_int >= 0) { // set
+                        only_info.active = (mbtk_ecall_only_type_enum)tmp_int;
+                        err = mbtk_ecall_only_set(&only_info);
+                        if(err != MBTK_RIL_ERR_SUCCESS) {
+                            printf("Error : %d\n", err);
+                        } else {
+                            printf("MSD set success\n");
+                        }
+                    }
+                }
+            } else if(!strncasecmp(cmd, "dial", 4)){ // dial <0-5>
+                mbtk_ecall_dial_type_enum type;
+                if(!strcasecmp(cmd, "dial")) { // Get
+                    err = mbtk_ecall_dial_state_get(&type);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Type : %d\n", type);
+                    }
+                } else { // Set
+                    int reset;
+                    int count = sscanf(cmd, "dial %d", &reset);
+                    if(count == 1) {
+                        err = mbtk_ecall_dial_start((mbtk_ecall_dial_type_enum)reset);
+                        if(err != MBTK_RIL_ERR_SUCCESS) {
+                            printf("Error : %d\n", err);
+                        } else {
+                            printf("Start ecall dial success\n");
+                        }
+                    }
+                }
+            } else if(!strncasecmp(cmd, "reg", 3)){ // reg <0/1>
+                if(!strcasecmp(cmd, "reg 0")) {
+                    err = mbtk_ecall_reg_set(0);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Set net reg 0\n");
+                    }
+                } else if(!strcasecmp(cmd, "reg 1")) {
+                    err = mbtk_ecall_reg_set(1);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Set net reg 1\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "mode", 4)){ // mode EU/ERA
+                if(!strcasecmp(cmd, "mode")) {
+                    mbtk_ecall_mode_type_enum mode;
+                    err = mbtk_ecall_mode_get(&mode);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Ecall mode[%d] : %s\n", mode, mode == MBTK_ECALL_MODE_TYPE_EU ? "EU" : "ERA");
+                    }
+                } else if(!strcasecmp(cmd, "mode EU")) {
+                    err = mbtk_ecall_mode_set(MBTK_ECALL_MODE_TYPE_EU);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Set mode EU\n");
+                    }
+                } else if(!strcasecmp(cmd, "mode ERA")) {
+                    err = mbtk_ecall_mode_set(MBTK_ECALL_MODE_TYPE_ERA);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Set mode ERA\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "cfg", 3)){ // cfg <type> <value>
+                int tmp1 = -1, tmp2 = -1;
+                int count = sscanf(cmd, "cfg %d %d", &tmp1, &tmp2);
+                mbtk_ecall_cfg_info_t cfg;
+                if(count == 1 && tmp1 >= 0) { // Get
+                    memset(&cfg, 0, sizeof(cfg));
+                    cfg.type = (mbtk_ecall_cfg_item_enum)tmp1;
+                    err = mbtk_ecall_cfg_get(&cfg);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Ecall config[%d] is %d\n", cfg.type, cfg.data);
+                    }
+                } else if(count == 2 && tmp1 >= 0 && tmp2 >= 0) { // Set
+                    memset(&cfg, 0, sizeof(cfg));
+                    cfg.type = (mbtk_ecall_cfg_item_enum)tmp1;
+                    cfg.data = (uint32)tmp2;
+                    err = mbtk_ecall_cfg_set(&cfg);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Set ecall config[%d] to %d success\n", cfg.type, cfg.data);
+                    }
+                }
+            } else if(!strncasecmp(cmd, "sms_num", 7)){ // sms_num <number>
+                uint8 number[RIL_MAX_NUMBER_LEN] = {0};
+                if(!strcasecmp(cmd, "sms_num")) { // Get
+                    err = mbtk_ecall_sms_number_get(number);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("SMS number : %s\n", number);
+                    }
+                } else { // Set
+                    int count = sscanf(cmd, "sms_num %s", number);
+                    if(count == 1 && strlen(number) > 0) {
+                        err = mbtk_ecall_sms_number_set(number);
+                        if(err != MBTK_RIL_ERR_SUCCESS) {
+                            printf("Error : %d\n", err);
+                        } else {
+                            printf("Set SMS number[%s] success\n", number);
+                        }
+                    }
+                }
+            } else if(!strncasecmp(cmd, "mute_spk", 8)){ // mute_spk <0/1>
+                if(!strcasecmp(cmd, "mute_spk 0")) {
+                    err = mbtk_ecall_mute_spk_set(0);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Set mute spk to 0\n");
+                    }
+                } else if(!strcasecmp(cmd, "mute_spk 1")) {
+                    err = mbtk_ecall_mute_spk_set(1);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Set mute spk to 1\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "gain", 4)){    // gain <0/1/2> <gain>
+                int tmp1 = -1, tmp2 = -1;
+                int count = sscanf(cmd, "gain %d %d", &tmp1, &tmp2);
+                mbtk_ecall_gain_info_t gain;
+                if(count == 2 && tmp1 >= 0) { // Get
+                    memset(&gain, 0, sizeof(gain));
+                    gain.mode = (mbtk_ecall_gain_mode_enum)tmp1;
+                    gain.gain = (int8)tmp2;
+                    err = mbtk_ecall_dsp_gain_set(&gain);
+                    if(err != MBTK_RIL_ERR_SUCCESS) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Set DSP gain[%d] to %d\n", gain.mode, gain.gain);
+                    }
+                }
+            }
+            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;
+}
+
diff --git a/mbtk/test/libmbtk_ril/mbtk_ril_test.c b/mbtk/test/libmbtk_ril/mbtk_ril_test.c
index acc9266..dc0c65d 100755
--- a/mbtk/test/libmbtk_ril/mbtk_ril_test.c
+++ b/mbtk/test/libmbtk_ril/mbtk_ril_test.c
@@ -102,6 +102,78 @@
     }
 }
 
+static void ril_ser_state_change_cb(const void* data, int data_len)
+{
+    if(data) {
+        uint8 *ptr = (const char*)data;
+        mbtk_ril_ser_state_enum state = (mbtk_ril_ser_state_enum)ptr[0];
+        printf("ril server state : %d.\n", state);
+    }
+}
+
+static void net_reg_state_change_cb(const void* data, int data_len)
+{
+    if(data) {
+        mbtk_ril_net_reg_state_info_t *state = (mbtk_ril_net_reg_state_info_t*)data;
+        printf("net reg state change : type - %d, tech - %d, reg_state - %d\n", state->type,
+            state->tech, state->reg_state);
+    }
+}
+
+static void call_state_change_cb(const void* data, int data_len)
+{
+    if(data) {
+        mbtk_ril_call_state_info_t *state = (mbtk_ril_call_state_info_t*)data;
+        printf("call state change : call_id-%d, dir-%d, state-%d, num_type-%d,number-%s\n", state->call_id,
+            state->dir, state->state, state->num_type, state->call_number);
+    }
+}
+
+static void sms_state_change_cb(const void* data, int data_len)
+{
+
+}
+
+static void radio_state_change_cb(const void* data, int data_len)
+{
+    if(data) {
+        mbtk_ril_radio_state_info_t *state = (mbtk_ril_radio_state_info_t*)data;
+        printf("radio state change : %d\n", state->radio_state);
+    }
+}
+
+static void sim_state_change_cb(const void* data, int data_len)
+{
+    if(data) {
+        mbtk_ril_sim_state_info_t *state = (mbtk_ril_sim_state_info_t*)data;
+        printf("sim state change : type - %d, state - %d\n", state->sim_type, state->sim_state);
+    }
+}
+
+static void pdp_state_change_cb(const void* data, int data_len)
+{
+    if(data) {
+        mbtk_ril_pdp_state_info_t *state = (mbtk_ril_pdp_state_info_t*)data;
+        printf("pdp state change : cid - %d, action - %d, reason-%d, auto_change - %d\n",
+            state->cid, state->action, state->reason, state->auto_change);
+    }
+}
+
+static void signal_state_change_cb(const void* data, int data_len)
+{
+
+}
+
+static void ecall_state_change_cb(const void* data, int data_len)
+{
+    if(data)
+    {
+        mbtk_ril_ecall_state_info_t *ecall_data = (mbtk_ril_ecall_state_info_t*)data;
+        printf("ecall state change : urc_id - %d, urc_data - %s\n", ecall_data->urc_id, ecall_data->urc_data);
+    }
+}
+
+
 static void sig_process(int sig)
 {
     LOGI("I got signal %d\n", sig);
@@ -208,6 +280,24 @@
         return -1;
     }
 
+    mbtk_ril_ser_state_change_cb_reg(ril_ser_state_change_cb);
+
+    mbtk_net_reg_state_change_cb_reg(net_reg_state_change_cb);
+
+    mbtk_call_state_change_cb_reg(call_state_change_cb);
+
+    mbtk_sms_state_change_cb_reg(sms_state_change_cb);
+
+    mbtk_radio_state_change_cb_reg(radio_state_change_cb);
+
+    mbtk_sim_state_change_cb_reg(sim_state_change_cb);
+
+    mbtk_pdp_state_change_cb_reg(pdp_state_change_cb);
+
+    mbtk_signal_state_change_cb_reg(signal_state_change_cb);
+
+    mbtk_ecall_state_change_cb_reg(ecall_state_change_cb);
+
 #if 0
     memset(cli_threads, 0, sizeof(ril_cli_thread_info_t) * CLI_THREAD_MAX);
 
@@ -721,7 +811,9 @@
                     mbtk_ip_info_t ip;
                     memset(&ip, 0, sizeof(mbtk_ip_info_t));
                     if(type == MBTK_DATA_CALL_START) {
-                        err = mbtk_data_call_start((mbtk_ril_cid_enum)cid, (bool)auto_boot_call, (bool)def_route, (bool)as_dns, 10, 10, &ip);
+                        int retry_interval[] = {5, 10, 15};
+                        err = mbtk_data_call_start((mbtk_ril_cid_enum)cid, (bool)auto_boot_call, (bool)def_route, (bool)as_dns, retry_interval,
+                                    3, 0, &ip);
                     } else if(type == MBTK_DATA_CALL_STOP) {
                         err = mbtk_data_call_stop((mbtk_ril_cid_enum)cid, 10);
                     } else {