data_call: add T108 data_call api

Change-Id: I762de517f8ef605dd3fdd51689cf8b09a122ab29
diff --git a/mbtk/include/lynq/lynq-qser-data.h b/mbtk/include/lynq/lynq-qser-data.h
index c84ab21..0d85f67 100755
--- a/mbtk/include/lynq/lynq-qser-data.h
+++ b/mbtk/include/lynq/lynq-qser-data.h
@@ -114,7 +114,7 @@
 } qser_data_call_info_s;
 
 typedef struct {
-	unsigned char profile_idx;              /*!< UMTS/CDMA profile ID. */
+	unsigned char profile_idx;              /*!< UMTS/CDMA profile ID. range: 0 - 7*/
 	qser_apn_pdp_type_e pdp_type;             /*!< Packet Data Protocol (PDP) type specifies the type of data payload
 	                                             exchanged over the airlink when the packet data session is
 	                                             established with this profile. */ 
diff --git a/mbtk/lynq_lib/src/lynq_data_call.c b/mbtk/lynq_lib/src/lynq_data_call.c
index fae8e3f..d65c3b6 100755
--- a/mbtk/lynq_lib/src/lynq_data_call.c
+++ b/mbtk/lynq_lib/src/lynq_data_call.c
@@ -1,60 +1,581 @@
 #include "lynq-qser-data.h"
 #include "mbtk_type.h"
+#include "mbtk_info_api.h"
 
+/****************************DEFINE***************************************/
+#define QSER_RESULT_SUCCESS 0
+#define QSER_RESULT_FAIL -1
 
+//default  range: 0 - 7
+//AT+CGACT range: 1 - 8
+//1 default IDX, 8 IMS IDX
+#define QSER_PROFILE_IDX_MIN 1
+#define QSER_PROFILE_IDX_MAX 6
+/****************************DEFINE***************************************/
+
+/****************************VARIABLE***************************************/
+mbtk_info_handle_t* qser_info_handle = NULL;
+int qser_info_handle_num = 0;
+static bool inited = FALSE;
+static qser_data_call_evt_cb_t qser_net_status_cb = NULL;
+static qser_apn_info_s qser_apn_info[8] = {0};
+/****************************VARIABLE***************************************/
+
+/******************************FUNC*****************************************/
+int qser_apn_info_param_convert(int profile_idx, qser_apn_info_s *new_apn, mbtk_apn_info_t *old_apn)
+{
+    if(new_apn == NULL || old_apn == NULL)
+    {
+        LOGE("[qser_data_call] qser_apn_info_param_convert apn param is NULL.");
+        return QSER_RESULT_FAIL;
+    }
+    
+    //get ip type
+    if(old_apn->ip_type == MBTK_IP_TYPE_IPV4V6) // IPV4V6
+    {
+        new_apn->pdp_type = QSER_APN_PDP_TYPE_IPV4V6;
+    }
+    else if(old_apn->ip_type == MBTK_IP_TYPE_IP) // IPV4
+    {
+        new_apn->pdp_type = QSER_APN_PDP_TYPE_IPV4;
+    }
+    else if(old_apn->ip_type == MBTK_IP_TYPE_IPV6) // IPV6
+    {
+        new_apn->pdp_type = QSER_APN_PDP_TYPE_IPV6;
+    }
+    else
+    {
+        new_apn->pdp_type = QSER_APN_PDP_TYPE_PPP;
+    }
+
+    //get apn name
+    if(strlen(old_apn->apn)+1 > QSER_APN_NAME_SIZE)
+    {
+        LOGE("[qser_data_call] apn_nmea length verylong.");
+        return QSER_RESULT_FAIL;
+    }
+    else
+    {
+        if(strlen(old_apn->apn) > 0)
+        {
+            memcpy(new_apn->apn_name, old_apn->apn,strlen(old_apn->apn)+1);
+        }
+        else
+        {
+            memset(new_apn->apn_name, 0x0, QSER_APN_NAME_SIZE);
+        }
+    }
+
+    //get apn user
+    if(strlen(old_apn->user)+1 > QSER_APN_USERNAME_SIZE)
+    {
+        LOGE("[qser_data_call] apn_user length verylong.");
+        return QSER_RESULT_FAIL;
+    }
+    else
+    {
+        if(strlen(old_apn->user) > 0)
+        {
+            memcpy(new_apn->username, old_apn->user, strlen(old_apn->user)+1);
+        }
+        else
+        {
+            memset(new_apn->username , 0x0, QSER_APN_USERNAME_SIZE);
+        }
+    }
+
+    //get apn password
+    if(strlen(old_apn->pass)+1 > QSER_APN_PASSWORD_SIZE)
+    {
+        LOGE("[qser_data_call] apn_password length verylong.");
+        return QSER_RESULT_FAIL;
+    }
+    else
+    {
+        if(strlen(old_apn->pass) > 0)
+        {
+            memcpy(new_apn->password, old_apn->pass, strlen(old_apn->pass)+1);
+        }
+        else
+        {
+            memset(new_apn->username , 0x0, QSER_APN_PASSWORD_SIZE);
+        }
+    }
+
+    //get apn proto
+    if(strlen(old_apn->auth) > 0)
+    {
+        if(strcmp(old_apn->auth, "NONE") == 0)
+        {
+            new_apn->auth_proto = QSER_APN_AUTH_PROTO_NONE;
+        }
+        else if(strcmp(old_apn->auth, "PAP") == 0)
+        {
+            new_apn->auth_proto = QSER_APN_AUTH_PROTO_PAP;
+        }
+        else if(strcmp(old_apn->auth, "CHAP") == 0)
+        {
+            new_apn->auth_proto = QSER_APN_AUTH_PROTO_CHAP;
+        }
+        else
+        {
+            LOGE("[qser_data_call] auth input error!");
+            return QSER_RESULT_FAIL;
+        }
+    }
+
+    //get apn type
+    new_apn->profile_idx = profile_idx;
+    memset(new_apn->apn_type, 0x0, QSER_APN_NAME_SIZE);
+    if(strlen(qser_apn_info[profile_idx].apn_type) > 0)
+    {
+        memcpy(new_apn->apn_type, qser_apn_info[profile_idx].apn_type, strlen(qser_apn_info[profile_idx].apn_type));
+    }
+
+    return QSER_RESULT_SUCCESS;
+}
+
+void qser_wan_net_state_change_cb(const void* data, int data_len)
+{
+    if(data == NULL || data_len == 0)
+    {
+        return;
+    }
+    
+    uint8 *net_data = NULL;
+    net_data = (uint8 *)data;
+
+    if(qser_net_status_cb != NULL)
+    {
+        //
+    }
+}
+/******************************FUNC*****************************************/
+
+/****************************API***************************************/
 int qser_data_call_init(qser_data_call_evt_cb_t evt_cb)
 {
-    UNUSED(evt_cb);
+    //UNUSED(evt_cb);
+    if(!inited && qser_info_handle == NULL)
+    {
+        qser_info_handle = mbtk_info_handle_get();
+        if(qser_info_handle)
+        {
+            qser_info_handle_num++;
+            inited = TRUE;
+            mbtk_pdp_state_change_cb_reg(qser_info_handle, qser_wan_net_state_change_cb);
+        }
+        else
+        {
+            LOGE("[qser_data_call] mbtk_info_handle_get() fail.");
+            return QSER_RESULT_FAIL;
+        }
+    }
+    else
+    {
+        if(!inited)
+        {
+            qser_info_handle_num++;
+            inited = TRUE;
+            mbtk_pdp_state_change_cb_reg(qser_info_handle, qser_wan_net_state_change_cb);
+        }
+    }
+    qser_net_status_cb = evt_cb;
 
-    return 0;
+    LOGE("[qser_data_call] mbtk_info_handle_get() success.");
+    return QSER_RESULT_SUCCESS;
 }
 
 void qser_data_call_destroy(void)
 {
-
+    if(qser_info_handle)
+    {
+        LOGE("qser_info_handle_num = %d", qser_info_handle_num);
+        if(qser_info_handle_num == 1)
+        { // 最后一个引用,可释放。
+            int ret = mbtk_info_handle_free(&qser_info_handle);
+            if(ret)
+            {
+                LOGE("[qser_data_call] mbtk_info_handle_free() fail.");
+            }
+            else
+            {
+                qser_info_handle_num = 0;
+                qser_info_handle = NULL;
+                inited = FALSE;
+            }
+        } 
+        else
+        {
+            qser_info_handle_num--;
+        }
+    }
+    else
+    {
+        LOGE("[qser_data_call] handle not inited.");
+    }
 }
 
 int qser_data_call_start(qser_data_call_s *data_call, qser_data_call_error_e *err)
 {
-    UNUSED(data_call);
-    UNUSED(err);
+    //UNUSED(data_call);
+    //UNUSED(err);
+    if(data_call == NULL || err == NULL)
+    {
+        LOGE("[qser_data_call] data_call or err is NULL.");
+        if(err != NULL)
+        {
+            *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+        }
+        return QSER_RESULT_FAIL;
+    }
+    
+    if(qser_info_handle == NULL)
+    {
+        LOGE("[qser_data_call] handle is NULL.");
+        *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+        return QSER_RESULT_FAIL;
+    }
 
-    return 0;
+    if(data_call->profile_idx < QSER_PROFILE_IDX_MIN || data_call->profile_idx > QSER_PROFILE_IDX_MAX)
+    {
+        LOGE("[qser_data_call] IDX range error.");
+        *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+        return QSER_RESULT_FAIL;
+    }
+
+    int ret = -1;
+    ret = mbtk_data_call_start(qser_info_handle, data_call->profile_idx + 1, 0, FALSE, 0);
+    if(ret != 0)
+    {
+        LOGE("[qser_data_call] mbtk_data_call_start fail.[ret = %d]", ret);
+        *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+        return QSER_RESULT_FAIL;
+    }
+    else
+    {
+        *err = QSER_DATA_CALL_ERROR_NONE;
+    }
+    return QSER_RESULT_SUCCESS;
 }
 
 int qser_data_call_stop(char profile_idx, qser_data_call_ip_family_e ip_family, qser_data_call_error_e *err)
 {
-    UNUSED(profile_idx);
+    //UNUSED(profile_idx);
     UNUSED(ip_family);
-    UNUSED(err);
+    //UNUSED(err);
+    if(err == NULL)
+    {
+        LOGE("[qser_data_call] err is NULL.");
+        return QSER_RESULT_FAIL;
+    }
 
-    return 0;
+    if(qser_info_handle == NULL)
+    {
+        LOGE("[qser_data_call] handle is NULL.");
+        *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+        return QSER_RESULT_FAIL;
+    }
+
+    if(profile_idx < QSER_PROFILE_IDX_MIN || profile_idx > QSER_PROFILE_IDX_MAX)
+    {
+        LOGE("[qser_data_call] IDX range error.");
+        *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+        return QSER_RESULT_FAIL;
+    }
+
+    int ret = -1;
+    ret = mbtk_data_call_stop(qser_info_handle, profile_idx + 1, 15);
+    if(ret != 0)
+    {
+        LOGE("[qser_data_call] mbtk_data_call_stop fail.[ret = %d]", ret);
+        *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+        return QSER_RESULT_FAIL;
+    }
+    else
+    {
+        *err = QSER_DATA_CALL_ERROR_NONE;
+    }
+    
+    return QSER_RESULT_SUCCESS;
 }
 
 int qser_data_call_info_get(char profile_idx,qser_data_call_ip_family_e ip_family,
         qser_data_call_info_s *info, qser_data_call_error_e *err)
 {
-    UNUSED(profile_idx);
+    //UNUSED(profile_idx);
     UNUSED(ip_family);
-    UNUSED(info);
-    UNUSED(err);
+    //UNUSED(info);
+    //UNUSED(err);
 
-    return 0;
+    if(info == NULL || err == NULL)
+    {
+        LOGE("[qser_data_call] info or err is NULL.");
+        if(err != NULL)
+        {
+            *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+        }
+        return QSER_RESULT_FAIL;
+    }
+
+    if(qser_info_handle == NULL)
+    {
+        LOGE("[qser_data_call] handle is NULL.");
+        *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+        return QSER_RESULT_FAIL;
+    }
+
+    if(profile_idx < QSER_PROFILE_IDX_MIN || profile_idx > QSER_PROFILE_IDX_MAX)
+    {
+        LOGE("[qser_data_call] IDX range error.");
+        *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+        return QSER_RESULT_FAIL;
+    }
+
+    int ret = -1;
+    mbtk_ipv4_info_t ipv4;
+    mbtk_ipv6_info_t ipv6;
+#ifdef QSER_TEST
+    char v4_buff[32] = {0};
+    char v6_buff[128] = {0};
+#endif
+    memset(info, 0, sizeof(qser_data_call_info_s));
+    ret = mbtk_data_call_state_get(qser_info_handle, profile_idx + 1, &ipv4, &ipv6);
+    if(ret != 0)
+    {
+        LOGE("[qser_data_call] mbtk_data_call_state_get fail.[ret = %d]", ret);
+        *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+        return QSER_RESULT_FAIL;
+    }
+    else
+    {
+        info->profile_idx = profile_idx;
+        if(ipv4.valid)
+        {
+            info->ip_family = QSER_DATA_CALL_TYPE_IPV4;
+            info->v4.state = QSER_DATA_CALL_CONNECTED;
+            sprintf(info->v4.name, "ccinet%d", profile_idx);
+            memcpy(&(info->v4.addr.ip), &(ipv4.IPAddr), 32);
+            memcpy(&(info->v4.addr.pri_dns), &(ipv4.PrimaryDNS), 32);
+            memcpy(&(info->v4.addr.sec_dns), &(ipv4.SecondaryDNS), 32);
+#ifdef QSER_TEST
+            if(inet_ntop(AF_INET, &(info->v4.addr.ip), v4_buff, 32) == NULL) {
+                LOGE("[qser_data_call] IP error.");
+            } else {
+                LOGE("[qser_data_call] IP : %s", v4_buff);
+            }
+            if(inet_ntop(AF_INET, &(info->v4.addr.pri_dns), v4_buff, 32) == NULL) {
+                LOGE("[qser_data_call] PrimaryDNS error.");
+            } else {
+                LOGE("[qser_data_call] PrimaryDNS : %s", v4_buff);
+            }
+            if(inet_ntop(AF_INET, &(info->v4.addr.sec_dns), v4_buff, 32) == NULL) {
+                LOGE("[qser_data_call] SecondaryDNS error.");
+            } else {
+                LOGE("[qser_data_call] SecondaryDNS : %s", v4_buff);
+            }
+#endif
+        }
+
+        if(ipv6.valid)
+        {
+            info->ip_family = QSER_DATA_CALL_TYPE_IPV6;
+            info->v6.state = QSER_DATA_CALL_CONNECTED;
+            sprintf(info->v6.name, "ccinet%d", profile_idx);
+            memcpy(&(info->v6.addr.ip), &(ipv6.IPV6Addr), 128);
+            memcpy(&(info->v6.addr.pri_dns), &(ipv6.PrimaryDNS), 128);
+            memcpy(&(info->v6.addr.sec_dns), &(ipv6.SecondaryDNS), 128);
+#ifdef QSER_TEST
+			if(ipv6_2_str(&(info->v6.addr.ip), v6_buff))
+            {
+				LOGE("[qser_data_call] IP error.");
+			} else {
+				LOGE("[qser_data_call] IP : %s", v6_buff);
+			}
+			if(ipv6_2_str(&(info->v6.addr.pri_dns), v6_buff))
+            {
+				LOGE("[qser_data_call] PrimaryDNS error.");
+			} else {
+				LOGE("[qser_data_call] PrimaryDNS : %s", v6_buff);
+			}
+			if(ipv6_2_str(&(info->v6.addr.sec_dns), v6_buff))
+            {
+				LOGE("[qser_data_call] SecondaryDNS error.");
+			} else {
+				LOGE("[qser_data_call] SecondaryDNS : %s", v6_buff);
+            }
+#endif
+        }
+        
+        if(ipv4.valid && ipv6.valid)
+        {
+            info->ip_family = QSER_DATA_CALL_TYPE_IPV4V6;
+        }
+
+        if(!ipv4.valid && !ipv6.valid)
+        {
+            info->v4.state = QSER_DATA_CALL_DISCONNECTED;
+            info->v6.state = QSER_DATA_CALL_DISCONNECTED;
+        }
+    }
+    
+    *err = QSER_DATA_CALL_ERROR_NONE;
+    return QSER_RESULT_SUCCESS;
 }
 
 int qser_apn_set(qser_apn_info_s *apn)
 {
-    UNUSED(apn);
+    //UNUSED(apn);
+    if(qser_info_handle == NULL)
+    {
+        LOGE("[qser_data_call] handle is NULL.");
+        return QSER_RESULT_FAIL;
+    }
+    
+    if(apn == NULL)
+    {
+        LOGE("[qser_data_call] apn param is NULL.");
+        return QSER_RESULT_FAIL;
+    }
 
-    return 0;
+    if(apn->profile_idx < QSER_PROFILE_IDX_MIN || apn->profile_idx > QSER_PROFILE_IDX_MAX)
+    {
+        LOGE("[qser_data_call] IDX range error.");
+        return QSER_RESULT_FAIL;
+    }
+
+    if(strlen(apn->apn_name) == 0)
+    {
+        LOGE("[qser_data_call] apn_name is NULL.");
+        return QSER_RESULT_FAIL;
+    }
+
+    int ret = -1;
+    char mbtk_auth[32]={0};
+    mbtk_ip_type_enum pdp_type = MBTK_IP_TYPE_IPV4V6;
+    
+    if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV4)
+    {
+        pdp_type = MBTK_IP_TYPE_IP;
+    }
+    else if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV6)
+    {
+        pdp_type = MBTK_IP_TYPE_IPV6;
+    }
+    else if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV4V6)
+    {
+        pdp_type = MBTK_IP_TYPE_IPV4V6;
+    }
+    else if(apn->pdp_type == QSER_APN_PDP_TYPE_PPP)
+    {
+        pdp_type = MBTK_IP_TYPE_PPP;
+    }
+    else
+    {
+        LOGE("[qser_data_call] pdp_type error.");
+        return QSER_RESULT_FAIL;
+    }
+
+    if(apn->auth_proto == QSER_APN_AUTH_PROTO_NONE || apn->auth_proto == QSER_APN_AUTH_PROTO_DEFAULT)
+    {
+        memcpy(mbtk_auth,"NONE",strlen("NONE")+1);
+    }
+    else if(apn->auth_proto == QSER_APN_AUTH_PROTO_PAP)
+    {
+        memcpy(mbtk_auth,"PAP",strlen("PAP")+1);
+    }
+    else if(apn->auth_proto == QSER_APN_AUTH_PROTO_CHAP)
+    {
+        memcpy(mbtk_auth,"CHAP",strlen("CHAP")+1);
+    }
+    #if 0
+    else if(apn->auth_proto == QSER_APN_AUTH_PROTO_PAP_CHAP)
+    {
+        //NOT SUPPORT
+    }
+    #endif
+    else
+    {
+        LOGE("[qser_data_call] auth input error!");
+        return QSER_RESULT_FAIL;
+    }
+
+    if(strlen(apn->username) > 0 && strlen(apn->password) > 0)
+    {
+        LOGE("[qser_data_call] setapn: %d, %d, %s, %s, %s, %s, %s.",apn->profile_idx, pdp_type, apn->apn_name, apn->username, apn->password, mbtk_auth, apn->apn_type);
+    }
+    else
+    {
+        LOGE("[qser_data_call] setapn: %d, %d, %s, NULL, NULL, %s, %s.",apn->profile_idx, pdp_type, apn->apn_name, apn->username, apn->password, mbtk_auth, apn->apn_type);
+    }
+
+    ret = mbtk_apn_set(qser_info_handle, apn->profile_idx + 1, pdp_type, apn->apn_name, apn->username, apn->password, mbtk_auth);
+    if(ret < 0)
+    {
+        LOGE("[qser_data_call] mbtk_apn_set fail!");
+        return QSER_RESULT_FAIL;
+    }
+
+    memcpy(&qser_apn_info[apn->profile_idx], apn, sizeof(qser_apn_info_s));
+    return QSER_RESULT_SUCCESS;
 }
 
 int qser_apn_get(unsigned char profile_idx, qser_apn_info_s *apn)
 {
-    UNUSED(profile_idx);
-    UNUSED(apn);
+    //UNUSED(profile_idx);
+    //UNUSED(apn);
+    if(qser_info_handle == NULL)
+    {
+        LOGE("[qser_data_call] handle is NULL.");
+        return QSER_RESULT_FAIL;
+    }
+    
+    if(apn == NULL)
+    {
+        LOGE("[qser_data_call] apn param is NULL.");
+        return QSER_RESULT_FAIL;
+    }
 
-    return 0;
+    if(profile_idx < QSER_PROFILE_IDX_MIN || profile_idx > QSER_PROFILE_IDX_MAX)
+    {
+        LOGE("[qser_data_call] IDX range error.");
+        return QSER_RESULT_FAIL;
+    }
+
+    //get apn info
+    mbtk_apn_info_t apns[10] = {0};
+    int apn_num = 10;
+    int ret = mbtk_apn_get(qser_info_handle, &apn_num, apns);
+    if(ret != 0)
+    {
+        LOGE("[qser_data_call] mbtk_apn_get fail. [ret = %d]",ret);
+        return QSER_RESULT_FAIL;
+    }
+    else
+    {
+        int i = 0;
+        for(i = 0; i < apn_num; i++)
+        {
+            if(apns[i].cid == profile_idx + 1)
+            {
+                LOGE("[qser_data_call] find IDX.");
+                break;
+            }
+        }
+
+        if(i == apn_num)
+        {
+            LOGE("[qser_data_call] not find IDX.[apn_num = %d]", apn_num);
+            return QSER_RESULT_FAIL;
+        }
+
+        if(qser_apn_info_param_convert(profile_idx, apn, &apns[i]) != 0)
+        {
+            LOGE("[qser_data_call] qser_apn_info_param_convert fail");
+            return QSER_RESULT_FAIL;
+        }
+    }
+    return QSER_RESULT_SUCCESS;
 }
 
 int qser_apn_add(qser_apn_add_s *apn, unsigned char *profile_idx)
