Add mbtk_ril V2 (Default close)

Change-Id: Iaa5921fd74aeeb394771110f0cec7aa7742dc83a
diff --git a/mbtk/libmbtk_ril_v2/Makefile b/mbtk/libmbtk_ril_v2/Makefile
new file mode 100755
index 0000000..617a549
--- /dev/null
+++ b/mbtk/libmbtk_ril_v2/Makefile
@@ -0,0 +1,36 @@
+BUILD_ROOT = $(shell pwd)/..
+include $(BUILD_ROOT)/Make.defines
+
+LOCAL_PATH=$(BUILD_ROOT)/libmbtk_ril_v2
+
+INC_DIR +=
+
+LIB_DIR +=
+
+LIBS += -llog -lmbtk_lib -lmbtk_net
+
+CFLAGS += -shared -Wl,-shared,-Bsymbolic
+
+LOCAL_SRC_FILES = $(wildcard src/*.cpp) $(wildcard src/*.c)
+OBJS = $(patsubst %.c, %.o, $(LOCAL_SRC_FILES))
+$(info OBJS = $(OBJS))
+
+OBJS = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(LOCAL_SRC_FILES)))
+$(info OBJS = $(OBJS))
+
+dtarget := $(OUT_DIR)/lib/libmbtk_ril.so
+
+all: $(dtarget)
+
+$(dtarget):$(OBJS)
+	$(CC) $(CFLAGS) $(DEFINE) $(LIB_DIR) $(LIBS) $(OBJS) -o $@
+
+%.o:%.c
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+%.o:%.cpp
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+clean:
+	rm -f $(OBJS) $(dtarget)
+
diff --git a/mbtk/libmbtk_ril_v2/inc/mbtk_alphabet.h b/mbtk/libmbtk_ril_v2/inc/mbtk_alphabet.h
new file mode 100755
index 0000000..1ffece7
--- /dev/null
+++ b/mbtk/libmbtk_ril_v2/inc/mbtk_alphabet.h
@@ -0,0 +1,140 @@
+//
+// Created by hitmoon on 15-12-10.
+//
+
+
+struct map_node {
+    unsigned short key;
+    unsigned short value;
+};
+
+
+#define map_size(map) (sizeof(map) / sizeof(struct map_node))
+
+
+// Unicode编码到GSM编码转换
+struct map_node UCS2ToBIT7[] = {
+        {0x000C, 0x1B0A},
+        {0x0024, 0x0002},
+        {0x0040, 0x0000},
+        {0x005B, 0x1B3C},
+        {0x005C, 0x1B2F},
+        {0x005D, 0x1B3E},
+        {0x005E, 0x1B14},
+        {0x005F, 0x0011},
+        {0x007B, 0x1B28},
+        {0x007C, 0x1B40},
+        {0x007D, 0x1B29},
+        {0x007E, 0x1B3D},
+        {0x00A0, 0x001B},
+        {0x00A1, 0x0040},
+        {0x00A3, 0x0001},
+        {0x00A4, 0x0024},
+        {0x00A5, 0x0003},
+        {0x00A7, 0x005F},
+        {0x00BF, 0x0060},
+        {0x00C4, 0x005B},
+        {0x00C5, 0x000E},
+        {0x00C6, 0x001C},
+        {0x00C9, 0x001F},
+        {0x00D1, 0x005D},
+        {0x00D6, 0x005C},
+        {0x00D8, 0x000B},
+        {0x00DC, 0x005E},
+        {0x00DF, 0x001E},
+        {0x00E0, 0x007F},
+        {0x00E4, 0x007B},
+        {0x00E5, 0x000F},
+        {0x00E6, 0x001D},
+        {0x00E7, 0x0009},
+        {0x00E8, 0x0004},
+        {0x00E9, 0x0005},
+        {0x00EC, 0x0007},
+        {0x00F1, 0x007D},
+        {0x00F2, 0x0008},
+        {0x00F6, 0x007C},
+        {0x00F8, 0x000C},
+        {0x00F9, 0x0006},
+        {0x00FC, 0x007E},
+        {0x0393, 0x0013},
+        {0x0394, 0x0010},
+        {0x0398, 0x0019},
+        {0x039B, 0x0014},
+        {0x039E, 0x001A},
+        {0x03A0, 0x0016},
+        {0x03A3, 0x0018},
+        {0x03A6, 0x0012},
+        {0x03A8, 0x0017},
+        {0x03A9, 0x0015},
+        {0x20AC, 0x1B65}
+};
+
+// GSM编码到Unicode编码转换
+struct map_node BIT7ToUCS2[] = {
+        {0x0000, 0x0040},
+        {0x0001, 0x00A3},
+        {0x0002, 0x0024},
+        {0x0003, 0x00A5},
+        {0x0004, 0x00E8},
+        {0x0005, 0x00E9},
+        {0x0006, 0x00F9},
+        {0x0007, 0x00EC},
+        {0x0008, 0x00F2},
+        {0x0009, 0x00E7},
+        {0x000B, 0x00D8},
+        {0x000C, 0x00F8},
+        {0x000E, 0x00C5},
+        {0x000F, 0x00E5},
+        {0x0010, 0x0394},
+        {0x0011, 0x005F},
+        {0x0012, 0x03A6},
+        {0x0013, 0x0393},
+        {0x0014, 0x039B},
+        {0x0015, 0x03A9},
+        {0x0016, 0x03A0},
+        {0x0017, 0x03A8},
+        {0x0018, 0x03A3},
+        {0x0019, 0x0398},
+        {0x001A, 0x039E},
+        {0x001B, 0x00A0},
+        {0x001C, 0x00C6},
+        {0x001D, 0x00E6},
+        {0x001E, 0x00DF},
+        {0x001F, 0x00C9},
+        {0x0024, 0x00A4},
+        {0x0040, 0x00A1},
+        {0x005B, 0x00C4},
+        {0x005C, 0x00D6},
+        {0x005D, 0x00D1},
+        {0x005E, 0x00DC},
+        {0x005F, 0x00A7},
+        {0x0060, 0x00BF},
+        {0x007B, 0x00E4},
+        {0x007C, 0x00F6},
+        {0x007D, 0x00F1},
+        {0x007E, 0x00FC},
+        {0x007F, 0x00E0}
+};
+// GSM编码转义序列到Unicode编码转换
+struct map_node BIT7EToUCS2[] = {
+        {0x000A, 0x000C},
+        {0x0014, 0x005E},
+        {0x0028, 0x007B},
+        {0x0029, 0x007D},
+        {0x002F, 0x005C},
+        {0x003C, 0x005B},
+        {0x003D, 0x007E},
+        {0x003E, 0x005D},
+        {0x0040, 0x007C},
+        {0x0065, 0x20AC}
+};
+
+// map 中查询键值
+int32_t map_get_value(struct map_node *map, unsigned int size, unsigned short key) {
+	int i = 0;
+    for (i = 0; i < size; i++) {
+        if (map[i].key == key)
+            return map[i].value;
+    }
+    return -1;
+}
diff --git a/mbtk/libmbtk_ril_v2/inc/mbtk_ril.h b/mbtk/libmbtk_ril_v2/inc/mbtk_ril.h
new file mode 100755
index 0000000..9303e26
--- /dev/null
+++ b/mbtk/libmbtk_ril_v2/inc/mbtk_ril.h
@@ -0,0 +1,355 @@
+#ifndef MBTK_INFO_INCLUDE
+#define MBTK_INFO_INCLUDE
+#include <netinet/in.h>
+#include <pthread.h>
+
+#include "mbtk_type.h"
+#include "mbtk_list.h"
+#include "mbtk_log.h"
+#include "mbtk_utils.h"
+#include "mbtk_ril_api.h"
+
+#define RIL_SOCK_PACKET_TAG 0x5F6F7F8F
+#define RIL_SOCK_NAME "/tmp/mbtk_ril_sock"
+#define RIL_SOCK_MSG_LEN_MAX 2048
+
+// Tag(4) + Packet_Length(2)
+#define RIL_SOCK_PACK_EXTRA_LEN 6
+// RIL_SOCK_PACK_EXTRA_LEN + Index(2) + Type(2) + Id(2) + Error(2) + data_len(2)
+#define RIL_SOCK_PACK_LEN_MIN (RIL_SOCK_PACK_EXTRA_LEN + 10)
+
+#define RIL_MSG_INDEX_AUTO      (-1)         // automatically , refor to :  ril_index
+#define RIL_MSG_INDEX_INVALID   (0)       // Invalid msg index.
+
+typedef enum
+{
+    RIL_MSG_TYPE_REQ,
+    RIL_MSG_TYPE_RSP,
+    RIL_MSG_TYPE_IND
+} ril_msg_type_enum;
+
+typedef enum
+{
+    // Device Information
+    RIL_MSG_ID_DEV_BEGIN = 0,
+    // <string> IMEI
+    RIL_MSG_ID_DEV_IMEI,
+    // <string> SN
+    RIL_MSG_ID_DEV_SN,
+    // <string> MEID
+    RIL_MSG_ID_DEV_MEID,
+    // <string> VERSION
+    RIL_MSG_ID_DEV_VERSION,
+    // <string> MODEL
+    RIL_MSG_ID_DEV_MODEL,
+    // <uint8> 0:Close 1:Open
+    RIL_MSG_ID_DEV_VOLTE,
+    // <string> Temperature
+    RIL_MSG_ID_DEV_TEMP,  // Temperature
+    // <string>  23/03/20,01:58:00+32
+    RIL_MSG_ID_DEV_CELL_TIME,  // Time
+    // <uint8><uint8>
+    RIL_MSG_ID_DEV_MODEM,
+
+    RIL_MSG_ID_DEV_END,
+
+    // Sim Information
+    RIL_MSG_ID_SIM_BEGIN = 1000,
+    // <uint8> 0:NOT_EXIST 1:READY ...
+    RIL_MSG_ID_SIM_STATE,
+    // <uint8> 0: SIM 1: USIM 2: TEST SIM 3: TEST USIM 4: UNKNOWN
+    RIL_MSG_ID_SIM_TYPE,
+    // <string> IMSI
+    RIL_MSG_ID_SIM_IMSI,
+    // <string> ICCID
+    RIL_MSG_ID_SIM_ICCID,
+    // <string> Phone Number
+    RIL_MSG_ID_SIM_PN,
+    // <string> PUK
+    RIL_MSG_ID_SIM_LOCK,
+    // <uint8> <uint8> <uint8> <uint8> PIN PUK LAST TIMES
+    RIL_MSG_ID_SIM_PINPUK_TIMES,
+    // <string> PLMN
+    RIL_MSG_ID_SIM_PLMN,
+
+    RIL_MSG_ID_SIM_END,
+
+    // Network Information
+    RIL_MSG_ID_NET_BEGIN = 2000,
+    // sel_mode(uint8)type(uint8)plmn(uint32)...sel_mode(uint8)type(uint8)plmn(uint32)
+    RIL_MSG_ID_NET_AVAILABLE,
+    // <uint8> 0: automatic 1: manual
+    // or
+    // sel_mode(uint8)type(uint8)plmn(uint32)
+    RIL_MSG_ID_NET_SEL_MODE,
+    // mbtk_band_info_t
+    RIL_MSG_ID_NET_BAND,
+    // mbtk_signal_info_t
+    RIL_MSG_ID_NET_SIGNAL,
+    // mbtk_net_reg_info_t
+    RIL_MSG_ID_NET_REG,
+    // mbtk_cell_info_t[]
+    RIL_MSG_ID_NET_CELL,
+    // mbtk_apn_info_t
+    RIL_MSG_ID_NET_APN,
+    // REQ:
+    // <call_type[1]><cid[1]><timeout[1]>
+    //  call_type : mbtk_data_call_type_enum
+    //  cid : 1 - 15
+    //  timeout : second
+    // RSP:
+    //  <type[1]><ipv4><ipv6>
+    //  type : 0-IPV4   1-IPV6  2-IPV4V6
+    //  ipv4 : mbtk_ipv4_info_t
+    //  ipv6 : mbtk_ipv6_info_t
+    RIL_MSG_ID_NET_DATA_CALL,
+
+    RIL_MSG_ID_NET_END,
+
+
+    // Call Information
+    RIL_MSG_ID_CALL_BEGIN = 3000,
+    RIL_MSG_ID_CALL_STATE,
+
+    // Start call.
+    RIL_MSG_ID_CALL_START,
+    //answer call
+    RIL_MSG_ID_CALL_ANSWER,
+    //hang up all call
+    RIL_MSG_ID_CALL_HANGUP,
+    //hang up a call
+    RIL_MSG_ID_CALL_HANGUP_A,
+    //hang up waiting or background call
+    RIL_MSG_ID_CALL_HANGUP_B,
+    //hang up foreground resume background
+    RIL_MSG_ID_CALL_HANGUP_C,
+    //wait in call
+    RIL_MSG_ID_CALL_WAITIN,
+    //mute call
+    RIL_MSG_ID_CALL_MUTE,
+    //dtmf call
+    RIL_MSG_ID_CALL_DTMF,
+    RIL_MSG_ID_CALL_END,
+
+    // SMS Information
+    RIL_MSG_ID_SMS_BEGIN = 4000,
+    RIL_MSG_ID_SMS_STATE,
+    RIL_MSG_ID_SMS_CMGF,
+    RIL_MSG_ID_SMS_CPMS,
+    RIL_MSG_ID_SMS_CMGS,
+    RIL_MSG_ID_SMS_CMSS,
+    RIL_MSG_ID_SMS_CMGR,
+    RIL_MSG_ID_SMS_CMGW,
+    RIL_MSG_ID_SMS_CMGD,
+    RIL_MSG_ID_SMS_CMGL,
+    RIL_MSG_ID_SMS_CSCA,
+    RIL_MSG_ID_SMS_CSMP,
+    RIL_MSG_ID_SMS_CSCB,
+    RIL_MSG_ID_SMS_CNMI,
+
+    RIL_MSG_ID_SMS_END,
+
+    // PhoneBook Information
+    RIL_MSG_ID_PB_BEGIN = 5000,
+    RIL_MSG_ID_PB_STATE,
+
+    RIL_MSG_ID_PB_END,
+
+    // IND Information
+    RIL_MSG_ID_IND_BEGIN = 10000,
+    // NULL
+    RIL_MSG_ID_IND_SER_READY,
+    // <uint8>  State
+    RIL_MSG_ID_IND_NET_STATE_CHANGE,
+    // <uint8>  State
+    RIL_MSG_ID_IND_CALL_STATE_CHANGE,
+    // <uint8>  State
+    RIL_MSG_ID_IND_SMS_STATE_CHANGE,
+    // <uint8>  State
+    RIL_MSG_ID_IND_RADIO_STATE_CHANGE,
+    // <uint8>  State
+    RIL_MSG_ID_IND_SIM_STATE_CHANGE,
+    // <uint8>  State
+    RIL_MSG_ID_IND_PDP_STATE_CHANGE,
+    // <uint8> State
+    RIL_MSG_ID_IND_SIGNAL_STATE_CHANGE,
+
+
+    RIL_MSG_ID_IND_END,
+    RIL_MSG_ID_UNKNOWN        // Unknown information.
+} ril_msg_id_enum;
+
+typedef struct {
+    uint32 tag;     // Refor to : RIL_SOCK_PACKET_TAG
+    uint16 msg_len;
+
+    uint16 msg_index;   // Message index(Start from 1)
+            // 0 : For unknown msg id
+    uint16 msg_type;    // Refor to : ril_msg_type_enum
+    uint16 msg_id;      // Refor to : ril_msg_id_enum
+    uint16 err;     // Only for RSP(Refor to : mbtk_ril_err_enum)
+    uint16 data_len;
+    uint8 *data;
+} __attribute__((packed)) ril_msg_pack_info_t;
+
+typedef struct {
+    pthread_t pid;
+    char name[20];
+    bool is_waitting;
+    pthread_cond_t cond;
+    pthread_mutex_t mutex;
+} ril_cli_thread_info_t;
+
+typedef struct {
+    pthread_t pid;
+    bool is_async;
+    int *rsp_data_len;  // Save response data length.
+    char *rsp_data;     // Save response date.
+    int *rsp_err;       // Save response error, refor to mbtk_ril_err_enum .
+    ril_msg_pack_info_t *pack;
+} ril_msg_info_t;
+
+/*
+GSM band��
+    1 �C PGSM 900 (standard or primary)
+    2 �C DCS GSM 1800
+    4 �C PCS GSM 1900
+    8 �C EGSM 900 (extended)
+    16 �C GSM 450
+    32 �C GSM 480
+    64 �C GSM 850
+    512 - BAND_LOCK_BIT // used for GSM band setting
+*/
+typedef enum
+{
+    MBTK_GSM_BAND_PGSM_900 = 1,
+    MBTK_GSM_BAND_DCS_GSM_1800 = 2,
+    MBTK_GSM_BAND_PCS_GSM_1900 = 4,
+    MBTK_GSM_BAND_EGSM_900 = 8,
+    MBTK_GSM_BAND_GSM_450 = 16,
+    MBTK_GSM_BAND_GSM_480 = 32,
+    MBTK_GSM_BAND_GSM_850 = 64,
+    MBTK_GSM_BAND_BAND_LOCK_BIT = 512
+} mbtk_gsm_band_enum;
+
+/*
+UMTS band��
+    1 �C UMTS_BAND_1
+    2 �C UMTS_BAND_2
+    4 �C UMTS_BAND_3
+    8 �C UMTS_BAND_4
+    16 �C UMTS_BAND_5
+    32 �C UMTS_BAND_6
+    64 �C UMTS_BAND_7
+    128 �C UMTS_BAND_8
+    256 �C UMTS_BAND_9
+*/
+typedef enum
+{
+    MBTK_UMTS_BAND_1 = 1,
+    MBTK_UMTS_BAND_2 = 2,
+    MBTK_UMTS_BAND_3 = 4,
+    MBTK_UMTS_BAND_4 = 8,
+    MBTK_UMTS_BAND_5 = 16,
+    MBTK_UMTS_BAND_6 = 32,
+    MBTK_UMTS_BAND_7 = 64,
+    MBTK_UMTS_BAND_8 = 128,
+    MBTK_UMTS_BAND_9 = 256
+} mbtk_umts_band_enum;
+
+/*
+LTEbandH(TDD-LTE band)
+    32 �C TDLTE_BAND_38
+    64 �C TDLTE_BAND_39
+    128 �C TDLTE_BAND_40
+    256 �C TDLTE_BAND_41
+*/
+typedef enum
+{
+    MBTK_TDLTE_BAND_38 = 32,
+    MBTK_TDLTE_BAND_39 = 64,
+    MBTK_TDLTE_BAND_40 = 128,
+    MBTK_TDLTE_BAND_41 = 256
+} mbtk_tdlte_band_enum;
+
+/*
+LTEbandL(FDD-LTE band)
+    1 �C FDDLTE_BAND_1
+    4 �C FDDLTE _BAND_3
+    8 �C FDDLTE _BAND_4
+    64 �C FDDLTE _BAND_7
+    65536 �C FDDLTE _BAND_17
+    524288 �C FDDLTE _BAND_20
+*/
+typedef enum
+{
+    MBTK_FDDLTE_BAND_1 = 1,
+    MBTK_FDDLTE_BAND_3 = 4,
+    MBTK_FDDLTE_BAND_4 = 8,
+    MBTK_FDDLTE_BAND_7 = 64,
+    MBTK_FDDLTE_BAND_17 = 65536,
+    MBTK_FDDLTE_BAND_20 = 524288
+} mbtk_fddlte_band_enum;
+
+typedef enum
+{
+    MBTK_LTE_EXT_BAND_65 = 1,
+    MBTK_LTE_EXT_BAND_66 = 2,
+    MBTK_LTE_EXT_BAND_67 = 4,
+    MBTK_LTE_EXT_BAND_68 = 8,
+    MBTK_LTE_EXT_BAND_69 = 16
+} mbtk_lte_ext_band_enum;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char* type2str(ril_msg_type_enum type);
+
+char* apn2str(mbtk_ip_type_enum type);
+
+/*
+IPv6 : 254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239 -> uint128
+*/
+int str_2_ipv6(const void *ip_str, void *ipv6);
+
+/*
+IPv6 : uint128 -> fe80::215:1dff:fe81:484c
+*/
+int ipv6_2_str(const void *ipv6, void *ipv6_str);
+
+char* id2str(int id);
+
+char* err2str(mbtk_ril_err_enum err);
+
+void *mbtk_memcpy(const void *src, unsigned int n);
+
+/*
+0   GSM
+1   GSM_COMPACT
+2   UTRAN
+3   GSM_EGPRS
+4   UTRAN_HSDPA
+5   UTRAN_HSUPA
+6   UTRAN_HSDPA_HSUPA
+7   EUTRAN
+8   ECGSM
+*/
+mbtk_net_type_enum mbtk_net_type_get(mbtk_radio_technology_enum radio_tech);
+
+void ril_msg_pack_free(ril_msg_pack_info_t* pack);
+
+ril_msg_pack_info_t* ril_msg_pack_creat(int msg_type, int msg_id, int msg_index, const void *data, int data_len);
+
+int ril_pack_send(int fd, ril_msg_pack_info_t *pack);
+
+ril_msg_pack_info_t** ril_pack_recv(int fd, bool is_server, mbtk_ril_err_enum *err);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* MBTK_INFO_INCLUDE */
+
+
diff --git a/mbtk/libmbtk_ril_v2/src/mbtk_pdu_sms.c b/mbtk/libmbtk_ril_v2/src/mbtk_pdu_sms.c
new file mode 100755
index 0000000..5825cb6
--- /dev/null
+++ b/mbtk/libmbtk_ril_v2/src/mbtk_pdu_sms.c
@@ -0,0 +1,1086 @@
+//

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

+//

+

+#include <stddef.h>

+#include <stdlib.h>

+#include <stdio.h>

+#include "mbtk_pdu_sms.h"

+#include "mbtk_alphabet.h"

+

+#define SUB_STR_SIZE 512

+char temp[SUB_STR_SIZE];

+

+// some constant

+

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

+enum EnumCSMIEI mCSMIEI;

+// 服务中心地址

+char *mSCA;

+// 请求状态报告

+bool mSRR;

+// 拒绝副本

+bool mRD;

+// 短信有效期

+char *mVP;

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

+int mCSMMR;

+

+// initialize PDU constants

+void sms_init()

+{

+    mCSMMR = 0;

+    mRD = false;

+    mSRR = false;

+    mSCA = "";

+    mVP = "";

+    mCSMIEI = BIT8MIEI;

+}

+

+

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

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

+    if (size > 0)

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

+    else if (size < 0)

+        strcpy(temp, str + start);

+

+    return temp;

+}

