| #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) |
| static 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 QSER_RESULT_FAIL; |
| 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 QSER_RESULT_FAIL; |
| } |
| |
| ret = write(fd, buf, offset); |
| if(ret < 0) |
| { |
| LOGD("mbtk_route_config : write fail."); |
| } |
| |
| close(fd); |
| } |
| } |
| |
| return 0; |
| } |
| #endif |
| |
| static 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; |
| } |
| |
| static 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; |
| } |
| |
| static 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*/ |
| static 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 = strstr(qser_apn_info[0].apn_name, "mnc"); |
| 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) -1; |
| 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 || apn->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; |
| } |
| |
| 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( 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***************************************/ |
| |