| #include "ql_type.h" | 
 | #include "ql_data_call.h" | 
 | #include "mbtk_info_api.h" | 
 |  | 
 | typedef struct { | 
 |     int apn_id; | 
 |     ql_data_call_apn_config_t apn_info; | 
 | } mbtk_data_call_apn_param_info_t; | 
 |  | 
 | typedef struct { | 
 |     QL_NET_DATA_CALL_RECONNECT_MODE_E reconnect_mode; | 
 |     int time_num; | 
 |     int time_list[QL_NET_MAX_RECONNECT_INTERVAL_LEN]; | 
 |     mbtk_data_call_apn_param_info_t *apn_param;     // Point to data_call_apn_param_list. | 
 | } mbtk_data_call_param_info_t; | 
 |  | 
 | typedef struct { | 
 |     ql_data_call_item_t call_info; | 
 |     int is_background; | 
 |  | 
 |     ql_data_call_status_t call_state; | 
 |  | 
 |     mbtk_data_call_param_info_t call_param_info; | 
 | } mbtk_data_call_info_t; | 
 |  | 
 | static mbtk_info_handle_t* ql_info_handle = NULL; | 
 | static mbtk_data_call_info_t data_call_info[QL_NET_MAX_DATA_CALL_NUM]; | 
 | static mbtk_data_call_apn_param_info_t data_call_apn_param_list[QL_NET_MAX_DATA_CALL_NUM]; | 
 | static ql_data_call_service_error_cb_f data_call_service_error_cb = NULL; | 
 | static ql_data_call_status_ind_cb_f data_call_status_ind_cb = NULL; | 
 |  | 
 | static int call_index_get_by_call_id(int call_id) | 
 | { | 
 |     int i = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_info[i].call_info.call_id == call_id) { | 
 |             break; | 
 |         } | 
 |         i++; | 
 |     } | 
 |  | 
 |     if(i == QL_NET_MAX_DATA_CALL_NUM) { | 
 |         return -1; | 
 |     } else { | 
 |         return i; | 
 |     } | 
 | } | 
 |  | 
 | static int call_index_get_by_apn_id(int apn_id) | 
 | { | 
 |     int i = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_info[i].call_param_info.apn_param && | 
 |             data_call_info[i].call_param_info.apn_param->apn_id == apn_id) { | 
 |             break; | 
 |         } | 
 |         i++; | 
 |     } | 
 |  | 
 |     if(i == QL_NET_MAX_DATA_CALL_NUM) { | 
 |         return -1; | 
 |     } else { | 
 |         return i; | 
 |     } | 
 | } | 
 |  | 
 | static void data_call_info_list_print() | 
 | { | 
 |     int i = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_info[i].call_info.call_id > 0) { | 
 |             LOGD("CALL START : call_id - %d, call_name - %s, is_background - %d", data_call_info[i].call_info.call_id, data_call_info[i].call_info.call_name, | 
 |                 data_call_info[i].is_background); | 
 |             LOGD("call_state : ip_ver - %d, call_status - %d, device - %s", data_call_info[i].call_state.ip_ver, | 
 |             data_call_info[i].call_state.call_status, data_call_info[i].call_state.device); | 
 |             LOGD("param_info : reconnect_mode - %d, time_num - %d", data_call_info[i].call_param_info.reconnect_mode, | 
 |                 data_call_info[i].call_param_info.time_num); | 
 |             int j = 0; | 
 |             while(j < data_call_info[i].call_param_info.time_num) { | 
 |                 LOGD("time_item[%d] - %d", j, data_call_info[i].call_param_info.time_list[j]); | 
 |                 j++; | 
 |             } | 
 |  | 
 |             if(data_call_info[i].call_param_info.apn_param) { | 
 |                 LOGD("apn_param : apn_id - %d, auth_pref - %d, ip_ver - %d, apn_name - %s, username - %s, password - %s", data_call_info[i].call_param_info.apn_param->apn_id, | 
 |                     data_call_info[i].call_param_info.apn_param->apn_info.auth_pref, | 
 |                     data_call_info[i].call_param_info.apn_param->apn_info.ip_ver, | 
 |                     data_call_info[i].call_param_info.apn_param->apn_info.apn_name, | 
 |                     data_call_info[i].call_param_info.apn_param->apn_info.username, | 
 |                     data_call_info[i].call_param_info.apn_param->apn_info.password); | 
 |             } else { | 
 |                 LOGE("data_call_info[i]->call_param_info->apn_param is NULL."); | 
 |             } | 
 |         } | 
 |         i++; | 
 |     } | 
 | } | 
 |  | 
 | static void data_call_info_item_print(int call_id) | 
 | { | 
 |     int i = call_index_get_by_call_id(call_id); | 
 |     if(i >= 0) { | 
 |         LOGD("CALL START : call_id - %d, call_name - %s, is_background - %d", data_call_info[i].call_info.call_id, data_call_info[i].call_info.call_name, | 
 |             data_call_info[i].is_background); | 
 |         LOGD("call_state : ip_ver - %d, call_status - %d, device - %s", data_call_info[i].call_state.ip_ver, | 
 |         data_call_info[i].call_state.call_status, data_call_info[i].call_state.device); | 
 |         LOGD("param_info : reconnect_mode - %d, time_num - %d", data_call_info[i].call_param_info.reconnect_mode, | 
 |             data_call_info[i].call_param_info.time_num); | 
 |         int j = 0; | 
 |         while(j < data_call_info[i].call_param_info.time_num) { | 
 |             LOGD("time_item[%d] - %d", j, data_call_info[i].call_param_info.time_list[j]); | 
 |             j++; | 
 |         } | 
 |  | 
 |         if(data_call_info[i].call_param_info.apn_param) { | 
 |             LOGD("apn_param : apn_id - %d, auth_pref - %d, ip_ver - %d, apn_name - %s, username - %s, password - %s", data_call_info[i].call_param_info.apn_param->apn_id, | 
 |                 data_call_info[i].call_param_info.apn_param->apn_info.auth_pref, | 
 |                 data_call_info[i].call_param_info.apn_param->apn_info.ip_ver, | 
 |                 data_call_info[i].call_param_info.apn_param->apn_info.apn_name, | 
 |                 data_call_info[i].call_param_info.apn_param->apn_info.username, | 
 |                 data_call_info[i].call_param_info.apn_param->apn_info.password); | 
 |         } else { | 
 |             LOGE("data_call_info[i]->call_param_info->apn_param is NULL."); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | static void ril_server_state_cb(const void* data, int data_len) | 
 | { | 
 |     if(data != NULL && data_len == sizeof(int)) { | 
 |         const int *state = (const int*)data; | 
 |         if(*state) { | 
 |             if(data_call_service_error_cb) { | 
 |                 data_call_service_error_cb(QL_ERR_ABORTED); | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | static void data_call_state_change_cb(const void* data, int data_len) | 
 | { | 
 |     LOGD("data_call_state_change_cb() start."); | 
 |     if(data == NULL || data_len == 0) | 
 |     { | 
 |         return; | 
 |     } | 
 |  | 
 |     // data_call_info_print(); | 
 |  | 
 |     uint8 *net_data = NULL; | 
 |     net_data = (uint8 *)data; | 
 |  | 
 |     if(*net_data > 100 && *net_data < 200) | 
 |     { | 
 |         int apn_id = *net_data - 100; | 
 |         if(apn_id <= QL_NET_MAX_DATA_CALL_NUM) | 
 |         { | 
 |             int i = 0; | 
 |             while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |  | 
 |                 if(data_call_info[i].call_param_info.apn_param) { | 
 |                     if(data_call_info[i].call_param_info.apn_param->apn_id == apn_id) { | 
 |                         break; | 
 |                     } else { | 
 |                         LOGD("call_id = %d, apn_id = %d", data_call_info[i].call_info.call_id, | 
 |                             data_call_info[i].call_param_info.apn_param->apn_id); | 
 |                     } | 
 |                 } | 
 |                 i++; | 
 |             } | 
 |  | 
 |             if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this apn_id. | 
 |                 LOGW("Unknown apn_id : %d", apn_id); | 
 |                 return; | 
 |             } else { | 
 |                 QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status; | 
 |                 data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED; | 
 |                 if(data_call_status_ind_cb) { | 
 |                     data_call_status_ind_cb(data_call_info[i].call_info.call_id, pre_call_status, | 
 |                         &(data_call_info[i].call_state)); | 
 |                 } | 
 |             } | 
 |         } | 
 |         else | 
 |         { | 
 |             LOGE("[qser_data] cb fail,idx is %d.", apn_id); | 
 |         } | 
 |  | 
 |     } | 
 |     else if(*net_data > 200 && *net_data < 220) | 
 |     { | 
 |         LOGE("[qser_data] cid[%d] is open.", *net_data - 200); | 
 |     } | 
 |     else if(*net_data > 220) | 
 |     { | 
 |         LOGE("[qser_data] cid[%d] is reopen.", *net_data - 220); | 
 |         int apn_id = *net_data - 220; | 
 |         if(apn_id <= QL_NET_MAX_DATA_CALL_NUM) | 
 |         { | 
 |             int i = 0; | 
 |             while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |                 if(data_call_info[i].call_param_info.apn_param | 
 |                     && data_call_info[i].call_param_info.apn_param->apn_id == apn_id) { | 
 |                     break; | 
 |                 } | 
 |                 i++; | 
 |             } | 
 |  | 
 |             if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this apn_id. | 
 |                 LOGW("Unknown apn_id : %d", apn_id); | 
 |                 return; | 
 |             } else { | 
 |                 QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status; | 
 |                 data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED; | 
 |                 if(data_call_status_ind_cb) { | 
 |                     data_call_status_ind_cb(data_call_info[i].call_info.call_id, pre_call_status, | 
 |                         &(data_call_info[i].call_state)); | 
 |                 } | 
 |             } | 
 |         } | 
 |     } | 
 |     else if(*net_data == 1) | 
 |     { | 
 |         LOGE("[qser_data] pdp is open."); | 
 |     } | 
 |     else | 
 |     { | 
 |         LOGE("[qser_data] unkonwn param [%d].", *net_data); | 
 |     } | 
 | } | 
 |  | 
 | static int data_call_state_query(int call_id) | 
 | { | 
 |     int i = call_index_get_by_call_id(call_id); | 
 |     if(i < 0) { | 
 |         LOGE("Unknown call_id : %d", call_id); | 
 |         return -1; | 
 |     } | 
 |  | 
 |     // Get network information. | 
 |     mbtk_ipv4_info_t ipv4; | 
 |     mbtk_ipv6_info_t ipv6; | 
 |     QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status; | 
 |     int ret = mbtk_data_call_state_get(ql_info_handle, data_call_info[i].call_param_info.apn_param->apn_id, &ipv4, &ipv6); | 
 |     if(ret != 0) | 
 |     { | 
 |         LOGE("mbtk_data_call_state_get fail.[ret = %d]", ret); | 
 |         data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_ERROR; | 
 |         return -1; | 
 |     } | 
 |     else | 
 |     { | 
 |         data_call_info[i].call_state.has_addr = ipv4.valid; | 
 |         if(ipv4.valid) | 
 |         { | 
 |             if(inet_ntop(AF_INET, &(ipv4.IPAddr), data_call_info[i].call_state.addr.addr , QL_NET_MAX_ADDR_LEN) == NULL) { | 
 |                 LOGE("IPv4 error."); | 
 |             } else { | 
 |                 LOGD("IPv4 : %s", data_call_info[i].call_state.addr.addr); | 
 |             } | 
 |  | 
 |             if(inet_ntop(AF_INET, &(ipv4.NetMask), data_call_info[i].call_state.addr.netmask , QL_NET_MAX_ADDR_LEN) == NULL) { | 
 |                 LOGE("NetMask error."); | 
 |             } else { | 
 |                 LOGD("NetMask : %s", data_call_info[i].call_state.addr.netmask); | 
 |             } | 
 |  | 
 |             if(inet_ntop(AF_INET, &(ipv4.GateWay), data_call_info[i].call_state.addr.gateway , QL_NET_MAX_ADDR_LEN) == NULL) { | 
 |                 LOGE("GateWay error."); | 
 |             } else { | 
 |                 LOGD("GateWay : %s", data_call_info[i].call_state.addr.gateway); | 
 |             } | 
 |  | 
 |             if(inet_ntop(AF_INET, &(ipv4.PrimaryDNS), data_call_info[i].call_state.addr.dnsp , QL_NET_MAX_ADDR_LEN) == NULL) { | 
 |                 LOGE("PrimaryDNS error."); | 
 |             } else { | 
 |                 LOGD("PrimaryDNS : %s", data_call_info[i].call_state.addr.dnsp); | 
 |             } | 
 |  | 
 |             if(inet_ntop(AF_INET, &(ipv4.SecondaryDNS), data_call_info[i].call_state.addr.dnss , QL_NET_MAX_ADDR_LEN) == NULL) { | 
 |                 LOGE("SecondaryDNS error."); | 
 |             } else { | 
 |                 LOGD("SecondaryDNS : %s", data_call_info[i].call_state.addr.dnss); | 
 |             } | 
 |         } | 
 |  | 
 |         data_call_info[i].call_state.has_addr6 = ipv6.valid; | 
 |         if(ipv6.valid) | 
 |         { | 
 |             if(ipv6_2_str(&(ipv6.IPV6Addr), data_call_info[i].call_state.addr6.addr)) { | 
 |                 LOGE("IPv6 error."); | 
 |             } else { | 
 |                 LOGD("IPv6 : %s", data_call_info[i].call_state.addr6.addr); | 
 |             } | 
 |  | 
 |             if(ipv6_2_str(&(ipv6.NetMask), data_call_info[i].call_state.addr6.prefix)) { | 
 |                 LOGE("prefix error."); | 
 |             } else { | 
 |                 LOGD("prefix : %s", data_call_info[i].call_state.addr6.prefix); | 
 |             } | 
 |  | 
 |             if(ipv6_2_str(&(ipv6.GateWay), data_call_info[i].call_state.addr6.gateway)) { | 
 |                 LOGE("GateWay error."); | 
 |             } else { | 
 |                 LOGD("GateWay : %s", data_call_info[i].call_state.addr6.gateway); | 
 |             } | 
 |  | 
 |             if(ipv6_2_str(&(ipv6.PrimaryDNS), data_call_info[i].call_state.addr6.dnsp)) { | 
 |                 LOGE("PrimaryDNS error."); | 
 |             } else { | 
 |                 LOGD("PrimaryDNS : %s", data_call_info[i].call_state.addr6.dnsp); | 
 |             } | 
 |  | 
 |             if(ipv6_2_str(&(ipv6.SecondaryDNS), data_call_info[i].call_state.addr6.dnsp)) { | 
 |                 LOGE("SecondaryDNS error."); | 
 |             } else { | 
 |                 LOGD("SecondaryDNS : %s", data_call_info[i].call_state.addr6.dnsp); | 
 |             } | 
 |         } | 
 |  | 
 |         pre_call_status = data_call_info[i].call_state.call_status; | 
 | #if 1 | 
 |         if(data_call_info[i].call_state.ip_ver == QL_NET_IP_VER_V4V6) { | 
 |             if(ipv4.valid && !ipv6.valid) { | 
 |                 data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_PARTIAL_V4_CONNECTED; | 
 |             } else if(!ipv4.valid && ipv6.valid) { | 
 |                 data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_PARTIAL_V6_CONNECTED; | 
 |             } else if(ipv4.valid && ipv6.valid) { | 
 |                 data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED; | 
 |             } else { | 
 |                 data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED; | 
 |             } | 
 |         } else if(data_call_info[i].call_state.ip_ver == QL_NET_IP_VER_V4) { | 
 |             if(ipv4.valid) { | 
 |                 data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED; | 
 |             } else { | 
 |                 data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED; | 
 |             } | 
 |         } else if(data_call_info[i].call_state.ip_ver == QL_NET_IP_VER_V6) { | 
 |             if(ipv6.valid) { | 
 |                 data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED; | 
 |             } else { | 
 |                 data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED; | 
 |             } | 
 |         } else { | 
 |             data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED; | 
 |         } | 
 | #else | 
 |         if(ipv4.valid && ipv6.valid) { | 
 |             data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED; | 
 |         } else if(!ipv4.valid && ipv6.valid) { | 
 |             data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_PARTIAL_V6_CONNECTED; | 
 |         } else if(ipv4.valid && !ipv6.valid) { | 
 |             data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_PARTIAL_V4_CONNECTED; | 
 |         } else { | 
 |             data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED; | 
 |         } | 
 | #endif | 
 |  | 
 |         if(data_call_status_ind_cb) { | 
 |             data_call_status_ind_cb(call_id, pre_call_status, | 
 |                 &(data_call_info[i].call_state)); | 
 |         } | 
 |     } | 
 |  | 
 |     return 0; | 
 | } | 
 |  | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Initialize the data call service | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   QL_ERR_INVALID_ARG - as defined | 
 |   QL_ERR_UNKNOWN - unknown error, failed to connect to service | 
 |   QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_init(void) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |  | 
 |         mbtk_log_init("radio", "QL_DATA_CALL"); | 
 |  | 
 |         ql_info_handle = mbtk_info_handle_get(); | 
 |         if(ql_info_handle) | 
 |         { | 
 |             memset(&data_call_info, 0, sizeof(data_call_info)); | 
 |             memset(&data_call_apn_param_list, 0, sizeof(data_call_apn_param_list)); | 
 |             return QL_ERR_OK; | 
 |         } else { | 
 |             LOGE("mbtk_info_handle_get() fail."); | 
 |             return QL_ERR_UNKNOWN; | 
 |         } | 
 |     } else { | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Create a data call instance | 
 |   @param[in] call_id The unique identifier of the data call instance, specified by the user | 
 |   @param[in] call_name Friendly data call name,  specified by the user | 
 |   @param[in] is_background Whether the data call status is maintained by the data call service daemon. | 
 |   If it is 0, the data call instance will be deleted after the data call process exits. | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   QL_ERR_INVALID_ARG - as defined | 
 |   QL_ERR_UNKNOWN - unknown error, failed to connect to service | 
 |   QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_create(int call_id, const char *call_name, int is_background) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(call_id <= 0 || call_name == NULL || strlen(call_name) == 0 | 
 |         || strlen(call_name) > QL_NET_MAX_NAME_LEN) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     int i = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_info[i].call_info.call_id == 0) { // Not use. | 
 |             break; | 
 |         } | 
 |         i++; | 
 |     } | 
 |  | 
 |     if(i == QL_NET_MAX_DATA_CALL_NUM) { // data_call item full. | 
 |         LOGW("data_call instance is full."); | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     data_call_info[i].call_info.call_id = call_id; | 
 |     memcpy(data_call_info[i].call_info.call_name, call_name, strlen(call_name)); | 
 |     data_call_info[i].call_state.call_id = call_id; | 
 |     memcpy(data_call_info[i].call_state.call_name, call_name, strlen(call_name)); | 
 |  | 
 |     data_call_info[i].is_background = is_background; | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Alloc for a data call configuration instance | 
 |   @return | 
 |   NULL - Not enough memory | 
 |   Other - successful | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | ql_data_call_param_t *ql_data_call_param_alloc(void) | 
 | { | 
 |     ql_data_call_param_t *result = malloc(sizeof(mbtk_data_call_param_info_t)); | 
 |     if(result) { | 
 |         memset(result, 0, sizeof(mbtk_data_call_param_info_t)); | 
 |     } | 
 |  | 
 |     return result; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Initialize the data call configuration instance | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_init(ql_data_call_param_t *param) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     memset(info, 0, sizeof(mbtk_data_call_param_info_t)); | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Release the data call configuration instance | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_free(ql_data_call_param_t *param) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     free(param); | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Bind APN ID, range:1-16 | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[in] apn_id APN ID, range:1-16 | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_set_apn_id(ql_data_call_param_t *param, int apn_id) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     // 1 - 7 | 
 |     if(param == NULL || apn_id <= 0 || apn_id > QL_NET_MAX_APN_ID) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |  | 
 |     int i = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_apn_param_list[i].apn_id == apn_id) { | 
 |             break; | 
 |         } | 
 |         i++; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     if(info->apn_param != NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     if(i == QL_NET_MAX_DATA_CALL_NUM) { | 
 |         LOGW("No found apn_id : %d.", apn_id); | 
 |         // Found next empty apn item. | 
 |         int j = 0; | 
 |         while(j < QL_NET_MAX_DATA_CALL_NUM) { | 
 |             if(data_call_apn_param_list[j].apn_id <= 0) { | 
 |                 break; | 
 |             } | 
 |             j++; | 
 |         } | 
 |         if(j == QL_NET_MAX_DATA_CALL_NUM) { // Full | 
 |             return QL_ERR_UNKNOWN; | 
 |         } | 
 |  | 
 |         info->apn_param = &(data_call_apn_param_list[j]); | 
 |         info->apn_param->apn_id = apn_id; | 
 |     } else { | 
 |         // Found apn_id | 
 |         info->apn_param = &(data_call_apn_param_list[i]); | 
 |     } | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Get APN name from configuration instance | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[out] buf APN ID | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_get_apn_id(ql_data_call_param_t *param, int *apn_id) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL || apn_id == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     if(info->apn_param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     *apn_id = info->apn_param->apn_id; | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Configure APN name | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[in] apn_name APN name | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_set_apn_name(ql_data_call_param_t *param, const char *apn_name) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL || apn_name == NULL || strlen(apn_name) == 0 | 
 |         || strlen(apn_name) > QL_NET_MAX_APN_NAME_LEN) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     if(info->apn_param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     memcpy(info->apn_param->apn_info.apn_name, apn_name, strlen(apn_name)); | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Get APN name from configuration instance | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[out] buf APN name buffer | 
 |   @param[in] buf_len APN name buffer size | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_get_apn_name(ql_data_call_param_t *param, char *buf, int buf_len) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL || buf == NULL || buf_len <= 0) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     if(info->apn_param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     if(strlen(info->apn_param->apn_info.apn_name) + 1 > buf_len) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     memcpy(buf, info->apn_param->apn_info.apn_name, strlen(info->apn_param->apn_info.apn_name)); | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Configure APN user name | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[in] user_name APN user name | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_set_user_name(ql_data_call_param_t *param, const char *user_name) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL || user_name == NULL || strlen(user_name) == 0 | 
 |         || strlen(user_name) > QL_NET_MAX_APN_USERNAME_LEN) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     if(info->apn_param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     memcpy(info->apn_param->apn_info.username, user_name, strlen(user_name)); | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Get APN user name from configuration instance | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[out] buf APN user name buffer | 
 |   @param[in] buf_len APN user name buffer size | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_get_user_name(ql_data_call_param_t *param, char *buf, int buf_len) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL || buf == NULL || buf_len <= 0) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     if(info->apn_param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     if(strlen(info->apn_param->apn_info.username) + 1 > buf_len) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     memcpy(buf, info->apn_param->apn_info.username, strlen(info->apn_param->apn_info.username)); | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Configure APN user password | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[in] user_password APN user password | 
 |   @return | 
 |   QL_ERR_OK - Not enough memory | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_set_user_password(ql_data_call_param_t *param, const char *user_password) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL || user_password == NULL || strlen(user_password) == 0 | 
 |         || strlen(user_password) > QL_NET_MAX_APN_PASSWORD_LEN) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     if(info->apn_param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     memcpy(info->apn_param->apn_info.password, user_password, strlen(user_password)); | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Get APN user password from configuration instance | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[out] buf APN user password buffer | 
 |   @param[in] buf_len APN user password buffer size | 
 |   @return | 
 |   QL_ERR_OK - Not enough memory | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_get_user_password(ql_data_call_param_t *param, char *buf, int buf_len) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL || buf == NULL || buf_len <= 0) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     if(info->apn_param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     if(strlen(info->apn_param->apn_info.password) + 1 > buf_len) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     memcpy(buf, info->apn_param->apn_info.password, strlen(info->apn_param->apn_info.password)); | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Configure the data call authentication method | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[in] auth_pref Defined by QL_DATA_CALL_AUTH_PREF_E | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_set_auth_pref(ql_data_call_param_t *param, int auth_pref) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     if(info->apn_param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     info->apn_param->apn_info.auth_pref = (QL_NET_AUTH_PREF_E)auth_pref; | 
 |  | 
 |     return QL_ERR_OK; | 
 |  | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Configure the data call authentication method | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[out] p_data Store return value | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_get_auth_pref(ql_data_call_param_t *param, int *p_data) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL || p_data == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     if(info->apn_param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     *p_data = info->apn_param->apn_info.auth_pref; | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Configure the data call IP version | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[in] ip_ver Defined by QL_NET_IP_VER_E | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_set_ip_version(ql_data_call_param_t *param, int ip_ver) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     if(info->apn_param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     info->apn_param->apn_info.ip_ver = (QL_NET_IP_VER_E)ip_ver; | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Get IP version from configuration instance | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[out] p_ver Store return value | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_get_ip_version(ql_data_call_param_t *param, int *p_ver) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL || p_ver == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     if(info->apn_param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     *p_ver = info->apn_param->apn_info.ip_ver; | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Configure the data call auto reconnection mode | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[in] mode Defined by QL_NET_DATA_CALL_RECONNECT_MODE_E | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_set_reconnect_mode(ql_data_call_param_t *param, int reconnect_mode) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     info->reconnect_mode = reconnect_mode; | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Get auto reconnection mode from configuration instance | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[out] p_mode Store return value | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_get_reconnect_mode(ql_data_call_param_t *param, int *p_mode) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL || p_mode == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     *p_mode = info->reconnect_mode; | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Configure the data call auto reconnection interval | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[in] time_list Interval time list in ms | 
 |   @param[in] num Number of time list | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_set_reconnect_interval(ql_data_call_param_t *param, int *time_list, int num) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL || time_list == NULL || num <= 0 || num > QL_NET_MAX_RECONNECT_INTERVAL_LEN) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     info->time_num = num; | 
 |     memcpy(&(info->time_list), time_list, sizeof(int) * num); | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Get auto reconnection interval from configuration instance | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @param[out] time_list Store return value | 
 |   @param[in,out] p_num | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_param_get_reconnect_interval(ql_data_call_param_t *param, int *time_list, int *p_num) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL || time_list == NULL || p_num == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param; | 
 |     *p_num = info->time_num; | 
 |     int i = 0; | 
 |     for(; i < info->time_num; i++) { | 
 |         *(time_list + i) = info->time_list[i]; | 
 |     } | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Configure the specified data call instance | 
 |   @param[in] call_id Specify a data call instance | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_config(int call_id, ql_data_call_param_t *param) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     int i = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_info[i].call_info.call_id == call_id) { | 
 |             break; | 
 |         } | 
 |         i++; | 
 |     } | 
 |  | 
 |     if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this call_id. | 
 |         LOGW("Unknown call_id : %d", call_id); | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     memcpy(&(data_call_info[i].call_param_info), param, sizeof(mbtk_data_call_param_info_t));; | 
 |  | 
 |     if(data_call_info[i].call_param_info.apn_param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |     snprintf(data_call_info[i].call_state.device, QL_NET_MAX_NAME_LEN, "ccinet%d", | 
 |         data_call_info[i].call_param_info.apn_param->apn_id - 1); | 
 |     data_call_info[i].call_state.ip_ver = data_call_info[i].call_param_info.apn_param->apn_info.ip_ver; | 
 |     data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_IDLE; | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Get the specified data call configuration instance | 
 |   @param[in] call_id Specify a data call instance | 
 |   @param[in] param Point to the data call configuration instance | 
 |   @return | 
 |   QL_ERR_OK - Successful | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_get_config(int call_id, ql_data_call_param_t *param) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(param == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     int i = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_info[i].call_info.call_id == call_id) { | 
 |             break; | 
 |         } | 
 |         i++; | 
 |     } | 
 |  | 
 |     if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this call_id. | 
 |         LOGW("Unknown call_id : %d", call_id); | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     memcpy(param, &(data_call_info[i].call_param_info), sizeof(mbtk_data_call_param_info_t)); | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Start data call | 
 |   @param[in] call_id Specify a data call instance | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   QL_ERR_NOT_INIT - uninitialized | 
 |   QL_ERR_SERVICE_NOT_READY - service is not ready | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_start(int call_id) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     int i = call_index_get_by_call_id(call_id); | 
 |     if(i < 0) { | 
 |         LOGE("Unknown call_id : %d", call_id); | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     if(data_call_info[i].call_param_info.apn_param == NULL) { | 
 |         LOGE("data_call_info[i]->call_param_info->apn_param is NULL."); | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     int ret = data_call_state_query(call_id); | 
 |     if(ret) { | 
 |         LOGE("data_call_state_query fail."); | 
 |         data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_IDLE; | 
 |         // return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     if(data_call_info[i].call_state.call_status == QL_NET_DATA_CALL_STATUS_PARTIAL_V4_CONNECTED | 
 |         || data_call_info[i].call_state.call_status == QL_NET_DATA_CALL_STATUS_PARTIAL_V6_CONNECTED | 
 |         || data_call_info[i].call_state.call_status == QL_NET_DATA_CALL_STATUS_CONNECTED) { | 
 |         LOGW("call_id %d has connected.", call_id); | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     LOGD("Start Data Call : %d", call_id); | 
 |     data_call_info_item_print(call_id); | 
 |  | 
 |     // Set APN in the first. | 
 |     mbtk_ip_type_enum ip_type; | 
 |     switch(data_call_info[i].call_param_info.apn_param->apn_info.ip_ver) { | 
 |         case QL_NET_IP_VER_V4: | 
 |             ip_type = MBTK_IP_TYPE_IP; | 
 |             break; | 
 |         case QL_NET_IP_VER_V6: | 
 |             ip_type = MBTK_IP_TYPE_IPV6; | 
 |             break; | 
 |         case QL_NET_IP_VER_V4V6: | 
 |             ip_type = MBTK_IP_TYPE_IPV4V6; | 
 |             break; | 
 |         default: | 
 |             LOGE("Unknown ip_ver."); | 
 |             return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     char auth_type[64]={0}; | 
 |     switch(data_call_info[i].call_param_info.apn_param->apn_info.auth_pref) { | 
 |         case QL_NET_AUTH_PREF_PAP_CHAP_NOT_ALLOWED: | 
 |             memcpy(auth_type,"NONE",strlen("NONE")); | 
 |             break; | 
 |         case QL_NET_AUTH_PREF_PAP_ONLY_ALLOWED: | 
 |             memcpy(auth_type,"PAP",strlen("PAP")); | 
 |             break; | 
 |         case QL_NET_AUTH_PREF_CHAP_ONLY_ALLOWED: | 
 |             memcpy(auth_type,"CHAP",strlen("CHAP")); | 
 |             break; | 
 | #if 0 | 
 |         case QL_NET_AUTH_PREF_PAP_CHAP_BOTH_ALLOWED: | 
 |             apninfo.auth_proto = MBTK_APN_AUTH_PROTO_PAP_CHAP; | 
 |             break; | 
 | #endif | 
 |         default: | 
 |             LOGE("Unknown auth_pref."); | 
 |             return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     ret = mbtk_apn_set(ql_info_handle, data_call_info[i].call_param_info.apn_param->apn_id, ip_type, | 
 |                 data_call_info[i].call_param_info.apn_param->apn_info.apn_name, | 
 |                 data_call_info[i].call_param_info.apn_param->apn_info.username, | 
 |                 data_call_info[i].call_param_info.apn_param->apn_info.password, auth_type); | 
 |     if(ret) { | 
 |         LOGE("mbtk_apn_set fail."); | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     // Start data call. | 
 |     int auto_conn_interval = 0; | 
 |     QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status; | 
 |     data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTING; | 
 |     if(data_call_status_ind_cb) { | 
 |         data_call_status_ind_cb(call_id, pre_call_status, | 
 |             &(data_call_info[i].call_state)); | 
 |     } | 
 |  | 
 |     if(data_call_info[i].call_param_info.reconnect_mode == QL_NET_DATA_CALL_RECONNECT_NORMAL | 
 |         || data_call_info[i].call_param_info.reconnect_mode == QL_NET_DATA_CALL_RECONNECT_MODE_1 | 
 |         || data_call_info[i].call_param_info.reconnect_mode == QL_NET_DATA_CALL_RECONNECT_MODE_2) { | 
 |         if(data_call_info[i].call_param_info.time_num > 0) { | 
 |             auto_conn_interval = data_call_info[i].call_param_info.time_list[0]; | 
 |         } | 
 |     } else { | 
 |         auto_conn_interval = 0; | 
 |     } | 
 |  | 
 |     ret = mbtk_data_call_start(ql_info_handle, data_call_info[i].call_param_info.apn_param->apn_id, auto_conn_interval, | 
 |                 FALSE, 0); | 
 |     if(ret) { | 
 |         LOGE("mbtk_data_call_start fail."); | 
 |         data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_ERROR; | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     ret = data_call_state_query(call_id); | 
 |     if(ret) { | 
 |         LOGE("data_call_state_query fail."); | 
 |         data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_ERROR; | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Stop data call | 
 |   @param[in] call_id Specify a data call instance | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   QL_ERR_NOT_INIT - uninitialized | 
 |   QL_ERR_SERVICE_NOT_READY - service is not ready | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_stop(int call_id) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     int i = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_info[i].call_info.call_id == call_id) { | 
 |             break; | 
 |         } | 
 |         i++; | 
 |     } | 
 |  | 
 |     if(data_call_info[i].call_param_info.apn_param) { | 
 |         int ret = mbtk_data_call_stop(ql_info_handle, data_call_info[i].call_param_info.apn_param->apn_id, 15); | 
 |         if(ret) { | 
 |             LOGE("mbtk_data_call_stop() fail."); | 
 |             return QL_ERR_UNKNOWN; | 
 |         } | 
 |     } else { | 
 |         LOGE("data_call_info[i]->call_param_info->apn_param is NULL."); | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Delete a data call instance | 
 |   @param[in] call_id Specify a data call instance | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   QL_ERR_NOT_INIT - uninitialized | 
 |   QL_ERR_SERVICE_NOT_READY - service is not ready | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_delete(int call_id) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     int i = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_info[i].call_info.call_id == call_id) { | 
 |             break; | 
 |         } | 
 |         i++; | 
 |     } | 
 |  | 
 |     if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this call_id. | 
 |         LOGW("Unknown call_id : %d", call_id); | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     if(data_call_info[i].call_param_info.apn_param) { | 
 |         memset(data_call_info[i].call_param_info.apn_param, 0, sizeof(mbtk_data_call_apn_param_info_t)); | 
 |     } | 
 |     memset(&(data_call_info[i]), 0, sizeof(mbtk_data_call_info_t)); | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Get the current data call instance list | 
 |   @param[out] list Data call instance array | 
 |   @param[in,out] list_len, in-> Data call instance array size, out->current data call instance number | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   QL_ERR_NOT_INIT - uninitialized | 
 |   QL_ERR_SERVICE_NOT_READY - service is not ready | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_get_list(ql_data_call_item_t *list, int *list_len) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(list == NULL || list_len == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     int i = 0; | 
 |     *list_len = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_info[i].call_info.call_id > 0) { | 
 |             memset(&(list[*list_len]), 0, sizeof(ql_data_call_item_t)); | 
 |             list[*list_len].call_id = data_call_info[i].call_info.call_id; | 
 |             memcpy(list[*list_len].call_name, data_call_info[i].call_info.call_name, | 
 |                 strlen(data_call_info[i].call_info.call_name)); | 
 |  | 
 |             (*list_len)++; | 
 |         } | 
 |         i++; | 
 |     } | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Get the data call status | 
 |   @param[in] call_id Specify a data call instance | 
 |   @param[out] p_sta Point to status instance | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   QL_ERR_NOT_INIT - uninitialized | 
 |   QL_ERR_SERVICE_NOT_READY - service is not ready | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_get_status(int call_id, ql_data_call_status_t *p_sta) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(p_sta == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     int i = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_info[i].call_info.call_id == call_id) { | 
 |             break; | 
 |         } | 
 |         i++; | 
 |     } | 
 |  | 
 |     if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this call_id. | 
 |         LOGW("Unknown call_id : %d", call_id); | 
 |         return QL_ERR_UNKNOWN; | 
 |     } | 
 |  | 
 |     memcpy(p_sta, &(data_call_info[i].call_state), sizeof(ql_data_call_status_t)); | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Register data call status change event | 
 |   @param[in] cb | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   QL_ERR_NOT_INIT - uninitialized | 
 |   QL_ERR_SERVICE_NOT_READY - service is not ready | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_set_status_ind_cb(ql_data_call_status_ind_cb_f cb) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_UNKNOWN; | 
 |     } else { | 
 |         if(mbtk_pdp_state_change_cb_reg(ql_info_handle, data_call_state_change_cb)) | 
 |         { | 
 |             return QL_ERR_UNKNOWN; | 
 |         } | 
 |  | 
 |         data_call_status_ind_cb = cb; | 
 |         return QL_ERR_OK; | 
 |     } | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Set APN related configuration.If the apn does not exist, it is automatically created. | 
 |   @param[in] apn_id APN ID, range:1-16 | 
 |   @param[in] p_info APN configuration | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   QL_ERR_NOT_INIT - uninitialized | 
 |   QL_ERR_SERVICE_NOT_READY - service is not ready | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_set_apn_config(int apn_id, ql_data_call_apn_config_t *p_info) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(p_info == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     int i = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_info[i].call_param_info.apn_param | 
 |             && data_call_info[i].call_param_info.apn_param->apn_id == apn_id) { | 
 |             break; | 
 |         } | 
 |         i++; | 
 |     } | 
 |  | 
 |     if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this apn_id. | 
 |         LOGW("New apn_id : %d", apn_id); | 
 |         // New data call param. | 
 |         int j = 0; | 
 |         while(j < QL_NET_MAX_DATA_CALL_NUM) { | 
 |             if(data_call_apn_param_list[j].apn_id <= 0) { | 
 |                 break; | 
 |             } | 
 |             j++; | 
 |         } | 
 |  | 
 |         if(j == QL_NET_MAX_DATA_CALL_NUM) { // Full | 
 |             LOGW("data_call_apn_param_list is full."); | 
 |             return QL_ERR_UNKNOWN; | 
 |         } | 
 |  | 
 |         data_call_apn_param_list[j].apn_id = apn_id; | 
 |         memcpy(&(data_call_apn_param_list[j].apn_info), p_info, sizeof(ql_data_call_apn_config_t)); | 
 |     } else { | 
 |         memcpy(&(data_call_info[i].call_param_info.apn_param->apn_info), p_info, sizeof(ql_data_call_apn_config_t)); | 
 |     } | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief  Set APN related configuration. If the apn does not exist, it is automatically created and | 
 |   the default parameters are set. | 
 |   @param[in] apn_id APN ID, range:1-16 | 
 |   @param[out] p_info APN configuration | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   QL_ERR_NOT_INIT - uninitialized | 
 |   QL_ERR_SERVICE_NOT_READY - service is not ready | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_get_apn_config(int apn_id, ql_data_call_apn_config_t *p_info) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_SERVICE_NOT_READY; | 
 |     } | 
 |  | 
 |     if(p_info == NULL || p_info == NULL) { | 
 |         return QL_ERR_INVALID_ARG; | 
 |     } | 
 |  | 
 |     int i = 0; | 
 |     while(i < QL_NET_MAX_DATA_CALL_NUM) { | 
 |         if(data_call_info[i].call_param_info.apn_param | 
 |             && data_call_info[i].call_param_info.apn_param->apn_id == apn_id) { | 
 |             break; | 
 |         } | 
 |         i++; | 
 |     } | 
 |  | 
 |     if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this apn_id. | 
 |         LOGE("Unknown apn_id : %d", apn_id); | 
 |         return QL_ERR_UNKNOWN; | 
 |     } else { | 
 |         memcpy(p_info, &(data_call_info[i].call_param_info.apn_param->apn_info), sizeof(ql_data_call_apn_config_t)); | 
 |     } | 
 |  | 
 |     return QL_ERR_OK; | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Set APN related configuration,APN ID:1 | 
 |   @param[in] p_info APN configuration | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   QL_ERR_NOT_INIT - uninitialized | 
 |   QL_ERR_SERVICE_NOT_READY - service is not ready | 
 |   QL_ERR_INVALID_ARG - Invalid arguments | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_set_attach_apn_config(ql_data_call_apn_config_t *p_info) | 
 | { | 
 |     return ql_data_call_set_apn_config(1, p_info); | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief  Registration server error callback. Currently, only if the server exits abnormally, | 
 |   the callback function will be executed, and the error code is QL_ERR_ABORTED; | 
 |   @param[in] cb  Callback function | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_set_service_error_cb(ql_data_call_service_error_cb_f cb) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_UNKNOWN; | 
 |     } else { | 
 |         if(mbtk_ril_server_state_change_reg(ql_info_handle, ril_server_state_cb)) | 
 |         { | 
 |             return QL_ERR_UNKNOWN; | 
 |         } | 
 |  | 
 |         data_call_service_error_cb = cb; | 
 |         return QL_ERR_OK; | 
 |     } | 
 | } | 
 |  | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | /** | 
 |   @brief Deinitialize the data call service | 
 |   @return | 
 |   QL_ERR_OK - successful | 
 |   Other - error code defined by ql_type.h | 
 |   */ | 
 | /*-----------------------------------------------------------------------------------------------*/ | 
 | int ql_data_call_deinit(void) | 
 | { | 
 |     if(ql_info_handle == NULL) | 
 |     { | 
 |         return QL_ERR_UNKNOWN; | 
 |     } else { | 
 |         if(mbtk_info_handle_free(&ql_info_handle)) | 
 |         { | 
 |             return QL_ERR_UNKNOWN; | 
 |         } | 
 |  | 
 |         return QL_ERR_OK; | 
 |     } | 
 | } |