+

+struct SMS_Struct PDUDecoding(const char *data) {

+

+    struct SMS_Struct sms;

+    int end_index;

+    int PDUType;

+    // 短信中心

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

+

+    // 协议数据单元类型

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

+    end_index += 2;

+

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

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

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

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

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

+

+    // 发送方SME的地址

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

+

+    // 协议标识

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

+    end_index += 2;

+

+    // 数据编码方案

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

+    end_index += 2;

+

+    // 文本压缩指示

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

+    // 编码字符集

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

+

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

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

+        sms.MC = DCSType & 3;

+    }

+    else {

+        // 不含信息类型信息

+        sms.MC = -1;

+    }

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

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

+    end_index += 14;

+

+    // 用户数据头

+    if (sms.UDHI) {

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

+    }

+    else {

+        sms.UDH = NULL;

+    }

+

+    // 用户数据

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

+

+    return sms;

+}

+

+

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

+    int len;

+

+    char *result;

+    char *buf;

+	int i = 0;

+

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

+    if (len == 0) {

+        *EndIndex = 2;

+        return NULL;

+    }

+

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

+

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

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

+

+    buf = result;

+    len *= 2;

+

+    // 服务中心地址类型

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

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

+    }

+

+    // 服务中心地

+

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

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

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

+    }