@@ -74,8 +595,54 @@
 
 int qser_apn_get_list(qser_apn_info_list_s *apn_list)
 {
-    UNUSED(apn_list);
+    //UNUSED(apn_list);
 
-    return 0;
+    if(qser_info_handle == NULL)
+    {
+        LOGE("[qser_data_call] handle is NULL.");
+        return QSER_RESULT_FAIL;
+    }
+    
+    if(apn_list == NULL)
+    {
+        LOGE("[qser_data_call] apn_list param is NULL.");
+        return QSER_RESULT_FAIL;
+    }
+
+    mbtk_apn_info_t apns[10] = {0};
+    int apn_num = 10;
+    int ret = mbtk_apn_get(qser_info_handle, &apn_num, apns);
+    if(ret != 0)
+    {
+        LOGE("[qser_data_call] mbtk_apn_get fail. [ret = %d]",ret);
+        return QSER_RESULT_FAIL;
+    }
+    else
+    {
+        if(apn_num > 0 && apn_num <= QSER_APN_MAX_LIST)
+        {
+            int i = 0;
+            for(i = 0; i < apn_num; i++)
+            {
+                if(qser_apn_info_param_convert(apns[i].cid - 1, &apn_list->apn[i], &apns[i]) != 0)
+                {
+                    LOGE("[qser_data_call] qser_apn_info_param_convert fail");
+                    return QSER_RESULT_FAIL;
+                }
+            }
+            apn_list->cnt = apn_num;
+        }
+        else if(apn_num > QSER_APN_MAX_LIST)
+        {
+            LOGE("[qser_data_call] apn_num overlong");
+            return QSER_RESULT_FAIL;
+        }
+        else
+        {
+            apn_list->cnt = 0;
+        }
+    }
+    return QSER_RESULT_SUCCESS;
 }
+/****************************API***************************************/