| #include "lynq-qser-data.h" | 
 | #include "mbtk_type.h" | 
 | #include "mbtk_info_api.h" | 
 |  | 
 | #include <pthread.h> | 
 | #include <cutils/properties.h> | 
 | #include <string.h> | 
 | #include <unistd.h> | 
 | #include <sys/types.h> | 
 | #include <sys/stat.h> | 
 | #include <fcntl.h> | 
 | /****************************DEFINE***************************************/ | 
 | #define QSER_RESULT_SUCCESS 0 | 
 | #define QSER_RESULT_FAIL -1 | 
 |  | 
 | #define MBTK_INFO_ERR_CID_EXIST 311 | 
 | #define MBTK_INFO_ERR_CID_NO_EXIST 312 | 
 | #define MBTK_INFO_ERR_NO_APN 500 | 
 |  | 
 | #define QSER_APN_NUM 8 | 
 | //default  range: 0 - 7 | 
 | //AT+CGACT range: 1 - 8 | 
 | //1 default IDX, 8 IMS IDX | 
 | #if defined(MBTK_ALL_CID_SUPPORT) | 
 | #if defined(MBTK_SG_SUPPORT) | 
 | #define QSER_PROFILE_IDX_MIN 0 | 
 | #else | 
 | #define QSER_PROFILE_IDX_MIN 1 | 
 | #endif | 
 | #else | 
 | #define QSER_PROFILE_IDX_MIN 1 | 
 | #endif | 
 | #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; | 
 | /****************************VARIABLE***************************************/ | 
 |  | 
 | /******************************FUNC*****************************************/ | 
 | static int qser_apn_info_param_convert(int profile_idx, qser_apn_info_s *new_apn, mbtk_qser_apn_info_s *old_apn) | 
 | { | 
 |     if(new_apn == NULL || old_apn == NULL) | 
 |     { | 
 |         LOGE("[qser_data] qser_apn_info_param_convert apn param is NULL."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |  | 
 |     memset(new_apn, 0x0, sizeof(qser_apn_info_s)); | 
 |     new_apn->profile_idx = old_apn->cid - 1; | 
 |     //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((char *)old_apn->apn_name) > QSER_APN_NAME_SIZE) | 
 |     { | 
 |         LOGE("[qser_data] apn_nmea length verylong."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |     else | 
 |     { | 
 |         if(strlen((char *)old_apn->apn_name) > 0) | 
 |         { | 
 |             memcpy(new_apn->apn_name, old_apn->apn_name,strlen((char *)old_apn->apn_name)); | 
 |         } | 
 |     } | 
 |  | 
 |     //get apn user | 
 |     if(strlen((char *)old_apn->user_name) > QSER_APN_USERNAME_SIZE) | 
 |     { | 
 |         LOGE("[qser_data] apn_user length verylong."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |     else | 
 |     { | 
 |         if(strlen((char *)old_apn->user_name) > 0) | 
 |         { | 
 |             memcpy(new_apn->username, old_apn->user_name, strlen((char *)old_apn->user_name)); | 
 |         } | 
 |     } | 
 |  | 
 |     //get apn password | 
 |     if(strlen((char *)old_apn->user_pass) > QSER_APN_PASSWORD_SIZE) | 
 |     { | 
 |         LOGE("[qser_data] apn_password length verylong."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |     else | 
 |     { | 
 |         if(strlen((char *)old_apn->user_pass) > 0) | 
 |         { | 
 |             memcpy(new_apn->password, old_apn->user_pass, strlen((char *)old_apn->user_pass)); | 
 |         } | 
 |     } | 
 |  | 
 |     //get apn proto | 
 |     new_apn->auth_proto = (qser_apn_auth_proto_e)old_apn->auth_proto; | 
 |  | 
 |     //get apn type | 
 |     if(strlen((char *)old_apn->apn_type) > QSER_APN_PASSWORD_SIZE) | 
 |     { | 
 |         LOGE("[qser_data] apn_type length verylong."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |     else | 
 |     { | 
 |         if(strlen((char *)old_apn->apn_type) > 0) | 
 |         { | 
 |             memcpy(new_apn->apn_type, old_apn->apn_type, strlen((char *)old_apn->apn_type)); | 
 |         } | 
 |     } | 
 |  | 
 |     return QSER_RESULT_SUCCESS; | 
 | } | 
 |  | 
 | static void qser_state_init(qser_data_call_state_s *state) | 
 | { | 
 |     if(state != NULL) | 
 |     { | 
 |         state->profile_idx = 0; | 
 |         memset(state->name, 0x0, 16); | 
 |         state->ip_family = QSER_DATA_CALL_TYPE_IPV4V6; | 
 |         state->state = QSER_DATA_CALL_DISCONNECTED; | 
 |         state->err = QSER_DATA_CALL_ERROR_NONE; | 
 |         inet_aton("0.0.0.0", &(state->v4.ip)); | 
 |         inet_aton("0.0.0.0", &(state->v4.gateway)); | 
 |         inet_aton("0.0.0.0", &(state->v4.pri_dns)); | 
 |         inet_aton("0.0.0.0", &(state->v4.sec_dns)); | 
 |         inet_pton(AF_INET6, "::", &(state->v6.ip)); | 
 |         inet_pton(AF_INET6, "::", &(state->v6.gateway)); | 
 |         inet_pton(AF_INET6, "::", &(state->v6.pri_dns)); | 
 |         inet_pton(AF_INET6, "::", &(state->v6.sec_dns)); | 
 |     } | 
 | } | 
 |  | 
 | 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(*net_data > 100 && *net_data < 200) | 
 |     { | 
 |         int idx = *net_data - 101; | 
 |         if(idx <= QSER_PROFILE_IDX_MAX) | 
 |         { | 
 |             qser_data_call_state_s state = {0}; | 
 |             qser_state_init(&state); | 
 |             state.profile_idx = idx; | 
 |             state.state = QSER_DATA_CALL_DISCONNECTED; | 
 |             if(qser_net_status_cb != NULL) | 
 |             { | 
 |                 qser_net_status_cb(&state); | 
 |             } | 
 |         } | 
 |         else | 
 |         { | 
 |             LOGE("[qser_data] cb fail,idx is %d.", idx); | 
 |         } | 
 |          | 
 |     } | 
 |     else if(*net_data > 200) | 
 |     { | 
 |         LOGE("[qser_data] cid[%d] is open.", *net_data - 201); | 
 |     } | 
 |     else if(*net_data == 1) | 
 |     { | 
 |         LOGE("[qser_data] pdp is open."); | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("[qser_data] unkonwn param [%d].", *net_data); | 
 |     } | 
 | } | 
 |  | 
 | static void* data_call_async_thread(void* arg) | 
 | { | 
 |     qser_data_call_error_e err; | 
 |      | 
 |     qser_data_call_s qser_data_backup = {0}; | 
 |     if(arg != NULL) | 
 |     { | 
 |         memcpy(&qser_data_backup, (qser_data_call_s *)arg, sizeof(qser_data_call_s)); | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("[qser_data] arg is NULL."); | 
 |     } | 
 |  | 
 |     qser_data_call_state_s state = {0}; | 
 |     qser_state_init(&state); | 
 |     state.profile_idx = qser_data_backup.profile_idx; | 
 |     state.ip_family = qser_data_backup.ip_family; | 
 |      | 
 |     int ret = qser_data_call_start(&qser_data_backup, &err); | 
 |     if(ret != QSER_RESULT_SUCCESS) | 
 |     { | 
 |         LOGE("[qser_data] qser_data_call_start() fail."); | 
 |         state.err = err; | 
 |         if(qser_net_status_cb != NULL) | 
 |         { | 
 |             qser_net_status_cb(&state); | 
 |         } | 
 |     } | 
 |  | 
 |     qser_data_call_info_s info = {0}; | 
 |     ret = qser_data_call_info_get(qser_data_backup.profile_idx, qser_data_backup.ip_family, &info, &err); | 
 |     if(ret != QSER_RESULT_SUCCESS) | 
 |     { | 
 |         LOGE("[qser_data] qser_data_call_info_get() fail."); | 
 |         state.err = err; | 
 |         if(qser_net_status_cb != NULL) | 
 |         { | 
 |             qser_net_status_cb(&state); | 
 |         } | 
 |     } | 
 |      | 
 |     snprintf(state.name, 16, "ccinet%d", qser_data_backup.profile_idx); | 
 |     state.state = QSER_DATA_CALL_CONNECTED; | 
 |     state.err = err; | 
 |     memcpy(&(state.v4), &(info.v4.addr), sizeof(struct v4_address_status)); | 
 |     memcpy(&(state.v6), &(info.v6.addr), sizeof(struct v6_address_status)); | 
 |     if(qser_net_status_cb != NULL) | 
 |     { | 
 |         qser_net_status_cb(&state); | 
 |     } | 
 |     return NULL; | 
 | } | 
 |  | 
 | /******************************FUNC*****************************************/ | 
 |  | 
 | /****************************API***************************************/ | 
 | int qser_data_call_init(qser_data_call_evt_cb_t 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] 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; | 
 |  | 
 |     LOGE("[qser_data] mbtk_info_handle_get() success."); | 
 |     return QSER_RESULT_SUCCESS; | 
 | } | 
 |  | 
 | void qser_data_call_destroy(void) | 
 | { | 
 |     if(qser_info_handle) | 
 |     { | 
 |         LOGE("[qser_data] 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] mbtk_info_handle_free() fail."); | 
 |             } | 
 |             else | 
 |             { | 
 |                 qser_info_handle_num = 0; | 
 |                 qser_info_handle = NULL; | 
 |                 qser_net_status_cb = NULL; | 
 |                 inited = FALSE; | 
 |             } | 
 |         }  | 
 |         else | 
 |         { | 
 |             qser_info_handle_num--; | 
 |             qser_net_status_cb = NULL; | 
 |         } | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("[qser_data] 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); | 
 |     if(data_call == NULL || err == NULL) | 
 |     { | 
 |         LOGE("[qser_data] 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] handle is NULL."); | 
 |         *err = QSER_DATA_CALL_ERROR_NO_INIT; | 
 |         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] mbtk_data_call_start fail.[ret = %d]", ret); | 
 |         if(ret == MBTK_INFO_ERR_CID_EXIST) | 
 |         { | 
 |             *err = QSER_DATA_CALL_ERROR_PDP_ACTIVATE; | 
 |         } | 
 |         else | 
 |         { | 
 |             *err = QSER_DATA_CALL_ERROR_UNKNOWN; | 
 |         } | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |     else | 
 |     { | 
 |         *err = QSER_DATA_CALL_ERROR_NONE; | 
 |     } | 
 |  | 
 |     return QSER_RESULT_SUCCESS; | 
 | } | 
 |  | 
 | int qser_data_call_start_async(qser_data_call_s *data_call, qser_data_call_error_e *err) | 
 | { | 
 |     //UNUSED(data_call); | 
 |     UNUSED(err); | 
 |     if(data_call == NULL || err == NULL) | 
 |     { | 
 |         LOGE("[qser_data] 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] handle is NULL."); | 
 |         *err = QSER_DATA_CALL_ERROR_NO_INIT; | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |  | 
 |     pthread_attr_t thread_attr; | 
 |     pthread_t data_call_thread_id; | 
 |     pthread_attr_init(&thread_attr); | 
 |     if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED)) | 
 |     { | 
 |         LOGE("[qser_data] pthread_attr_setdetachstate() fail."); | 
 |         *err = QSER_DATA_CALL_ERROR_UNKNOWN; | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |  | 
 |     //memcpy(&qser_data_backup, data_call, sizeof(qser_data_call_s)); | 
 |     if(pthread_create(&data_call_thread_id, &thread_attr, data_call_async_thread, (void *) data_call)) | 
 |     { | 
 |         LOGE("[qser_data] pthread_create() fail."); | 
 |         *err = QSER_DATA_CALL_ERROR_UNKNOWN; | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |     pthread_attr_destroy(&thread_attr); | 
 |      | 
 |     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(ip_family); | 
 |     //UNUSED(err); | 
 |     if(err == NULL) | 
 |     { | 
 |         LOGE("[qser_data] err is NULL."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |  | 
 |     if(qser_info_handle == NULL) | 
 |     { | 
 |         LOGE("[qser_data] handle is NULL."); | 
 |         *err = QSER_DATA_CALL_ERROR_NO_INIT; | 
 |         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] mbtk_data_call_stop fail.[ret = %d]", ret); | 
 |         if(ret == MBTK_INFO_ERR_CID_NO_EXIST) | 
 |         { | 
 |             *err = QSER_DATA_CALL_ERROR_PDP_NO_ACTIVATE; | 
 |         } | 
 |         else | 
 |         { | 
 |             *err = QSER_DATA_CALL_ERROR_UNKNOWN; | 
 |         } | 
 |         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(ip_family); | 
 |     //UNUSED(info); | 
 |     //UNUSED(err); | 
 |  | 
 |     if(info == NULL || err == NULL) | 
 |     { | 
 |         LOGE("[qser_data] 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] handle is NULL."); | 
 |         *err = QSER_DATA_CALL_ERROR_NO_INIT; | 
 |         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] mbtk_data_call_state_get fail.[ret = %d]", ret); | 
 |         if(ret == MBTK_INFO_ERR_CID_NO_EXIST) | 
 |         { | 
 |             *err = QSER_DATA_CALL_ERROR_PDP_NO_ACTIVATE; | 
 |         } | 
 |         else | 
 |         { | 
 |             *err = QSER_DATA_CALL_ERROR_UNKNOWN; | 
 |         } | 
 |         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); | 
 |             info->v4.addr.ip.s_addr = ipv4.IPAddr; | 
 |             info->v4.addr.pri_dns.s_addr = ipv4.PrimaryDNS; | 
 |             info->v4.addr.sec_dns.s_addr = ipv4.SecondaryDNS; | 
 |  | 
 | #ifdef QSER_TEST | 
 |             //LOGE("[qser_data] IP: %x pri_DNS: %x sec_DNS: %x.", ipv4.IPAddr, ipv4.PrimaryDNS, ipv4.SecondaryDNS); | 
 |             if(inet_ntop(AF_INET, &(info->v4.addr.ip), v4_buff, 32) == NULL) { | 
 |                 LOGE("[qser_data] IP error."); | 
 |             } else { | 
 |                 LOGE("[qser_data] IP : %s", v4_buff); | 
 |             } | 
 |             if(inet_ntop(AF_INET, &(info->v4.addr.pri_dns), v4_buff, 32) == NULL) { | 
 |                 LOGE("[qser_data] PrimaryDNS error."); | 
 |             } else { | 
 |                 LOGE("[qser_data] PrimaryDNS : %s", v4_buff); | 
 |             } | 
 |             if(inet_ntop(AF_INET, &(info->v4.addr.sec_dns), v4_buff, 32) == NULL) { | 
 |                 LOGE("[qser_data] SecondaryDNS error."); | 
 |             } else { | 
 |                 LOGE("[qser_data] 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), sizeof(ipv6.IPV6Addr)); | 
 |             memcpy(&(info->v6.addr.pri_dns), &(ipv6.PrimaryDNS), sizeof(ipv6.PrimaryDNS)); | 
 |             memcpy(&(info->v6.addr.sec_dns), &(ipv6.SecondaryDNS), sizeof(ipv6.SecondaryDNS)); | 
 | #ifdef QSER_TEST | 
 | 			if(ipv6_2_str(&(info->v6.addr.ip), v6_buff)) | 
 |             { | 
 | 				LOGE("[qser_data] IP error."); | 
 | 			} else { | 
 | 				LOGE("[qser_data] IP : %s", v6_buff); | 
 | 			} | 
 | 			if(ipv6_2_str(&(info->v6.addr.pri_dns), v6_buff)) | 
 |             { | 
 | 				LOGE("[qser_data] PrimaryDNS error."); | 
 | 			} else { | 
 | 				LOGE("[qser_data] PrimaryDNS : %s", v6_buff); | 
 | 			} | 
 | 			if(ipv6_2_str(&(info->v6.addr.sec_dns), v6_buff)) | 
 |             { | 
 | 				LOGE("[qser_data] SecondaryDNS error."); | 
 | 			} else { | 
 | 				LOGE("[qser_data] 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); | 
 |     if(qser_info_handle == NULL) | 
 |     { | 
 |         LOGE("[qser_data] handle is NULL."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |      | 
 |     if(apn == NULL) | 
 |     { | 
 |         LOGE("[qser_data] apn param is NULL."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |  | 
 |     int ret = 0; | 
 |     mbtk_qser_apn_info_s apninfo; | 
 |     memset(&apninfo, 0x0, sizeof(mbtk_qser_apn_info_s)); | 
 |     apninfo.cid = apn->profile_idx + 1; | 
 |      | 
 |     if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV4) | 
 |     { | 
 |         apninfo.ip_type = MBTK_IP_TYPE_IP; | 
 |     } | 
 |     else if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV6) | 
 |     { | 
 |         apninfo.ip_type = MBTK_IP_TYPE_IPV6; | 
 |     } | 
 |     else if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV4V6) | 
 |     { | 
 |         apninfo.ip_type = MBTK_IP_TYPE_IPV4V6; | 
 |     } | 
 |     else if(apn->pdp_type == QSER_APN_PDP_TYPE_PPP) | 
 |     { | 
 |         apninfo.ip_type = MBTK_IP_TYPE_PPP; | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("[qser_data] pdp_type error."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |  | 
 |      | 
 |     apninfo.req_type = MBTK_APN_REQ_TYPE_SET; | 
 |     apninfo.auth_proto = (mbtk_apn_auth_proto_enum)apn->auth_proto; | 
 |     if(strlen(apn->apn_name)) | 
 |     { | 
 |         memcpy(apninfo.apn_name, apn->apn_name, strlen(apn->apn_name)); | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("[qser_data] apn_name is NULL."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |     if(strlen(apn->username)) | 
 |     { | 
 |         memcpy(apninfo.user_name, apn->username, strlen(apn->username)); | 
 |     } | 
 |     if(strlen(apn->password)) | 
 |     { | 
 |         memcpy(apninfo.user_pass, apn->password, strlen(apn->password)); | 
 |     } | 
 |     if(strlen(apn->apn_type)) | 
 |     { | 
 |         memcpy(apninfo.apn_type, apn->apn_type, strlen(apn->apn_type)); | 
 |     } | 
 |     ret = mbtk_qser_apn_set(qser_info_handle, &apninfo, NULL); | 
 |     if(ret != 0) | 
 |     { | 
 |         LOGE("[qser_data] mbtk_qser_apn_set fail."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |  | 
 |     return QSER_RESULT_SUCCESS; | 
 | } | 
 |  | 
 | int qser_apn_get(unsigned char profile_idx, qser_apn_info_s *apn) | 
 | { | 
 |     //UNUSED(profile_idx); | 
 |     //UNUSED(apn); | 
 |     if(qser_info_handle == NULL) | 
 |     { | 
 |         LOGE("[qser_data] handle is NULL."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |      | 
 |     if(apn == NULL) | 
 |     { | 
 |         LOGE("[qser_data] apn param is NULL."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |  | 
 |     //get apn info | 
 |     mbtk_qser_apn_info_s apns[10] = {0}; | 
 |     int apn_num = 10; | 
 |     int ret = mbtk_qser_apn_get(qser_info_handle, &apn_num, apns); | 
 |     if(ret != 0) | 
 |     { | 
 |         LOGE("[qser_data] 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] find IDX."); | 
 |                 break; | 
 |             } | 
 |         } | 
 |  | 
 |         if(i == apn_num) | 
 |         { | 
 |             LOGE("[qser_data] 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] 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) | 
 | { | 
 |     //UNUSED(apn); | 
 |     //UNUSED(profile_idx); | 
 |     if(qser_info_handle == NULL) | 
 |     { | 
 |         LOGE("[qser_data] handle is NULL."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |      | 
 |     if(apn == NULL || profile_idx == NULL) | 
 |     { | 
 |         LOGE("[qser_data] apn param is NULL."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |  | 
 |     int ret = 0; | 
 |     unsigned char idx[2] = {0}; | 
 |     mbtk_qser_apn_info_s apninfo; | 
 |     memset(&apninfo, 0x0, sizeof(mbtk_qser_apn_info_s)); | 
 |     apninfo.cid = 0; | 
 |      | 
 |     if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV4) | 
 |     { | 
 |         apninfo.ip_type = MBTK_IP_TYPE_IP; | 
 |     } | 
 |     else if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV6) | 
 |     { | 
 |         apninfo.ip_type = MBTK_IP_TYPE_IPV6; | 
 |     } | 
 |     else if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV4V6) | 
 |     { | 
 |         apninfo.ip_type = MBTK_IP_TYPE_IPV4V6; | 
 |     } | 
 |     else if(apn->pdp_type == QSER_APN_PDP_TYPE_PPP) | 
 |     { | 
 |         apninfo.ip_type = MBTK_IP_TYPE_PPP; | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("[qser_data] pdp_type error."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |  | 
 |     apninfo.req_type = MBTK_APN_REQ_TYPE_ADD; | 
 |     apninfo.auth_proto = (mbtk_apn_auth_proto_enum)apn->auth_proto; | 
 |     if(strlen(apn->apn_name)) | 
 |     { | 
 |         memcpy(apninfo.apn_name, apn->apn_name, strlen(apn->apn_name)); | 
 |     } | 
 |  | 
 |     if(strlen(apn->username)) | 
 |     { | 
 |         memcpy(apninfo.user_name, apn->username, strlen(apn->username)); | 
 |     } | 
 |     if(strlen(apn->password)) | 
 |     { | 
 |         memcpy(apninfo.user_pass, apn->password, strlen(apn->password)); | 
 |     } | 
 |     if(strlen(apn->apn_type)) | 
 |     { | 
 |         memcpy(apninfo.apn_type, apn->apn_type, strlen(apn->apn_type)); | 
 |     } | 
 |     ret = mbtk_qser_apn_set(qser_info_handle, &apninfo, idx); | 
 |     if(ret != 0) | 
 |     { | 
 |         LOGE("[qser_data] mbtk_qser_apn_set fail."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |     *profile_idx = idx[0] - 1; | 
 |     return QSER_RESULT_SUCCESS; | 
 | } | 
 |  | 
 | int qser_apn_del(unsigned char profile_idx) | 
 | { | 
 |     int ret = 0; | 
 |  | 
 |     //UNUSED(profile_idx); | 
 |     if(qser_info_handle == NULL) | 
 |     { | 
 |         LOGE("[qser_data] handle is NULL."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |  | 
 |     ret = mbtk_apn_del(qser_info_handle, profile_idx); | 
 |     if(ret < 0) | 
 |     { | 
 |         LOGE("[qser_data] mbtk_apn_del fail!"); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |     return QSER_RESULT_SUCCESS; | 
 | } | 
 |  | 
 | int qser_apn_get_list(qser_apn_info_list_s *apn_list) | 
 | { | 
 |     //UNUSED(apn_list); | 
 |  | 
 |     if(qser_info_handle == NULL) | 
 |     { | 
 |         LOGE("[qser_data] handle is NULL."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |      | 
 |     if(apn_list == NULL) | 
 |     { | 
 |         LOGE("[qser_data] apn_list param is NULL."); | 
 |         return QSER_RESULT_FAIL; | 
 |     } | 
 |  | 
 |     mbtk_qser_apn_info_s apns[10] = {0}; | 
 |     int apn_num = 10; | 
 |     int ret = mbtk_qser_apn_get(qser_info_handle, &apn_num, apns); | 
 |     if(ret != 0) | 
 |     { | 
 |         if(ret == MBTK_INFO_ERR_NO_APN) | 
 |         { | 
 |             apn_list->cnt = 0; | 
 |             return QSER_RESULT_SUCCESS; | 
 |         } | 
 |         LOGE("[qser_data] 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; | 
 |             apn_list->cnt = 0; | 
 |             for(i = 0; i < apn_num; i++) | 
 |             { | 
 |                 if(qser_apn_info_param_convert(apns[i].cid - 1, &apn_list->apn[apn_list->cnt], &apns[i]) != 0) | 
 |                 { | 
 |                     LOGE("[qser_data] qser_apn_info_param_convert fail"); | 
 |                     return QSER_RESULT_FAIL; | 
 |                 } | 
 |                 apn_list->cnt++; | 
 |             } | 
 |         } | 
 |         else if(apn_num > QSER_APN_MAX_LIST) | 
 |         { | 
 |             LOGE("[qser_data] apn_num overlong"); | 
 |             return QSER_RESULT_FAIL; | 
 |         } | 
 |         else | 
 |         { | 
 |             apn_list->cnt = 0; | 
 |         } | 
 |     } | 
 |     return QSER_RESULT_SUCCESS; | 
 | } | 
 | /****************************API***************************************/ | 
 |  |