+

+    //  去掉填充的 'F'

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

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

+    }

+

+    return result;

+}

+

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

+    int len;

+    char *result, *buf;

+

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

+

+    if (len == 0) {

+        *EndIndex = index + 2;

+        return NULL;

+    }

+

+    *EndIndex = index + 4 + len;

+

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

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

+    buf = result;

+    

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

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

+    }

+

+    // 电话号码

+	int i = 0;

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

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

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

+

+    }

+

+    if (len % 2 != 0) {

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

+        (*EndIndex)++;

+    }

+    return result;

+}

+

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

+

+    char *result;

+

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

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

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

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

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

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

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

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

+

+    );

+    return result;

+}

+

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

+

+    int n1, n10;

+

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

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

+

+    if (isMSB) {

+        if (n10 >= 8)

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

+        else

+            return n10 * 10 + n1;

+    }

+    else {

+        return n10 * 10 + n1;

+    }

+}

+

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

+

+    int len;

+    struct UDHS *result;

+

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

+    index += 2;

+    int i = 0;

+

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

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

+    result->count = 0;

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

+

+    while (i < len) {

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

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

+        index += 2;

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

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

+        index += 2;

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

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

+        int j = 0;

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

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

+            index += 2;

+        }

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

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

+        result->count++;

+        i += IEDL + 2;

