blob: a685ef57848b0ba05bf2d71ab56ad527ffd975c9 [file] [log] [blame]
#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 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_ALL_APN_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;
static qser_apn_info_s qser_apn_info[QSER_APN_NUM] = {0};
static bool qser_apn_info_state[QSER_APN_NUM] = {0};
static bool qser_idx_pdp_state[QSER_APN_NUM];
static char qser_apn_add_save_state[QSER_APN_NUM + 1] = {0};
static char qser_apn_auth_state[QSER_APN_NUM + 1] = {0};
#if defined(MBTK_ALL_CID_SUPPORT)
static int qser_apn_default_idx = -1;
static int qser_default_pdp_idx = -1;
#else
static int qser_apn_default_idx = 0xFF;
static int qser_default_pdp_idx = 0;
#endif
/****************************VARIABLE***************************************/
/******************************FUNC*****************************************/
#if defined(MBTK_ALL_CID_SUPPORT)
int qser_route_config(int profile_idx)
{
char buf[1024] = {0};
char dns[128] = {0};
int offset = 0;
int fd = -1;
mbtk_ipv4_info_t ipv4;
mbtk_ipv6_info_t ipv6;
sprintf(buf, "route add default dev ccinet%d", profile_idx -1);
system(buf);
int ret = mbtk_data_call_state_get(qser_info_handle, profile_idx, &ipv4, &ipv6);
if(ret != 0)
return -1;
else
{
memset(buf, 0x0, 1024);
memset(dns, 0x0, 128);
offset = sprintf(buf, "search lan\n");
if(ipv4.valid)
{
if(inet_ntop(AF_INET, &(ipv4.PrimaryDNS), dns, 32) == NULL) {
LOGD("PrimaryDNS error.");
} else {
LOGD("PrimaryDNS : %s", dns);
}
offset += sprintf(buf + offset, "nameserver %s\n", dns);
memset(dns, 0x0, 128);
if(inet_ntop(AF_INET, &(ipv4.SecondaryDNS), dns, 32) == NULL) {
LOGD("SecondaryDNS error.");
} else {
LOGD("SecondaryDNS : %s", dns);
}
offset += sprintf(buf + offset, "nameserver %s\n", dns);
}
if(ipv6.valid)
{
memset(dns, 0x0, 128);
if(ipv6_2_str(&(ipv6.PrimaryDNS), dns))
{
LOGD("PrimaryDNS error.");
} else {
LOGD("PrimaryDNS : %s", dns);
}
offset += sprintf(buf + offset, "nameserver %s\n", dns);
memset(dns, 0x0, 128);
if(ipv6_2_str(&(ipv6.SecondaryDNS), dns))
{
LOGD("SecondaryDNS error.");
} else {
LOGD("SecondaryDNS : %s", dns);
}
offset += sprintf(buf + offset, "nameserver %s\n", dns);
}
if(offset > 0)
{
fd = open("/tmp/resolv.conf", O_WRONLY | O_TRUNC);
if(fd < 0)
{
LOGD("mbtk_route_config : open fail.");
return -1;
}
ret = write(fd, buf, offset);
if(ret < 0)
{
LOGD("mbtk_route_config : write fail.");
}
close(fd);
}
}
return 0;
}
#endif
char qser_get_apn_profile_idx(void)
{
char i = 0;
for(i = QSER_PROFILE_IDX_MIN; i <= QSER_PROFILE_IDX_MAX; i++)
{
if(qser_apn_info_state[i] == FALSE)
{
return i;
}
}
return i;
}
int qser_check_profile_idx(unsigned char profile_idx)
{
if(profile_idx < QSER_PROFILE_IDX_MIN || profile_idx > QSER_PROFILE_IDX_MAX)
{
LOGE("IDX range error.");
return QSER_RESULT_FAIL;
}
if(qser_apn_info_state[profile_idx] != TRUE)
{
LOGE("profile_idx is not exist.");
return QSER_RESULT_FAIL;
}
return QSER_RESULT_SUCCESS;
}
int qser_apn_info_param_convert(int profile_idx, qser_apn_info_s *new_apn, mbtk_apn_info_t *old_apn)
{
if(new_apn == NULL || old_apn == NULL)
{
LOGE("qser_apn_info_param_convert apn param is NULL.");
return QSER_RESULT_FAIL;
}
//get ip type
if(old_apn->ip_type == MBTK_IP_TYPE_IPV4V6) // IPV4V6
{
new_apn->pdp_type = QSER_APN_PDP_TYPE_IPV4V6;
}
else if(old_apn->ip_type == MBTK_IP_TYPE_IP) // IPV4
{
new_apn->pdp_type = QSER_APN_PDP_TYPE_IPV4;
}
else if(old_apn->ip_type == MBTK_IP_TYPE_IPV6) // IPV6
{
new_apn->pdp_type = QSER_APN_PDP_TYPE_IPV6;
}
else
{
new_apn->pdp_type = QSER_APN_PDP_TYPE_PPP;
}
//get apn name
if(strlen(old_apn->apn)+1 > QSER_APN_NAME_SIZE)
{
LOGE("apn_nmea length verylong.");
return QSER_RESULT_FAIL;
}
else
{
if(strlen(old_apn->apn) > 0)
{
memcpy(new_apn->apn_name, old_apn->apn,strlen(old_apn->apn)+1);
}
else
{
memset(new_apn->apn_name, 0x0, QSER_APN_NAME_SIZE);
}
}
//get apn user
if(strlen(old_apn->user)+1 > QSER_APN_USERNAME_SIZE)
{
LOGE("apn_user length verylong.");
return QSER_RESULT_FAIL;
}
else
{
if(strlen(old_apn->user) > 0)
{
memcpy(new_apn->username, old_apn->user, strlen(old_apn->user)+1);
}
else
{
memset(new_apn->username , 0x0, QSER_APN_USERNAME_SIZE);
}
}
//get apn password
if(strlen(old_apn->pass)+1 > QSER_APN_PASSWORD_SIZE)
{
LOGE("apn_password length verylong.");
return QSER_RESULT_FAIL;
}
else
{
if(strlen(old_apn->pass) > 0)
{
memcpy(new_apn->password, old_apn->pass, strlen(old_apn->pass)+1);
}
else
{
memset(new_apn->username , 0x0, QSER_APN_PASSWORD_SIZE);
}
}
//get apn proto
if(strlen(old_apn->auth) > 0)
{
if(strcmp(old_apn->auth, "NONE") == 0)
{
if(qser_apn_auth_state[profile_idx] == '1')
{
new_apn->auth_proto = QSER_APN_AUTH_PROTO_NONE;
}
else
{
new_apn->auth_proto = QSER_APN_AUTH_PROTO_DEFAULT;
}
}
else if(strcmp(old_apn->auth, "PAP") == 0)
{
new_apn->auth_proto = QSER_APN_AUTH_PROTO_PAP;
}
else if(strcmp(old_apn->auth, "CHAP") == 0)
{
new_apn->auth_proto = QSER_APN_AUTH_PROTO_CHAP;
}
else
{
LOGE("auth input error!");
return QSER_RESULT_FAIL;
}
}
//get apn type
new_apn->profile_idx = profile_idx;
memset(new_apn->apn_type, 0x0, QSER_APN_NAME_SIZE);
if(strlen(qser_apn_info[profile_idx].apn_type) > 0)
{
memcpy(new_apn->apn_type, qser_apn_info[profile_idx].apn_type, strlen(qser_apn_info[profile_idx].apn_type));
}
return QSER_RESULT_SUCCESS;
}
/*Check parameter*/
int qser_check_apn_name_type(qser_apn_info_s *apn)
{
if(apn == NULL)
{
LOGE("qser_check_apn_type apn is NULL!");
return QSER_RESULT_FAIL;
}
//check default idx = 0
int apn_name_length = strlen(apn->apn_name);
//LOGE("qser_apn_info[0].apn_name: %s!", qser_apn_info[0].apn_name);
char *p = strchr(qser_apn_info[0].apn_name, '.');
if(p == NULL)
{
LOGE("qser_check_apn_type not find!");
//return QSER_RESULT_FAIL;
}
else
{
int default_apn_name_length = p - (qser_apn_info[0].apn_name);
//LOGE("qser_check_apn_type default_apn_name_length = [%d]!", default_apn_name_length);
if(default_apn_name_length == apn_name_length)
{
int i = 0;
while(i < default_apn_name_length)
{
if(isalpha(qser_apn_info[0].apn_name[i]) && isalpha(apn->apn_name[i]))
{
if(tolower(qser_apn_info[0].apn_name[i]) != tolower(apn->apn_name[i]))
{
break;
}
}
else
{
//LOGE("not char!");
if(qser_apn_info[0].apn_name[i] != apn->apn_name[i])
{
break;
}
}
i++;
}
if(i == default_apn_name_length)
{
LOGE("apn_name is same!idx = [0]");
return QSER_RESULT_FAIL;
}
}
}
//check 1 -6
int pdp_type_tmp = 1;
for (;pdp_type_tmp < QSER_APN_NUM; pdp_type_tmp++)
{
if(pdp_type_tmp == apn->profile_idx)
{
continue;
}
if( (qser_apn_add_save_state[pdp_type_tmp] == '1') || (qser_apn_add_save_state[pdp_type_tmp] == '2') )
{
if(strcmp(qser_apn_info[pdp_type_tmp].apn_type, apn->apn_type) == 0)
{
LOGE("apn_type is same!idx = [%d]", pdp_type_tmp);
return QSER_RESULT_FAIL;
}
if (strcmp(qser_apn_info[pdp_type_tmp].apn_name, apn->apn_name) == 0)
{
if(qser_apn_info[pdp_type_tmp].pdp_type == QSER_APN_PDP_TYPE_IPV4V6)
{
LOGE("apn_name is same and pdp_type is IPV4V6!idx = [%d]", pdp_type_tmp);
return QSER_RESULT_FAIL;
}
if(qser_apn_info[pdp_type_tmp].pdp_type == apn->pdp_type)
{
LOGE("pdp_type is same and pdp_type is same!idx = [%d]", pdp_type_tmp);
return QSER_RESULT_FAIL;
}
}
}
}
return QSER_RESULT_SUCCESS;
}
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( idx == qser_default_pdp_idx )
{
qser_default_pdp_idx = -1;
}
qser_idx_pdp_state[idx] = false;
if(qser_net_status_cb != NULL)
{
qser_net_status_cb(&state);
}
}
else
{
LOGE("cb fail,idx is %d.", idx);
}
}
else if(*net_data > 200)
{
LOGE("cid[%d] is open.", *net_data - 201);
}
else if(*net_data == 1)
{
LOGE("pdp is open.");
}
else
{
LOGE("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("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_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_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);
mbtk_log_init("radio", "QSER_DATA_CALL");
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("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;
property_get("persist.qser.datacall.apn", qser_apn_add_save_state, "00000000");
LOGE("qser_apn_add_save_state = %s", qser_apn_add_save_state);
property_get("persist.qser.apn.auth", qser_apn_auth_state, "00000000");
mbtk_apn_info_t apns[10] = {0};
int apn_num = 10;
char qser_apn_type[32] = {0};
int ret = mbtk_apn_get(qser_info_handle, &apn_num, apns);
if(ret != 0)
{
LOGE("mbtk_apn_get fail. [ret = %d]",ret);
return QSER_RESULT_FAIL;
}
else
{
if(apn_num > 0 && apn_num <= QSER_APN_MAX_LIST)
{
int i = 0;
for(i = 0; i < apn_num; i++)
{
if(qser_apn_add_save_state[apns[i].cid - 1] == '0')
{
//LOGE("idx no open.");
#if defined(MBTK_ALL_CID_SUPPORT)
if(apns[i].cid - 1 == 0)
{
qser_apn_info_param_convert(apns[i].cid - 1, &qser_apn_info[apns[i].cid - 1], &apns[i]);
}
#endif
continue;
}
#if defined(MBTK_ALL_CID_SUPPORT)
if(qser_apn_add_save_state[apns[i].cid - 1] == '2')
{
qser_apn_default_idx = apns[i].cid - 1;
}
#endif
if(qser_apn_info_param_convert(apns[i].cid - 1, &qser_apn_info[apns[i].cid - 1], &apns[i]) != 0)
{
LOGE("qser_apn_info_param_convert fail");
return QSER_RESULT_FAIL;
}
else
{
qser_apn_info_state[apns[i].cid - 1] = TRUE;
sprintf(qser_apn_type, "persist.qser.apn.type%d", apns[i].cid - 1);
property_get(qser_apn_type, qser_apn_info[apns[i].cid - 1].apn_type, NULL);
}
}
}
}
int idx = 0;
for(;idx < QSER_APN_NUM; idx++)
{
qser_idx_pdp_state[idx] = false;
}
LOGE("mbtk_info_handle_get() success.");
return QSER_RESULT_SUCCESS;
}
void qser_data_call_destroy(void)
{
if(qser_info_handle)
{
LOGE("qser_info_handle_num = %d", qser_info_handle_num);
if(qser_info_handle_num == 1)
{ // 最后一个引用,可释放。
int ret = mbtk_info_handle_free(&qser_info_handle);
if(ret)
{
LOGE("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("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("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("handle is NULL.");
*err = QSER_DATA_CALL_ERROR_NO_INIT;
return QSER_RESULT_FAIL;
}
#if defined(MBTK_ALL_CID_SUPPORT)
if( ( (data_call->profile_idx == qser_apn_default_idx) || (data_call->profile_idx == 0) ) && (qser_default_pdp_idx >= 0) )
{
LOGE("default pdp exist.");
*err = QSER_DATA_CALL_ERROR_UNKNOWN;
return QSER_RESULT_FAIL;
}
#endif
if(qser_check_profile_idx(data_call->profile_idx) < 0)
{
#if defined(MBTK_ALL_CID_SUPPORT)
if( data_call->profile_idx == 0 )
{
LOGE("profile_idx = 0.");
}
else
#endif
{
LOGE("profile_idx is invalid.");
*err = QSER_DATA_CALL_ERROR_IDX_NO_EXIST;
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("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;
}
#if defined(MBTK_ALL_CID_SUPPORT)
if(qser_apn_default_idx == data_call->profile_idx)
{
qser_route_config(qser_apn_default_idx + 1);
qser_default_pdp_idx = data_call->profile_idx;
}
else if(data_call->profile_idx == 0)
{
qser_route_config(1);
qser_default_pdp_idx = data_call->profile_idx;
}
else
{
//
}
#endif
qser_idx_pdp_state[data_call->profile_idx] = true;
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("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("handle is NULL.");
*err = QSER_DATA_CALL_ERROR_NO_INIT;
return QSER_RESULT_FAIL;
}
#if defined(MBTK_ALL_CID_SUPPORT)
if( ( (data_call->profile_idx == qser_apn_default_idx) || (data_call->profile_idx == 0) ) && (qser_default_pdp_idx >= 0) )
{
LOGE("default pdp exist.");
*err = QSER_DATA_CALL_ERROR_UNKNOWN;
return QSER_RESULT_FAIL;
}
#endif
if(qser_check_profile_idx(data_call->profile_idx) < 0)
{
#if defined(MBTK_ALL_CID_SUPPORT)
if((data_call->profile_idx == 0) && (qser_default_pdp_idx < 0))
{
LOGE("profile_idx = 0 and not open default idx.");
}
else
#endif
{
LOGE("profile_idx is invalid.");
*err = QSER_DATA_CALL_ERROR_IDX_NO_EXIST;
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("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("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("err is NULL.");
return QSER_RESULT_FAIL;
}
if(qser_info_handle == NULL)
{
LOGE("handle is NULL.");
*err = QSER_DATA_CALL_ERROR_NO_INIT;
return QSER_RESULT_FAIL;
}
if(qser_check_profile_idx(profile_idx) < 0)
{
#if defined(MBTK_ALL_CID_SUPPORT)
if(profile_idx == 0)
{
LOGE("profile_idx = 0.");
}
else
#endif
{
LOGE("profile_idx is invalid.");
*err = QSER_DATA_CALL_ERROR_IDX_NO_EXIST;
return QSER_RESULT_FAIL;
}
}
int ret = -1;
ret = mbtk_data_call_stop(qser_info_handle, profile_idx + 1, 15);
if(ret != 0)
{
LOGE("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;
}
#if defined(MBTK_ALL_CID_SUPPORT)
if(qser_default_pdp_idx == profile_idx)
{
qser_default_pdp_idx = -1;
}
#endif
qser_idx_pdp_state[profile_idx] = false;
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("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("handle is NULL.");
*err = QSER_DATA_CALL_ERROR_NO_INIT;
return QSER_RESULT_FAIL;
}
if(qser_check_profile_idx(profile_idx) < 0)
{
#if defined(MBTK_ALL_CID_SUPPORT)
if(profile_idx == 0)
{
LOGE("profile_idx = 0.");
}
else
#endif
{
LOGE("profile_idx is invalid.");
*err = QSER_DATA_CALL_ERROR_IDX_NO_EXIST;
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("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("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("IP error.");
} else {
LOGE("IP : %s", v4_buff);
}
if(inet_ntop(AF_INET, &(info->v4.addr.pri_dns), v4_buff, 32) == NULL) {
LOGE("PrimaryDNS error.");
} else {
LOGE("PrimaryDNS : %s", v4_buff);
}
if(inet_ntop(AF_INET, &(info->v4.addr.sec_dns), v4_buff, 32) == NULL) {
LOGE("SecondaryDNS error.");
} else {
LOGE("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("IP error.");
} else {
LOGE("IP : %s", v6_buff);
}
if(ipv6_2_str(&(info->v6.addr.pri_dns), v6_buff))
{
LOGE("PrimaryDNS error.");
} else {
LOGE("PrimaryDNS : %s", v6_buff);
}
if(ipv6_2_str(&(info->v6.addr.sec_dns), v6_buff))
{
LOGE("SecondaryDNS error.");
} else {
LOGE("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("handle is NULL.");
return QSER_RESULT_FAIL;
}
if(apn == NULL)
{
LOGE("apn param is NULL.");
return QSER_RESULT_FAIL;
}
if(qser_check_profile_idx(apn->profile_idx) < 0)
{
LOGE("profile_idx is invalid.");
return QSER_RESULT_FAIL;
}
if(strlen(apn->apn_name) == 0)
{
LOGE("apn_name is NULL.");
return QSER_RESULT_FAIL;
}
#if 0
if(memcmp(apn->apn_type, "iot_default", strlen("iot_default")) == 0)
{
if(qser_apn_default_idx > -1)
{
LOGE("iot_default is exist.");
return QSER_RESULT_FAIL;
}
}
#endif
/*add name and type verify*/
if (qser_check_apn_name_type(apn) < 0)
{
LOGE("check param error.");
return QSER_RESULT_FAIL;
}
int ret = -1;
char mbtk_auth[32]={0};
char qser_apn_type[32] = {0};
mbtk_ip_type_enum pdp_type = MBTK_IP_TYPE_IPV4V6;
if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV4)
{
pdp_type = MBTK_IP_TYPE_IP;
}
else if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV6)
{
pdp_type = MBTK_IP_TYPE_IPV6;
}
else if(apn->pdp_type == QSER_APN_PDP_TYPE_IPV4V6)
{
pdp_type = MBTK_IP_TYPE_IPV4V6;
}
else if(apn->pdp_type == QSER_APN_PDP_TYPE_PPP)
{
pdp_type = MBTK_IP_TYPE_PPP;
}
else
{
LOGE("pdp_type error.");
return QSER_RESULT_FAIL;
}
if(apn->auth_proto == QSER_APN_AUTH_PROTO_NONE || apn->auth_proto == QSER_APN_AUTH_PROTO_DEFAULT)
{
memcpy(mbtk_auth,"NONE",strlen("NONE")+1);
}
else if(apn->auth_proto == QSER_APN_AUTH_PROTO_PAP)
{
memcpy(mbtk_auth,"PAP",strlen("PAP")+1);
}
else if(apn->auth_proto == QSER_APN_AUTH_PROTO_CHAP)
{
memcpy(mbtk_auth,"CHAP",strlen("CHAP")+1);
}
#if 0
else if(apn->auth_proto == QSER_APN_AUTH_PROTO_PAP_CHAP)
{
//NOT SUPPORT
}
#endif
else
{
LOGE("auth input error!");
return QSER_RESULT_FAIL;
}
if(strlen(apn->username) > 0 && strlen(apn->password) > 0)
{
LOGE("setapn: %d, %d, %s, %s, %s, %s, %s.",apn->profile_idx, pdp_type, apn->apn_name, apn->username, apn->password, mbtk_auth, apn->apn_type);
}
else
{
LOGE("setapn: %d, %d, %s, NULL, NULL, %s, %s.",apn->profile_idx, pdp_type, apn->apn_name, apn->username, apn->password, mbtk_auth, apn->apn_type);
}
ret = mbtk_apn_set(qser_info_handle, apn->profile_idx + 1, pdp_type, apn->apn_name, apn->username, apn->password, mbtk_auth);
if(ret < 0)
{
LOGE("mbtk_apn_set fail!");
return QSER_RESULT_FAIL;
}
sprintf(qser_apn_type, "persist.qser.apn.type%d", apn->profile_idx);
property_set(qser_apn_type, apn->apn_type);
if(apn->auth_proto == QSER_APN_AUTH_PROTO_NONE)
{
qser_apn_auth_state[apn->profile_idx] = '1';
}
else
{
qser_apn_auth_state[apn->profile_idx] = '0';
}
property_set("persist.qser.apn.auth", qser_apn_auth_state);
memcpy(&qser_apn_info[apn->profile_idx], apn, sizeof(qser_apn_info_s));
#if defined(MBTK_ALL_CID_SUPPORT)
if(strcmp(apn->apn_type, "iot_default") == 0)
{
qser_apn_add_save_state[apn->profile_idx] = '2';
qser_apn_default_idx = apn->profile_idx;
}
else
#endif
{
qser_apn_add_save_state[apn->profile_idx] = '1';
}
property_set("persist.qser.datacall.apn", qser_apn_add_save_state);
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("handle is NULL.");
return QSER_RESULT_FAIL;
}
if(apn == NULL)
{
LOGE("apn param is NULL.");
return QSER_RESULT_FAIL;
}
if(qser_check_profile_idx(profile_idx) < 0)
{
#if defined(MBTK_ALL_CID_SUPPORT)
if(profile_idx != 0)
#endif
{
LOGE("profile_idx is invalid.");
return QSER_RESULT_FAIL;
}
}
//get apn info
mbtk_apn_info_t apns[10] = {0};
int apn_num = 10;
int ret = mbtk_apn_get(qser_info_handle, &apn_num, apns);
if(ret != 0)
{
LOGE("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("find IDX.");
break;
}
}
if(i == apn_num)
{
LOGE("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_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("handle is NULL.");
return QSER_RESULT_FAIL;
}
if(apn == NULL)
{
LOGE("apn param is NULL.");
return QSER_RESULT_FAIL;
}
#if 0
if(memcmp(apn->apn_type, "iot_default", strlen("iot_default")) == 0)
{
if(qser_apn_default_idx > -1)
{
LOGE("iot_default is exist.");
return QSER_RESULT_FAIL;
}
}
/*add name and type verify*/
if (qser_check_apn_name_type(apn) < 0)
{
LOGE("check param error.");
return QSER_RESULT_FAIL;
}
#endif
int ret = 0;
char idx = qser_get_apn_profile_idx();
if(idx > QSER_PROFILE_IDX_MAX)
{
LOGE("idx is full.");
return QSER_RESULT_FAIL;
}
else
{
qser_apn_info_state[idx] = TRUE;
qser_apn_info_s set_apn;
set_apn.profile_idx = idx;
set_apn.pdp_type = apn->pdp_type;
set_apn.auth_proto = apn->auth_proto;
memcpy(set_apn.apn_name, apn->apn_name, QSER_APN_NAME_SIZE);
memcpy(set_apn.username, apn->username, QSER_APN_USERNAME_SIZE);
memcpy(set_apn.password, apn->password, QSER_APN_PASSWORD_SIZE);
memcpy(set_apn.apn_type, apn->apn_type, QSER_APN_NAME_SIZE);
ret = qser_apn_set(&set_apn);
if(ret != 0)
{
LOGE("qser_apn_set fail.");
qser_apn_info_state[idx] = FALSE;
return QSER_RESULT_FAIL;
}
*profile_idx = idx;
}
return QSER_RESULT_SUCCESS;
}
int qser_apn_del(unsigned char profile_idx)
{
//UNUSED(profile_idx);
if(qser_info_handle == NULL)
{
LOGE("handle is NULL.");
return QSER_RESULT_FAIL;
}
if(qser_idx_pdp_state[profile_idx] == true)
{
LOGE("profile_idx[%d] open pdp.", profile_idx);
return QSER_RESULT_FAIL;
}
if(qser_check_profile_idx(profile_idx) < 0)
{
LOGE("profile_idx is invalid.");
return QSER_RESULT_FAIL;
}
qser_apn_info_state[profile_idx] = FALSE;
qser_apn_add_save_state[profile_idx] = '0';
#if defined(MBTK_ALL_CID_SUPPORT)
if(profile_idx == qser_apn_default_idx)
{
qser_apn_default_idx = -1;
}
#endif
property_set("persist.qser.datacall.apn", qser_apn_add_save_state);
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("handle is NULL.");
return QSER_RESULT_FAIL;
}
if(apn_list == NULL)
{
LOGE("apn_list param is NULL.");
return QSER_RESULT_FAIL;
}
property_get("persist.qser.datacall.apn", qser_apn_add_save_state, "00000000");
LOGE("qser_apn_add_save_state = %s", qser_apn_add_save_state);
mbtk_apn_info_t apns[10] = {0};
int apn_num = 10;
int ret = mbtk_apn_get(qser_info_handle, &apn_num, apns);
if(ret != 0)
{
LOGE("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_add_save_state[apns[i].cid - 1] == '0')
{
#if defined(MBTK_ALL_CID_SUPPORT)
if((apns[i].cid - 1) != 0)
#endif
{
LOGE("idx no open.");
continue;
}
}
if(qser_apn_info_param_convert(apns[i].cid - 1, &apn_list->apn[apn_list->cnt], &apns[i]) != 0)
{
LOGE("qser_apn_info_param_convert fail");
return QSER_RESULT_FAIL;
}
apn_list->cnt++;
}
}
else if(apn_num > QSER_APN_MAX_LIST)
{
LOGE("apn_num overlong");
return QSER_RESULT_FAIL;
}
else
{
apn_list->cnt = 0;
}
}
return QSER_RESULT_SUCCESS;
}
/****************************API***************************************/