| /*-----------------------------------------------------------------------------------------------*/ |
| /** |
| @file lynq_data_call.c |
| @brief data call service API |
| */ |
| /*-----------------------------------------------------------------------------------------------*/ |
| |
| /*------------------------------------------------------------------------------------------------- |
| Copyright (c) 2024 mobiletek Wireless Solution, Co., Ltd. All Rights Reserved. |
| mobiletek Wireless Solution Proprietary and Confidential. |
| -------------------------------------------------------------------------------------------------*/ |
| |
| /*------------------------------------------------------------------------------------------------- |
| EDIT HISTORY |
| This section contains comments describing changes made to the file. |
| Notice that changes are listed in reverse chronological order. |
| $Header: $ |
| when who what, where, why |
| -------- --------- ----------------------------------------------------------------- |
| 20241202 yq.wang Created. |
| -------------------------------------------------------------------------------------------------*/ |
| |
| #include <pthread.h> |
| #include <cutils/properties.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| //#include <sys/scoket.h> |
| #include <netinet/in.h> |
| #include <arpa/inet.h> |
| |
| #include "lynq_qser_data.h" |
| #include "mbtk_type.h" |
| #include "mbtk_ril_api.h" |
| |
| /*define*/ |
| #define QSER_DATA_CALL_FUNC __func__ |
| |
| #define QSER_LOGE LOGE |
| #define QSER_LOGD LOGD |
| |
| #define QSER_DEFAULT_APN_TYPE "iot_default" |
| |
| /*define*/ |
| |
| /*enum*/ |
| typedef enum { |
| QSER_RESULT_SUCCESS = 0, |
| QSER_RESULT_FAIL, |
| QSER_RESULT_SERVER_NO_INIT, |
| QSER_RESULT_INVALID_PARAMS, |
| }qser_result_e; |
| |
| /*enum*/ |
| |
| /*struct*/ |
| typedef struct { |
| mbtk_ril_handle* handle; |
| qser_data_call_evt_cb_t net_status_cb; |
| }qser_data_call_handle_s; |
| |
| /*struct*/ |
| |
| /*----------------------------------------------DATA CALL FUNCTION-------------------------------------*/ |
| static qser_data_call_handle_s* qser_data_call_handle_get(void) |
| { |
| static qser_data_call_handle_s data_call_handle = {0}; |
| |
| return &data_call_handle; |
| } |
| |
| static int qser_apn_convert_to_qser_s(qser_apn_info_s *qser_apn, mbtk_apn_info_t *mbtk_apn) |
| { |
| if(qser_apn == NULL || mbtk_apn == NULL) |
| { |
| QSER_LOGE("[%s] apn param is NULL.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| int length = 0; |
| memset(qser_apn, 0x0, sizeof(qser_apn_info_s)); |
| qser_apn->profile_idx = (unsigned char)(mbtk_apn->cid - 1); |
| //get ip type |
| if(mbtk_apn->ip_type == MBTK_IP_TYPE_IPV4V6) // IPV4V6 |
| { |
| qser_apn->pdp_type = QSER_APN_PDP_TYPE_IPV4V6; |
| } |
| else if(mbtk_apn->ip_type == MBTK_IP_TYPE_IP) // IPV4 |
| { |
| qser_apn->pdp_type = QSER_APN_PDP_TYPE_IPV4; |
| } |
| else if(mbtk_apn->ip_type == MBTK_IP_TYPE_IPV6) // IPV6 |
| { |
| qser_apn->pdp_type = QSER_APN_PDP_TYPE_IPV6; |
| } |
| else |
| { |
| qser_apn->pdp_type = QSER_APN_PDP_TYPE_PPP; |
| } |
| |
| //get apn proto |
| qser_apn->auth_proto = (qser_apn_auth_proto_e)mbtk_apn->auth; |
| |
| //get apn name |
| length = strlen((char *)mbtk_apn->apn); |
| if( length <= 0 || length > QSER_APN_NAME_SIZE) |
| { |
| QSER_LOGE("[%s] apn_nmea length fault.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| else |
| { |
| memcpy(qser_apn->apn_name, mbtk_apn->apn, length); |
| } |
| |
| //get apn user |
| length = strlen((char *)mbtk_apn->user); |
| if(length < 0 || length > QSER_APN_USERNAME_SIZE) |
| { |
| QSER_LOGE("[%s] user length fault.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| else |
| { |
| memcpy(qser_apn->username, mbtk_apn->user, length); |
| } |
| |
| //get apn password |
| length = strlen((char *)mbtk_apn->pass); |
| if(length < 0 || length > QSER_APN_PASSWORD_SIZE) |
| { |
| QSER_LOGE("[%s] pass length fault.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| else |
| { |
| memcpy(qser_apn->password, mbtk_apn->pass, length); |
| } |
| |
| //get apn type |
| length = strlen((char *)mbtk_apn->type); |
| if(length < 0 || length > QSER_APN_TYPE_SIZE) |
| { |
| QSER_LOGE("[%s] type length fault.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| else |
| { |
| memcpy(qser_apn->apn_type, mbtk_apn->type, length); |
| } |
| |
| return QSER_RESULT_SUCCESS; |
| } |
| |
| static int qser_apn_convert_to_mbtk_s(mbtk_ril_cid_enum cid, mbtk_apn_info_t *mbtk_apn, qser_apn_info_s *qser_apn) |
| { |
| if(mbtk_apn == NULL || qser_apn == NULL) |
| { |
| QSER_LOGE("[%s] apn param is NULL.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| if(strlen(qser_apn->apn_name) > QSER_APN_NAME_SIZE || strlen(qser_apn->username) > QSER_APN_USERNAME_SIZE |
| || strlen(qser_apn->password) > QSER_APN_PASSWORD_SIZE || strlen(qser_apn->apn_type) > QSER_APN_TYPE_SIZE) |
| { |
| QSER_LOGE("[%s] apn length out of range.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_INVALID_PARAMS; |
| } |
| |
| memset(mbtk_apn, 0x0, sizeof(mbtk_apn_info_t)); |
| mbtk_apn->cid = cid; |
| |
| if(qser_apn->pdp_type == QSER_APN_PDP_TYPE_IPV4) |
| { |
| mbtk_apn->ip_type = MBTK_IP_TYPE_IP; |
| } |
| else if(qser_apn->pdp_type == QSER_APN_PDP_TYPE_IPV6) |
| { |
| mbtk_apn->ip_type = MBTK_IP_TYPE_IPV6; |
| } |
| else if(qser_apn->pdp_type == QSER_APN_PDP_TYPE_IPV4V6) |
| { |
| mbtk_apn->ip_type = MBTK_IP_TYPE_IPV4V6; |
| } |
| else if(qser_apn->pdp_type == QSER_APN_PDP_TYPE_PPP) |
| { |
| mbtk_apn->ip_type = MBTK_IP_TYPE_PPP; |
| } |
| else |
| { |
| QSER_LOGE("[%s] pdp_type error.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| //no support PAP_CHAP |
| if(qser_apn->auth_proto >= QSER_APN_AUTH_PROTO_DEFAULT && qser_apn->auth_proto < QSER_APN_AUTH_PROTO_PAP_CHAP) |
| { |
| mbtk_apn->auth = (mbtk_apn_auth_type_enum)qser_apn->auth_proto; |
| } |
| else |
| { |
| QSER_LOGE("[%s] auth_proto error.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| mbtk_apn->auto_save = true; |
| mbtk_apn->auto_boot_call = false; |
| |
| if(strlen(qser_apn->apn_type)) |
| { |
| if(memcmp(qser_apn->apn_type, QSER_DEFAULT_APN_TYPE, strlen(QSER_DEFAULT_APN_TYPE)) == 0) |
| { |
| mbtk_apn->def_route = true; |
| mbtk_apn->as_dns = true; |
| } |
| memcpy(mbtk_apn->type, qser_apn->apn_type, strlen(qser_apn->apn_type)); |
| } |
| else |
| { |
| mbtk_apn->def_route = false; |
| mbtk_apn->as_dns = false; |
| } |
| |
| if(strlen(qser_apn->apn_name)) |
| { |
| memcpy(mbtk_apn->apn, qser_apn->apn_name, strlen(qser_apn->apn_name)); |
| } |
| else |
| { |
| QSER_LOGE("[%s] apn is empty.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| if(strlen(qser_apn->username)) |
| { |
| memcpy(mbtk_apn->user, qser_apn->username, strlen(qser_apn->username)); |
| } |
| if(strlen(qser_apn->password)) |
| { |
| memcpy(mbtk_apn->pass, qser_apn->password, strlen(qser_apn->password)); |
| } |
| |
| return QSER_RESULT_SUCCESS; |
| } |
| |
| static void qser_netcard_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)); |
| } |
| } |
| |
| static void qser_pdp_state_change_cb(const void* data, int data_len) |
| { |
| if(data == NULL || data_len != sizeof(mbtk_ril_pdp_state_info_t)) |
| { |
| QSER_LOGE("[%s] cb data fault.", QSER_DATA_CALL_FUNC); |
| return; |
| } |
| |
| mbtk_ril_pdp_state_info_t pdp_data; |
| qser_data_call_state_s state = {0}; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| if(NULL == data_call_handle) |
| { |
| QSER_LOGE("[%s] qser_data_call_handle_get() fail.", QSER_DATA_CALL_FUNC); |
| return; |
| } |
| |
| |
| memset(&pdp_data, 0x0, sizeof(mbtk_ril_pdp_state_info_t)); |
| memcpy(&pdp_data, data, sizeof(mbtk_ril_pdp_state_info_t)); |
| QSER_LOGD("[%s] cid - %d, act - %d, auto_change - %d, reason - %d", QSER_DATA_CALL_FUNC, pdp_data.cid, pdp_data.action, |
| pdp_data.auto_change, pdp_data.reason); |
| |
| qser_netcard_state_init(&state); |
| state.profile_idx = (char)(pdp_data.cid - 1); |
| snprintf(state.name, 16, "ccinet%d", state.profile_idx); |
| if(pdp_data.action) |
| { |
| state.state = QSER_DATA_CALL_CONNECTED; |
| } |
| else |
| { |
| state.state = QSER_DATA_CALL_DISCONNECTED; |
| } |
| |
| if(pdp_data.ip_info_valid) |
| { |
| if(pdp_data.ip_info.ipv4.valid) |
| { |
| state.ip_family = QSER_DATA_CALL_TYPE_IPV4; |
| state.v4.ip.s_addr = pdp_data.ip_info.ipv4.IPAddr; |
| state.v4.pri_dns.s_addr = pdp_data.ip_info.ipv4.PrimaryDNS; |
| state.v4.sec_dns.s_addr = pdp_data.ip_info.ipv4.SecondaryDNS; |
| } |
| |
| if(pdp_data.ip_info.ipv6.valid) |
| { |
| state.ip_family = QSER_DATA_CALL_TYPE_IPV6; |
| memcpy(&(state.v6.ip), &(pdp_data.ip_info.ipv6.IPV6Addr), sizeof(pdp_data.ip_info.ipv6.IPV6Addr)); |
| memcpy(&(state.v6.pri_dns), &(pdp_data.ip_info.ipv6.PrimaryDNS), sizeof(pdp_data.ip_info.ipv6.PrimaryDNS)); |
| memcpy(&(state.v6.sec_dns), &(pdp_data.ip_info.ipv6.SecondaryDNS), sizeof(pdp_data.ip_info.ipv6.SecondaryDNS)); |
| } |
| |
| if(pdp_data.ip_info.ipv4.valid && pdp_data.ip_info.ipv6.valid) |
| { |
| state.ip_family = QSER_DATA_CALL_TYPE_IPV4V6; |
| } |
| } |
| |
| if(data_call_handle->net_status_cb) |
| { |
| data_call_handle->net_status_cb(&state); |
| } |
| } |
| |
| static void* qser_data_call_async_thread(void* arg) |
| { |
| QSER_LOGD("[%s] entry func.", QSER_DATA_CALL_FUNC); |
| mbtk_ril_err_enum ret = MBTK_RIL_ERR_SUCCESS; |
| qser_data_call_error_e err = QSER_DATA_CALL_ERROR_NONE; |
| |
| qser_data_call_state_s state = {0}; |
| qser_data_call_s qser_data_backup = {0}; |
| qser_data_call_info_s info = {0}; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| qser_netcard_state_init(&state); |
| if(arg != NULL) |
| { |
| memcpy(&qser_data_backup, (qser_data_call_s *)arg, sizeof(qser_data_call_s)); |
| } |
| else |
| { |
| QSER_LOGD("[%s] arg is NULL.", QSER_DATA_CALL_FUNC); |
| state.err = QSER_DATA_CALL_ERROR_UNKNOWN; |
| if(data_call_handle->net_status_cb) |
| { |
| data_call_handle->net_status_cb(&state); |
| } |
| return NULL; |
| } |
| |
| state.profile_idx = qser_data_backup.profile_idx; |
| snprintf(state.name, 16, "ccinet%d", qser_data_backup.profile_idx); |
| state.ip_family = qser_data_backup.ip_family; |
| |
| ret = qser_data_call_start(&qser_data_backup, &err); |
| if(ret != MBTK_RIL_ERR_SUCCESS) |
| { |
| QSER_LOGE("[%s] qser_data_call_start() fail.", QSER_DATA_CALL_FUNC); |
| state.err = err; |
| } |
| else |
| { |
| state.state = QSER_DATA_CALL_CONNECTED; |
| ret = qser_data_call_info_get(qser_data_backup.profile_idx, qser_data_backup.ip_family, &info, &err); |
| if(ret != MBTK_RIL_ERR_SUCCESS) |
| { |
| QSER_LOGE("[%s] qser_data_call_info_get() fail.", QSER_DATA_CALL_FUNC); |
| state.err = err; |
| } |
| else |
| { |
| memcpy(&(state.v4), &(info.v4.addr), sizeof(struct v4_address_status)); |
| memcpy(&(state.v6), &(info.v6.addr), sizeof(struct v6_address_status)); |
| } |
| } |
| |
| if(data_call_handle->net_status_cb) |
| { |
| data_call_handle->net_status_cb(&state); |
| } |
| return NULL; |
| } |
| |
| /*----------------------------------------------DATA CALL FUNCTION-------------------------------------*/ |
| |
| /*----------------------------------------------DATA CALL API------------------------------------------*/ |
| int qser_data_call_init(qser_data_call_evt_cb_t evt_cb) |
| { |
| mbtk_ril_err_enum ret = MBTK_RIL_ERR_SUCCESS; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| if(NULL == data_call_handle) |
| { |
| QSER_LOGE("[%s] qser_data_call_handle_get() fail.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| if(NULL == data_call_handle->handle) |
| { |
| data_call_handle->handle = mbtk_ril_open(MBTK_AT_PORT_DATA); |
| if(NULL == data_call_handle->handle) |
| { |
| QSER_LOGE("[%s] mbtk_ril_open() fail.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| ret = mbtk_pdp_state_change_cb_reg(qser_pdp_state_change_cb); |
| if(ret != MBTK_RIL_ERR_SUCCESS) |
| { |
| QSER_LOGE("[%s] mbtk_pdp_state_change_cb_reg() fail.[%d]", QSER_DATA_CALL_FUNC, ret); |
| goto error_1; |
| } |
| |
| data_call_handle->net_status_cb = evt_cb; |
| } |
| |
| QSER_LOGD("[%s] data call init success.", QSER_DATA_CALL_FUNC); |
| |
| return QSER_RESULT_SUCCESS; |
| error_1: |
| if(data_call_handle->handle) |
| { |
| ret = mbtk_ril_close(MBTK_AT_PORT_DATA); |
| data_call_handle->handle = NULL; |
| } |
| |
| return QSER_RESULT_FAIL; |
| } |
| |
| void qser_data_call_destroy(void) |
| { |
| mbtk_ril_err_enum ret = MBTK_RIL_ERR_SUCCESS; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| if(NULL == data_call_handle || NULL == data_call_handle->handle) |
| { |
| QSER_LOGE("[%s] server not init.", QSER_DATA_CALL_FUNC); |
| return; |
| } |
| |
| data_call_handle->net_status_cb = NULL; |
| |
| ret = mbtk_ril_close(MBTK_AT_PORT_DATA); |
| if(ret != MBTK_RIL_ERR_SUCCESS && ret != MBTK_RIL_ERR_PORT_NOT_CLOSE) |
| { |
| QSER_LOGE("[%s] mbtk_ril_close() fail.[%d]", QSER_DATA_CALL_FUNC, ret); |
| return; |
| } |
| data_call_handle->handle = NULL; |
| } |
| |
| int qser_data_call_start(qser_data_call_s *data_call, qser_data_call_error_e *err) |
| { |
| if(data_call == NULL || err == NULL) |
| { |
| QSER_LOGE("[%s] data_call or err is NULL.", QSER_DATA_CALL_FUNC); |
| if(err != NULL) |
| { |
| *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS; |
| } |
| return QSER_RESULT_FAIL; |
| } |
| |
| mbtk_ril_err_enum ret = MBTK_RIL_ERR_SUCCESS; |
| int retry_interval[] = {5, 10}; |
| mbtk_ip_info_t ip_info; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| if(NULL == data_call_handle || NULL == data_call_handle->handle) |
| { |
| QSER_LOGE("[%s] server not init.", QSER_DATA_CALL_FUNC); |
| *err = QSER_DATA_CALL_ERROR_NO_INIT; |
| return QSER_RESULT_SERVER_NO_INIT; |
| } |
| |
| memset(&ip_info, 0x0, sizeof(mbtk_ip_info_t)); |
| ret = mbtk_data_call_start(data_call_handle->handle, (mbtk_ril_cid_enum)(data_call->profile_idx + 1), |
| MBTK_DATA_CALL_ITEM_STATE_NON, MBTK_DATA_CALL_ITEM_STATE_NON, MBTK_DATA_CALL_ITEM_STATE_NON, |
| retry_interval, 2, 0, &ip_info); |
| if(ret != MBTK_RIL_ERR_SUCCESS) |
| { |
| QSER_LOGE("[%s] mbtk_data_call_start() fail.[%d]", QSER_DATA_CALL_FUNC, ret); |
| *err = QSER_DATA_CALL_ERROR_UNKNOWN; |
| return QSER_RESULT_FAIL; |
| } |
| else |
| { |
| *err = QSER_DATA_CALL_ERROR_NONE; |
| } |
| |
| return QSER_RESULT_SUCCESS; |
| } |
| |
| int qser_data_call_start_async(qser_data_call_s *data_call, qser_data_call_error_e *err) |
| { |
| if(data_call == NULL || err == NULL) |
| { |
| QSER_LOGE("[%s] data_call or err is NULL.", QSER_DATA_CALL_FUNC); |
| if(err != NULL) |
| { |
| *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS; |
| } |
| return QSER_RESULT_FAIL; |
| } |
| |
| pthread_attr_t thread_attr; |
| pthread_t data_call_thread_id; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| if(NULL == data_call_handle || NULL == data_call_handle->handle) |
| { |
| QSER_LOGE("[%s] server not init.", QSER_DATA_CALL_FUNC); |
| *err = QSER_DATA_CALL_ERROR_NO_INIT; |
| return QSER_RESULT_SERVER_NO_INIT; |
| } |
| |
| pthread_attr_init(&thread_attr); |
| if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED)) |
| { |
| QSER_LOGE("[%s] pthread_attr_setdetachstate() fail.", QSER_DATA_CALL_FUNC); |
| *err = QSER_DATA_CALL_ERROR_UNKNOWN; |
| return QSER_RESULT_FAIL; |
| } |
| |
| if(pthread_create(&data_call_thread_id, &thread_attr, qser_data_call_async_thread, (void *) data_call)) |
| { |
| QSER_LOGE("[%s] pthread_create() fail.", QSER_DATA_CALL_FUNC); |
| *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(ip_family); |
| |
| if(err == NULL) |
| { |
| QSER_LOGE("[%s] err is NULL.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| mbtk_ril_err_enum ret = MBTK_RIL_ERR_SUCCESS; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| if(NULL == data_call_handle || NULL == data_call_handle->handle) |
| { |
| QSER_LOGE("[%s] server not init.", QSER_DATA_CALL_FUNC); |
| *err = QSER_DATA_CALL_ERROR_NO_INIT; |
| return QSER_RESULT_SERVER_NO_INIT; |
| } |
| |
| ret = mbtk_data_call_stop(data_call_handle->handle, (mbtk_ril_cid_enum)(profile_idx + 1), 15); |
| if(ret != MBTK_RIL_ERR_SUCCESS) |
| { |
| QSER_LOGE("[%s] mbtk_data_call_stop() fail.[%d]", QSER_DATA_CALL_FUNC, ret); |
| *err = QSER_DATA_CALL_ERROR_UNKNOWN; |
| return QSER_RESULT_FAIL; |
| } |
| else |
| { |
| *err = QSER_DATA_CALL_ERROR_NONE; |
| } |
| |
| return QSER_RESULT_SUCCESS; |
| } |
| |
| int qser_data_call_info_get(char profile_idx,qser_data_call_ip_family_e ip_family, |
| qser_data_call_info_s *info, qser_data_call_error_e *err) |
| { |
| UNUSED(ip_family); |
| |
| if(info == NULL || err == NULL) |
| { |
| QSER_LOGE("[%s] info or err is NULL.", QSER_DATA_CALL_FUNC); |
| if(err != NULL) |
| { |
| *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS; |
| } |
| return QSER_RESULT_FAIL; |
| } |
| |
| mbtk_ril_err_enum ret = MBTK_RIL_ERR_SUCCESS; |
| mbtk_ip_info_t ip_info; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| if(NULL == data_call_handle || NULL == data_call_handle->handle) |
| { |
| QSER_LOGE("[%s] server not init.", QSER_DATA_CALL_FUNC); |
| *err = QSER_DATA_CALL_ERROR_NO_INIT; |
| return QSER_RESULT_SERVER_NO_INIT; |
| } |
| |
| #ifdef QSER_TEST |
| char v4_buff[32] = {0}; |
| char v6_buff[128] = {0}; |
| #endif |
| memset(&ip_info, 0x0, sizeof(mbtk_ip_info_t)); |
| memset(info, 0x0, sizeof(qser_data_call_info_s)); |
| ret = mbtk_data_call_state_get(data_call_handle->handle, (mbtk_ril_cid_enum)(profile_idx + 1), &ip_info); |
| if(ret != MBTK_RIL_ERR_SUCCESS) |
| { |
| QSER_LOGE("[%s] mbtk_data_call_state_get fail.[%d]", QSER_DATA_CALL_FUNC, ret); |
| *err = QSER_DATA_CALL_ERROR_UNKNOWN; |
| return QSER_RESULT_FAIL; |
| } |
| else |
| { |
| info->profile_idx = profile_idx; |
| if(ip_info.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 = ip_info.ipv4.IPAddr; |
| info->v4.addr.pri_dns.s_addr = ip_info.ipv4.PrimaryDNS; |
| info->v4.addr.sec_dns.s_addr = ip_info.ipv4.SecondaryDNS; |
| info->v4.reconnect = true; |
| |
| #ifdef QSER_TEST |
| //LOGE("[qser_data] IP: %x pri_DNS: %x sec_DNS: %x.", ipv4.IPAddr, ipv4.PrimaryDNS, ipv4.SecondaryDNS); |
| if(inet_ntop(AF_INET, &(info->v4.addr.ip), v4_buff, 32) == NULL) { |
| LOGE("[qser_data] IP error."); |
| } else { |
| LOGE("[qser_data] IP : %s", v4_buff); |
| } |
| if(inet_ntop(AF_INET, &(info->v4.addr.pri_dns), v4_buff, 32) == NULL) { |
| LOGE("[qser_data] PrimaryDNS error."); |
| } else { |
| LOGE("[qser_data] PrimaryDNS : %s", v4_buff); |
| } |
| if(inet_ntop(AF_INET, &(info->v4.addr.sec_dns), v4_buff, 32) == NULL) { |
| LOGE("[qser_data] SecondaryDNS error."); |
| } else { |
| LOGE("[qser_data] SecondaryDNS : %s", v4_buff); |
| } |
| #endif |
| } |
| |
| if(ip_info.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), &(ip_info.ipv6.IPV6Addr), sizeof(ip_info.ipv6.IPV6Addr)); |
| memcpy(&(info->v6.addr.pri_dns), &(ip_info.ipv6.PrimaryDNS), sizeof(ip_info.ipv6.PrimaryDNS)); |
| memcpy(&(info->v6.addr.sec_dns), &(ip_info.ipv6.SecondaryDNS), sizeof(ip_info.ipv6.SecondaryDNS)); |
| info->v6.reconnect = true; |
| |
| #ifdef QSER_TEST |
| if(ipv6_2_str(&(info->v6.addr.ip), v6_buff)) |
| { |
| LOGE("[qser_data] IP error."); |
| } else { |
| LOGE("[qser_data] IP : %s", v6_buff); |
| } |
| if(ipv6_2_str(&(info->v6.addr.pri_dns), v6_buff)) |
| { |
| LOGE("[qser_data] PrimaryDNS error."); |
| } else { |
| LOGE("[qser_data] PrimaryDNS : %s", v6_buff); |
| } |
| if(ipv6_2_str(&(info->v6.addr.sec_dns), v6_buff)) |
| { |
| LOGE("[qser_data] SecondaryDNS error."); |
| } else { |
| LOGE("[qser_data] SecondaryDNS : %s", v6_buff); |
| } |
| #endif |
| } |
| |
| if(ip_info.ipv4.valid && ip_info.ipv6.valid) |
| { |
| info->ip_family = QSER_DATA_CALL_TYPE_IPV4V6; |
| } |
| } |
| |
| *err = QSER_DATA_CALL_ERROR_NONE; |
| return QSER_RESULT_SUCCESS; |
| } |
| |
| int qser_apn_set(qser_apn_info_s *apn) |
| { |
| if(apn == NULL) |
| { |
| QSER_LOGE("[%s] apn param is NULL.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| mbtk_ril_err_enum ret = MBTK_RIL_ERR_SUCCESS; |
| mbtk_apn_info_t apninfo; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| if(NULL == data_call_handle || NULL == data_call_handle->handle) |
| { |
| QSER_LOGE("[%s] server not init.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_SERVER_NO_INIT; |
| } |
| |
| if(qser_apn_convert_to_mbtk_s((mbtk_ril_cid_enum)(apn->profile_idx + 1), &apninfo, apn) != QSER_RESULT_SUCCESS) |
| { |
| QSER_LOGE("[%s] qser_apn_convert_to_mbtk_s() fail.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| ret = mbtk_apn_set(data_call_handle->handle, &apninfo); |
| if(ret != MBTK_RIL_ERR_SUCCESS) |
| { |
| QSER_LOGE("[%s] mbtk_apn_set() fail.[%d]", QSER_DATA_CALL_FUNC, ret); |
| return QSER_RESULT_FAIL; |
| } |
| |
| return QSER_RESULT_SUCCESS; |
| } |
| |
| int qser_apn_get(unsigned char profile_idx, qser_apn_info_s *apn) |
| { |
| if(apn == NULL) |
| { |
| QSER_LOGE("[%s] apn param is NULL.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| int i = 0; |
| mbtk_ril_err_enum ret = MBTK_RIL_ERR_SUCCESS; |
| mbtk_apn_info_array_t apninfo; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| if(NULL == data_call_handle || NULL == data_call_handle->handle) |
| { |
| QSER_LOGE("[%s] server not init.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_SERVER_NO_INIT; |
| } |
| |
| memset(&apninfo, 0x0, sizeof(mbtk_apn_info_array_t)); |
| ret = mbtk_apn_get(data_call_handle->handle, &apninfo); |
| if(ret != MBTK_RIL_ERR_SUCCESS) |
| { |
| QSER_LOGE("[%s] mbtk_apn_get() fail. [%d]", QSER_DATA_CALL_FUNC, ret); |
| return QSER_RESULT_FAIL; |
| } |
| else |
| { |
| for(i = 0; i < apninfo.num; i++) |
| { |
| if(apninfo.apns[i].cid == (mbtk_ril_cid_enum)(profile_idx + 1)) |
| { |
| QSER_LOGD("[%s] find idx[%d].", QSER_DATA_CALL_FUNC, profile_idx); |
| break; |
| } |
| } |
| |
| if(i == apninfo.num) |
| { |
| QSER_LOGE("[%s] not find idx, max num[%d].", QSER_DATA_CALL_FUNC, apninfo.num); |
| return QSER_RESULT_FAIL; |
| } |
| |
| if(qser_apn_convert_to_qser_s(apn, &(apninfo.apns[i])) != QSER_RESULT_SUCCESS) |
| { |
| QSER_LOGE("[%s] qser_apn_convert_to_qser_s() fail.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| } |
| |
| return QSER_RESULT_SUCCESS; |
| } |
| |
| int qser_apn_add(qser_apn_add_s *apn, unsigned char *profile_idx) |
| { |
| if(apn == NULL || profile_idx == NULL) |
| { |
| QSER_LOGE("[%s] apn param is NULL.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| mbtk_ril_err_enum ret = MBTK_RIL_ERR_SUCCESS; |
| mbtk_apn_info_t apninfo; |
| qser_apn_info_s qser_info; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| if(NULL == data_call_handle || NULL == data_call_handle->handle) |
| { |
| QSER_LOGE("[%s] server not init.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_SERVER_NO_INIT; |
| } |
| |
| memset(&qser_info, 0x0, sizeof(qser_apn_info_s)); |
| qser_info.profile_idx = MBTK_RIL_CID_NUL; |
| qser_info.pdp_type = apn->pdp_type; |
| qser_info.auth_proto = apn->auth_proto; |
| memcpy(qser_info.apn_name, apn->apn_name, QSER_APN_NAME_SIZE); |
| memcpy(qser_info.username, apn->username, QSER_APN_USERNAME_SIZE); |
| memcpy(qser_info.password, apn->password, QSER_APN_PASSWORD_SIZE); |
| memcpy(qser_info.apn_type, apn->apn_type, QSER_APN_TYPE_SIZE); |
| if(qser_apn_convert_to_mbtk_s(MBTK_RIL_CID_NUL, &apninfo, &qser_info) != QSER_RESULT_SUCCESS) |
| { |
| QSER_LOGE("[%s] apn_convert_to_mbtk_s() fail.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| ret = mbtk_apn_set(data_call_handle->handle, &apninfo); |
| if(ret != MBTK_RIL_ERR_SUCCESS) |
| { |
| QSER_LOGE("[%s] mbtk_apn_set() fail.[%d]", QSER_DATA_CALL_FUNC, ret); |
| return QSER_RESULT_FAIL; |
| } |
| |
| *profile_idx = (unsigned char)(apninfo.cid - 1); |
| return QSER_RESULT_SUCCESS; |
| } |
| |
| int qser_apn_del(unsigned char profile_idx) |
| { |
| mbtk_ril_err_enum ret = MBTK_RIL_ERR_SUCCESS; |
| mbtk_apn_info_t apninfo; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| if(NULL == data_call_handle || NULL == data_call_handle->handle) |
| { |
| QSER_LOGE("[%s] server not init.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_SERVER_NO_INIT; |
| } |
| |
| memset(&apninfo, 0x0, sizeof(mbtk_apn_info_t)); |
| apninfo.cid = (mbtk_ril_cid_enum)(profile_idx + 1); |
| apninfo.auto_save = true; |
| ret = mbtk_apn_set(data_call_handle->handle, &(apninfo)); |
| if(ret != MBTK_RIL_ERR_SUCCESS) |
| { |
| QSER_LOGE("[%s] mbtk_apn_set fail.[%d]", QSER_DATA_CALL_FUNC, ret); |
| return QSER_RESULT_FAIL; |
| } |
| return QSER_RESULT_SUCCESS; |
| } |
| |
| int qser_apn_get_list(qser_apn_info_list_s *apn_list) |
| { |
| if(apn_list == NULL) |
| { |
| QSER_LOGE("[%s] apn_list param is NULL.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| |
| int i = 0; |
| mbtk_ril_err_enum ret = MBTK_RIL_ERR_SUCCESS; |
| mbtk_apn_info_array_t apninfo; |
| qser_data_call_handle_s* data_call_handle = qser_data_call_handle_get(); |
| if(NULL == data_call_handle || NULL == data_call_handle->handle) |
| { |
| QSER_LOGE("[%s] server not init.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_SERVER_NO_INIT; |
| } |
| |
| memset(&apninfo, 0x0, sizeof(mbtk_apn_info_array_t)); |
| ret = mbtk_apn_get(data_call_handle->handle, &apninfo); |
| if(ret != MBTK_RIL_ERR_SUCCESS && ret != MBTK_RIL_ERR_CME) |
| { |
| QSER_LOGE("[%s] mbtk_apn_get() fail. [%d]", QSER_DATA_CALL_FUNC, ret); |
| return QSER_RESULT_FAIL; |
| } |
| else |
| { |
| if(apninfo.num > 0 && apninfo.num <= QSER_APN_MAX_LIST) |
| { |
| apn_list->cnt = 0; |
| for(i = 0; i < apninfo.num; i++) |
| { |
| if(qser_apn_convert_to_qser_s(&apn_list->apn[apn_list->cnt], &(apninfo.apns[i])) != QSER_RESULT_SUCCESS) |
| { |
| QSER_LOGE("[%s] qser_apn_convert_to_qser_s() fail.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| apn_list->cnt++; |
| } |
| } |
| else if(apninfo.num > QSER_APN_MAX_LIST) |
| { |
| QSER_LOGE("[%s] apn_num overlong.", QSER_DATA_CALL_FUNC); |
| return QSER_RESULT_FAIL; |
| } |
| else |
| { |
| apn_list->cnt = 0; |
| } |
| } |
| |
| return QSER_RESULT_SUCCESS; |
| } |
| /*----------------------------------------------DATA CALL API------------------------------------------*/ |
| |