+    }

+

+    return result;

+}

+

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

+    char *result = NULL;

+    char *buf;

+

+    // 用户数据区长度

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

+    index += 2;

+

+    // 跳过用户数据头

+    int UDHL = 0;

+    if (UDHI) {

+        // 用户数据头长度

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

+        UDHL++;

+        index += UDHL << 1;

+

+    }

+

+    // 获取用户数据

+    if (dcs == UCS2) {

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

+        int utf8_len;

+

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

+        buf = result;

+        u_int32_t code[2];

+

+		int i = 0;

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

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

+            code[1] = 0;

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

+            buf += utf8_len;

+        }

+

+        buf[0] = '\0';

+        return result;

+    }

+    else if (dcs == BIT7) {

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

+

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

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

+    }

+    else {// 8Bit编码

+        // 获取数据长度

+        UDL -= UDHL;

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

+        int i = 0;

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

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

+        }

+        return result;

+    }

+

+    return "Error!";

+}

+

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

+    char *result;

+

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

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

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

+    int n = 0;

+    int left = 0;

+

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

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

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

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

+

+	int i = 0;

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

+

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

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

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

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

+        }

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

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

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

+        if (Order == 6) {

+            if (n == Septets)

+                break;

+            result[n++] = left;

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

+            left = 0;

+        }

+    }

+

+    return result;

+}

+

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

+{

+    char *result, *buf;

+

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

+    buf = result;

+

+	int i = 0;

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

+        u_int16_t key = BIT7Data[i];

+        if (isBIT7Same(key)) {

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

+        }

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

+            u_int16_t value;

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

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

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

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

+                    i++;

+                }

+                else {

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

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

+                }

+            }

+            else {

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

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

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

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

+

+            }

+        }

+        else {// 异常数据

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

+        }

+

+    }

+    return result;

+

+}

+

+int isBIT7Same(u_int16_t UCS2) {

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

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

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

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

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

+        return 1;

+    }

+    return 0;

+}

+

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

+    enum EnumDCS DCS;

+

+    sms_init();

+

+//    if (isGSMString(UDC))

+//        DCS = BIT7;

+//    else

+        DCS = UCS2;

+

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

+}

+

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

+    // 短信拆分

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

+    struct PDUS *pdus;

+

+    if (uds == NULL)

+        return NULL;

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

+    pdus->count = 0;

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

+

+    if (uds->total > 1) {

+        // 长短信

+        int CSMMR = mCSMMR;

+        if (++mCSMMR > 0xFFFF)

+            mCSMMR = 0;

+        // 生成短信编码序列

+		int i = 0;

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

+            // 更新用户数据头

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

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

+            pdus->count++;

+        }

+

+    }

+    else {  // 单条短信

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

+        pdus->count = 1;

+    }

+

+    return pdus;

+}

+

+int isGSMString(char *Data) {

+

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

+        return 1;

+

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

+        int len;

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

+

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

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

+

+        while (*code) {

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

+                return 0;

+            code++;

+        }

+

+        return 1;

+    }

+    else

+        return 1;

+

+}

+

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

+    int UDHL = getUDHL(udhs);

+    struct UDS *result;

+

+    if (DCS == BIT7) {

+        // 7-Bit编码

+        // 计算剩余房间数

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

+        if (room < 1) {

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

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

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

+                result->total = 1;

+                result->Data[0] = UDC;

+                return result;

+            }

+            else

+                return NULL;

+        }

+

+        // 不需要拆分

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

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

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

+            result->total = 1;

+            result->Data[0] = UDC;

+            return result;

+        }

+        else // 拆分短信

+        {

+            if (UDHL == 0)

+                UDHL++;

+            if (mCSMIEI == BIT8MIEI)

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

+            else

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

+            // 更新剩余房间数

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

+            if (room < 1)

+                return NULL;

+

+            int i = 0;

+            int len = strlen(UDC);

+

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

+            result->total = 0;

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

+

+            while (i < len) {

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

+                if (i + step < len) {

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

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

+                }

+                else {

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

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

+                }

+

+                i += step;

+

+            }

+            return result;

+

+        }

+    }

+    else { // UCS2编码

+        // 计算剩余房间数

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

+        if (room < 1) {

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

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

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

+                result->total = 1;

+                result->Data[0] = UDC;

+                return result;

+            }

+            else

+                return NULL;

+        }

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

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

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

+            result->total = 1;

+            result->Data[0] = UDC;

+            return result;

+        }

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

+        {

+            if (UDHL == 0)

+                UDHL++;

+            if (mCSMIEI == BIT8MIEI)

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

+            else

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

+

+            // 更新剩余房间数

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

+            if (room < 1)

+                return NULL;

+

+            int len = utf8len(UDC);

+

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

+            result->total = 0;

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

+	    int index = 0;

+		int i = 0;

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

+		    int real_size;

+                if (i + room < len) {

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

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

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

+                }

+                else {

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

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

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

+                }

+		index += real_size;

+            }

+            return result;

+        }

+

+    }

+}

+

+int getUDHL(struct UDHS *udhs) {

+    if (udhs == NULL)

+        return 0;

+

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

+    int UDHL = 1;

+	int i = 0;

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

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

+    }

+    return UDHL;

+}

+

+int SeptetsLength(char *source) {

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

+        return 0;

+    }

+    int len = strlen(source);

+    while (*source) {

+        u_int16_t code = (u_int16_t) *source;

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

+            len++;

+        }

+        source++;

+    }

+    return len;

+}

+

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

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

+        return 0;

+    int count = 0;

+    int i;

+

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

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

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

+            count++;

+

+        if (++count >= septets) {

+            if (count == septets)

+                i++;

+            break;

+        }

+    }

+    return i - index;

+}

+

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

+    struct UDHS *result;

+

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

+

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

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

+        result->count = 1;

+

+    }

+    else {

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

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

+        // 复制 UDH

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

+    }

+    // 插入第一个位置

+    if (mCSMIEI == BIT8MIEI) {

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

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

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

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

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

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

+    }

+    else {

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

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

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

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

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

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

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

+    }

+

+    return result;

+}

+

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

+    char *result;

+    char *buf, *ret;

+    int index;

+

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

+    buf = result;

+

+/*    //  短信中心

+	ret = SCAEncoding(SCA);

+    index = strlen(ret);

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

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

+    buf += index;

+

+*/

+    // 协议数据单元类型

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

+        ret = PDUTypeEncoding(false);

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

+        buf += strlen(ret);

+    }

+    else {

+        ret = PDUTypeEncoding(true);

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

+        buf += strlen(ret);

+    }

+    // 消息参考值

+    ret = MREncoding();

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

+    buf += strlen(ret);

+    // 接收方SME地址

+    ret = DAEncoding(DA);

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

+    buf += strlen(ret);

+    // 协议标识

+    ret = PIDEncoding();

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

+    buf += strlen(ret);

+    // 编码方案

+    ret = DCSEncoding(UC, DCS);

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

+    buf += strlen(ret);

+    // 有效期

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

+    buf += strlen(mVP);

+

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

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

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

+

+    return result;

+}

+

+char *SCAEncoding(char *SCA) {

+

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

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

+        return "00";

+    }

+

+    char *result;

+    char *buf;

+    int len;

+    len = strlen(SCA);

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

+    buf = result;

+

+    int index = 0;

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

+        // 国际号码

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

+        buf += 2;

+        sprintf(buf, "91");

+        buf += 2;

+        index = 1;

+    }

+    else {

+        // 国内号码

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

+        buf += 2;

+        sprintf(buf, "81");

+        buf += 2;

+    }

+    // SCA地址编码

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

+        if (index == len - 1) {

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

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

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

+

+        }

+        else {

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

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

+        }

+    }

+

+    return result;

+}

+

+char *PDUTypeEncoding(bool UDH) {

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

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

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

+//	int PDUType = 0x01;

+    char *result;

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

+

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

+    if (UDH) {

+        PDUType |= 0x40;

+    }

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

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

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

+        PDUType |= 0x10;

+    }

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

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

+        PDUType |= 0x18;

+    }

+

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

+    if (mSRR) {

+        // 请求状态报告

+        PDUType |= 0x20;

+    }

+

+    // 拒绝复本(Reject Duplicate)

+    if (mRD) {

+        PDUType |= 0x04;

+    }

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

+    return result;

+}

+

+char *MREncoding() {

+    // 由手机设置

+    return "00";

+}

+

+char *DAEncoding(char *DA) {

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

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

+        return "0080";

+    }

+    char *result, *buf;

+    int len = strlen(DA);

+    int index;

+

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

+    buf = result;

+

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

+        // 国际号码

+        // 地址长度编码

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

+        buf += 2;

+        // 地址类型

+        sprintf(buf, "91");

+        buf += 2;

+        index = 1;

+    }

+    else {

+        // 国内号码

+        // 地址长度编码

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

+        buf += 2;

+        // 地址类型

+        sprintf(buf, "81");

+        buf += 2;

+    }

+

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

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

+        if (index == len - 1) {

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

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

+        }

+        else {

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

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

+        }

+    }

+    return result;

+

+}

+

+char *PIDEncoding() {

+    return "00";

+}

+

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

+    if (DCS == BIT7) {

+        // 7-Bit编码

+        return "00";

+    }

+    else {

+        // UCS2编码

+        return "0800";

+    }

+}

+

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

+    int UDHL;

+

+    char *result;

+

+    // 用户数据头编码

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

+

+    // 用户数据内容编码

+    int UDCL;

+    char *body;

+

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

+

+    // 用户数据区长度

+    int UDL;

+    if (DCS == BIT7) {

+        // 7-Bit编码

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

+    }

+    else {

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

+        UDL = UDHL + UDCL;

+    }

+

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

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

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

+

+    return result;

+

+}

+

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

+

+    *UDHL = 0;

+

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

+        return "";

+	int i = 0;

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

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

+    }

+

+    char *result;

+    char *buf;

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

+    buf = result;

+

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

+    buf += 2;

+	

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

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

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

+        buf += 2;

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

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

+        buf += 2;

+        // 信息元素数据

+		int j = 0;

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

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

+            buf += 2;

+        }

+

+    }

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

+    (*UDHL)++;

+    return result;

+

+}

+

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

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

+        *UDCL = 0;

+        return "";

+    }

+

+    if (DCS == BIT7) {

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

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

+    }

+    else {

+        // UCS2编码

+

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

+        int len2;

+        unsigned short *code;

+

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

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

+        *UDCL = len * 2;

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

+        char *buf = result;

+

+		int i = 0;

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

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

+            buf += 4;

+        }

+        free(code);

+        return result;

+    }

+}

+

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

+    struct ByteArray *result;

+

+    int len = strlen(UDC);

+

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

+    result->len = 0;

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

+    *Septets = 0;

+

+	int i = 0;

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

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

+        if (isBIT7Same(code)) {

+            //  编码不变

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

+        }

+        else {

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

+            if (value >= 0) {

+                if (value > 0xFF) {

+                    // 转义序列

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

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

+                }

+                else {

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

+                }

+            }

+            else {

+                // 未知字符

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

+            }

+        }

+    }

+    // 重新调整大小

+    result->len = *Septets;

+

+    return result;

+}

+

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

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

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

+

+    // 压缩字节数

+    int len = Bit7Array->len;

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

+    char *result;

+    char *buf;

+

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

+    buf = result;

+

+    int left = 0;

+	int i = 0;

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

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

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

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

+        if (index == 0) {

+            left = Value;

+        }

+        else {

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

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

+            buf += 2;

+            left = Value >> index;

+        }

+    }

+

+

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

+        // 写入剩余数据

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

+        buf += 2;

+    }

+    buf[0] = '\0';

+    return result;

+}

+

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