blob: 8249cbd748203f7568dd42c23bf4b7b2b658f52e [file] [log] [blame]
/*-----------------------------------------------------------------------------------------------*/
/**
@file ql_nw.c
@brief network registration 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
-------- --------- -----------------------------------------------------------------
20241022 yq.wang Created .
-------------------------------------------------------------------------------------------------*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <fcntl.h>
#include "ql_nw.h"
#include "ql_type.h"
#include "mbtk_type.h"
#include "mbtk_ril_api.h"
/*----------------------------------------------DEFINE-------------------------------------------*/
#define QL_NW_LOGE LOGE
#define QL_NW_LOGD LOGD
#define MBTK_ERR_OK 0
#define MBTK_BUFF_TEMP_SIZE_8 8
#define QL_NW_MCC_LENGHT 3
#define QL_NW_MNC_MAX 3
#define QL_NW_MCC_MNC_MAX 6
#define QL_NW_MCC_MNC_MIN 5
#define MBTK_READ_EVENT_SIZE 1
#define MBTK_WRITE_EVENT_SIZE 1
/*----------------------------------------------DEFINE-------------------------------------------*/
/*----------------------------------------------ENUM---------------------------------------------*/
typedef enum {
QL_NW_REG_TYPE_VOICE = 0,
QL_NW_REG_TYPE_DATA,
}ql_nw_reg_type_enum;
typedef enum {
QL_NW_EVENT_THREAD_QUIT = 0,
QL_NW_EVENT_SIGNAL_CB,
QL_NW_EVENT_VOICE_CB,
QL_NW_EVENT_MAX = 255,
}ql_nw_event_enum;
/*----------------------------------------------ENUM---------------------------------------------*/
/*----------------------------------------------STRUCT-------------------------------------------*/
typedef struct {
mbtk_ril_handle* handle;
int control[2];
pthread_t cb_thread_id;
ql_nw_signal_strength_ind_cb signal_cb;
ql_nw_voice_reg_ind_cb voice_cb;
ql_nw_service_error_cb_f server_cb;
}ql_nw_info_handle_t;
/*----------------------------------------------STRUCT-------------------------------------------*/
/*----------------------------------------------GLOBAL STATIC VARIABLE---------------------------*/
static ql_nw_info_handle_t* nw_handle = NULL;
/*----------------------------------------------GLOBAL STATIC VARIABLE---------------------------*/
/*----------------------------------------------NW FUNCTION--------------------------------------*/
static int ql_get_cops_state(ql_nw_reg_status_info_t *p_info, ql_nw_info_handle_t *p_handle)
{
int ret = 0;
char mcc_mnc[MBTK_BUFF_TEMP_SIZE_8] = {0};
mbtk_net_info_t net = {0};
memset(&net, 0x0, sizeof(mbtk_net_info_t));
ret = mbtk_net_sel_mode_get(p_handle->handle, &net);
if(ret != MBTK_ERR_OK)
{
QL_NW_LOGE("[%s] net sel mode get fail.[%d]", __func__, ret);
return QL_ERR_FAILED;
}
switch(net.net_type)
{
case MBTK_RADIO_TECH_GSM:
case MBTK_RADIO_TECH_GSM_COMPACT:
{
p_info->radio_tech = QL_NW_RADIO_TECH_GSM;
break;
}
case MBTK_RADIO_TECH_GSM_EGPRS:
{
p_info->radio_tech = QL_NW_RADIO_TECH_GPRS;
break;
}
case MBTK_RADIO_TECH_UTRAN:
{
p_info->radio_tech = QL_NW_RADIO_TECH_UMTS;
break;
}
case MBTK_RADIO_TECH_UTRAN_HSDPA:
{
p_info->radio_tech = QL_NW_RADIO_TECH_HSDPA;
break;
}
case MBTK_RADIO_TECH_UTRAN_HSUPA:
{
p_info->radio_tech = QL_NW_RADIO_TECH_HSUPA;
break;
}
case MBTK_RADIO_TECH_UTRAN_HSDPA_HSUPA:
{
p_info->radio_tech = QL_NW_RADIO_TECH_HSPA;
break;
}
case MBTK_RADIO_TECH_UTRAN_HSPA:
{
p_info->radio_tech = QL_NW_RADIO_TECH_HSPAP;
break;
}
case MBTK_RADIO_TECH_E_UTRAN:
{
p_info->radio_tech = QL_NW_RADIO_TECH_LTE;
break;
}
default:
{
p_info->radio_tech = QL_NW_RADIO_TECH_NONE;
break;
}
}
memset(mcc_mnc, 0x0, MBTK_BUFF_TEMP_SIZE_8);
ret = snprintf(mcc_mnc, MBTK_BUFF_TEMP_SIZE_8, "%d", net.plmn);
if(ret != QL_NW_MCC_MNC_MIN && ret != QL_NW_MCC_MNC_MAX)
{
QL_NW_LOGE("[%s] mcc mnc get fail.[%d]", __func__, ret);
}
else
{
memcpy(p_info->mcc, mcc_mnc, QL_NW_MCC_LENGHT);
memcpy(p_info->mnc, mcc_mnc + QL_NW_MCC_LENGHT, ret - QL_NW_MCC_LENGHT);
}
return QL_ERR_OK;
}
static int ql_get_creg_state(ql_nw_reg_status_info_t *p_info, ql_nw_info_handle_t *p_handle, ql_nw_reg_type_enum reg_type)
{
int ret = 0;
uint8 reg_state = 0;
mbtk_net_reg_info_t reg;
memset(&reg, 0x0, sizeof(mbtk_net_reg_info_t));
ret = mbtk_net_reg_get(p_handle->handle, &reg);
if(ret != MBTK_ERR_OK)
{
QL_NW_LOGE("[%s] net reg get fail.[%d]", __func__, ret);
return QL_ERR_FAILED;
}
if(reg_type == QL_NW_REG_TYPE_VOICE)
{
if(reg.ims_state == 0)
{
reg_state = reg.call_state;
}
else
{
reg_state = reg.ims_state;
}
}
else
{
if(reg.type == MBTK_RADIO_TECH_E_UTRAN)
{
reg_state = reg.data_state;
}
else
{
reg_state = reg.call_state;
}
}
p_info->deny_reason = QL_NW_CS_DOMAIN_NOT_AVAILABLE_DENY_REASON;
switch(reg_state)
{
case MBTK_NET_REG_STATE_HOME:
{
p_info->reg_state = QL_NW_SERVICE_FULL;
p_info->roaming = QL_NW_ROAM_STATE_OFF;
break;
}
case MBTK_NET_REG_STATE_DENIED:
{
p_info->reg_state = QL_NW_SERVICE_NONE;
p_info->roaming = QL_NW_ROAM_STATE_OFF;
p_info->deny_reason = QL_NW_CS_DOMAIN_NOT_AVAILABLE_DENY_REASON; //now not support
break;
}
case MBTK_NET_REG_STATE_ROAMING:
{
p_info->reg_state = QL_NW_SERVICE_FULL;
p_info->roaming = QL_NW_ROAM_STATE_ON;
break;
}
case MBTK_NET_REG_STATE_SMS_ONLY:
case MBTK_NET_REG_STATE_CSFB_HOME:
case MBTK_NET_REG_STATE_EMERGENCY_ONLY:
{
p_info->reg_state = QL_NW_SERVICE_LIMITED;
p_info->roaming = QL_NW_ROAM_STATE_OFF;
break;
}
case MBTK_NET_REG_STATE_ROAMING_SMS:
case MBTK_NET_REG_STATE_CSFB_ROAMING:
{
p_info->reg_state = QL_NW_SERVICE_LIMITED;
p_info->roaming = QL_NW_ROAM_STATE_ON;
break;
}
case MBTK_NET_REG_STATE_NON:
case MBTK_NET_REG_STATE_SEARCHING:
case MBTK_NET_REG_STATE_UNKNOWN:
case MBTK_NET_REG_STATE_ATTACHED_EMERGENCY:
default:
{
p_info->reg_state = QL_NW_SERVICE_NONE;
p_info->roaming = QL_NW_ROAM_STATE_OFF;
break;
}
}
p_info->cid = reg.ci;
p_info->lac = reg.lac;
return QL_ERR_OK;
}
static int8_t rssi_convert_to_dBm(uint8 rssi)
{
if(rssi <= 31)
{
return rssi * 2 - 113;
}
else
{
return -125;
}
}
static int16_t rsrp_convert_to_dBm(uint8 rsrp)
{
if(rsrp <= 96)
{
return rsrp - 140;
}
else
{
return -44;
}
}
static int16_t rsrq_convert_to_dB(uint8 rsrq)
{
if(rsrq >= 1 && rsrq <= 34)
{
return (rsrq + 1) / 2 - 20;
}
else
{
return -20;
}
}
static int16_t ecno_convert_to_dB(uint8 ecno)
{
if(ecno >= 48)
{
return 0;
}
else if(ecno == 255)
{
return 255;
}
else
{
return 48 - ecno;
}
}
static QL_NW_SIGNAL_STRENGTH_LEVEL_E ql_rssi_convert_level(uint8 rssi)
{
//rssi 0 - 31,99
if(rssi == 0 || rssi == 99)
{
return QL_NW_SIGNAL_STRENGTH_LEVEL_NONE;
}
else if(rssi >= 1 && rssi < 10)
{
return QL_NW_SIGNAL_STRENGTH_LEVEL_POOR;
}
else if(rssi >= 10 && rssi < 20)
{
return QL_NW_SIGNAL_STRENGTH_LEVEL_MODERATE;
}
else if(rssi >= 20 && rssi <= 30)
{
return QL_NW_SIGNAL_STRENGTH_LEVEL_GOOD;
}
else
{
return QL_NW_SIGNAL_STRENGTH_LEVEL_GREAT;
}
}
static void ql_signal_state_change_cb(const void* data, int data_len)
{
if(data && data_len == 8)
{
uint8 *net_data = (uint8*)data;
mbtk_radio_technology_enum type = (mbtk_radio_technology_enum)net_data[0];
QL_NW_LOGD("[%s] reg_type[%d].", __func__, type);
ql_nw_event_enum cmd = QL_NW_EVENT_SIGNAL_CB;
if(nw_handle->control[0] >= 0)
{
int ret = write(nw_handle->control[0], &cmd, MBTK_WRITE_EVENT_SIZE);
if(ret != MBTK_WRITE_EVENT_SIZE)
{
QL_NW_LOGE("[%s] write fail.[%d]", __func__, ret);
}
}
}
else
{
QL_NW_LOGD("[%s] unknown data.", __func__);
}
}
static void ql_net_state_change_cb(const void* data, int data_len)
{
if(data)
{
ql_nw_event_enum cmd = QL_NW_EVENT_VOICE_CB;
if(nw_handle->control[0] >= 0)
{
int ret = write(nw_handle->control[0], &cmd, MBTK_WRITE_EVENT_SIZE);
if(ret != MBTK_WRITE_EVENT_SIZE)
{
QL_NW_LOGE("[%s] write fail.[%d]", __func__, ret);
}
}
}
else
{
QL_NW_LOGD("[%s] unknown data.", __func__);
}
}
static void ql_nw_server_change_cb(const void* data, int data_len)
{
if(data_len != sizeof(int))
{
QL_NW_LOGE("[%s] data_len[%d] than int[%d] fail. ", __func__, data_len, sizeof(int));
}
else
{
int server_state = *(int *)data;
if(server_state == 1 && nw_handle->server_cb)
{
nw_handle->server_cb(QL_ERR_ABORTED);
}
}
}
static int ql_epoll_register(int epoll_fd, int fd)
{
struct epoll_event ev;
int ret, flags;
/* important: make the fd non-blocking */
flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
ev.events = EPOLLIN;
ev.data.fd = fd;
do
{
ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev);
if(ret < 0)
{
QL_NW_LOGE("[%s] epoll_ctl fail.[%s]", __func__, strerror(errno));
}
} while (ret < 0 && errno == EINTR);
return QL_ERR_OK;
}
static void* ql_cb_thread(void* arg)
{
ql_nw_info_handle_t* info = (ql_nw_info_handle_t*)arg;
if(info->control[0] < 0 && info->control[0] < 0)
{
if(socketpair(AF_LOCAL, SOCK_STREAM, 0, info->control ) < 0)
{
QL_NW_LOGE("[%s] control creat fail.", __func__);
return NULL;
}
}
int ne = 0;
int nevents = 0;
int ret = 0;
struct epoll_event events[3];
int control_fd = info->control[1];
ql_nw_event_enum cmd = QL_NW_EVENT_THREAD_QUIT;
//A maximum of three events can be processed simultaneously
int epoll_fd = epoll_create(3);
ql_epoll_register(epoll_fd, control_fd);
QL_NW_LOGE("[%s] thread start run.", __func__);
while(1)
{
nevents = epoll_wait(epoll_fd, events, 3, -1);
if(nevents < 0)
{
if(errno != EINTR)
{
QL_NW_LOGE("[%s] epoll_wait fail.[%s]", __func__, strerror(errno));
}
continue;
}
for (ne = 0; ne < nevents; ne++)
{
if((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0)
{
QL_NW_LOGE("[%s] EPOLLERR or EPOLLHUP event error.", __func__);
break;
}
if ((events[ne].events & EPOLLIN) != 0)
{
if (events[ne].data.fd == control_fd)
{
ret = read(control_fd, &cmd, MBTK_READ_EVENT_SIZE);
if(ret != MBTK_READ_EVENT_SIZE)
{
QL_NW_LOGE("[%s] read fail.[%d]", __func__, ret);
}
else
{
switch(cmd)
{
case QL_NW_EVENT_THREAD_QUIT:
{
close(epoll_fd);
epoll_fd = -1;
if(info->control[0] >= 0)
{
close(info->control[0]);
info->control[0] = -1;
}
if(info->control[1] >= 0)
{
close(info->control[1]);
info->control[1] = -1;
}
QL_NW_LOGD("[%s] thread quit.", __func__);
return NULL;
}
case QL_NW_EVENT_SIGNAL_CB:
{
if(info->signal_cb)
{
ql_nw_signal_strength_info_t signal_info = {0};
QL_NW_SIGNAL_STRENGTH_LEVEL_E level = QL_NW_SIGNAL_STRENGTH_LEVEL_MIN;
ql_nw_get_signal_strength(&signal_info, &level);
info->signal_cb(&signal_info, level);
}
break;
}
case QL_NW_EVENT_VOICE_CB:
{
if(info->voice_cb)
{
ql_nw_reg_status_info_t voice_reg_info = {0};
ql_nw_get_voice_reg_status(&voice_reg_info);
info->voice_cb(&voice_reg_info);
}
break;
}
default:
{
QL_NW_LOGE("[%s] unknown event.[%d]", __func__, cmd);
break;
}
}
}
}
}
}
}
}
static int ql_cb_thread_creat(ql_nw_info_handle_t *info)
{
if(info->cb_thread_id == 0)
{
pthread_attr_t thread_attr;
pthread_attr_init(&thread_attr);
if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
{
QL_NW_LOGE("[%s] pthread_attr_setdetachstate fail.", __func__);
return QL_ERR_FAILED;
}
if(pthread_create(&(info->cb_thread_id), &thread_attr, ql_cb_thread, info))
{
QL_NW_LOGE("[%s] pthread_create fail.[%ld]", __func__, info->cb_thread_id);
return QL_ERR_FAILED;
}
QL_NW_LOGD("[%s] pthread_create success.[%ld]", __func__, info->cb_thread_id);
}
return QL_ERR_OK;
}
static int ql_cb_thread_free(ql_nw_info_handle_t *info)
{
int ret = 0;
if(info->cb_thread_id != 0)
{
ql_nw_event_enum cmd = QL_NW_EVENT_THREAD_QUIT;
if(info->control[0] >= 0)
{
ret = write(info->control[0], &cmd, MBTK_WRITE_EVENT_SIZE);
if(ret != MBTK_WRITE_EVENT_SIZE)
{
QL_NW_LOGE("[%s] write fail.[%d]", __func__, ret);
return QL_ERR_FAILED;
}
}
info->cb_thread_id = 0;
QL_NW_LOGE("[%s] pthread quit success.", __func__);
}
return QL_ERR_OK;
}
/*----------------------------------------------NW FUNCTION--------------------------------------*/
/*-----------------------------------------------------------------------------------------------*/
/**
@brief Initialize NW service.
@note You must call this function before other functions can be used in this module.
@return Whether the NW service was successfully intialized.
@retval QL_ERR_OK successful
@retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_init(void)
{
if(NULL == nw_handle)
{
nw_handle = (ql_nw_info_handle_t*)malloc(sizeof(ql_nw_info_handle_t));
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle malloc fail.", __func__);
return QL_ERR_FAILED;
}
nw_handle->handle = mbtk_ril_open(MBTK_AT_PORT_DEF);
if(NULL == nw_handle->handle)
{
QL_NW_LOGE("[%s] mbtk handle init fail.", __func__);
goto error_1;
}
int ret = mbtk_signal_state_change_cb_reg(ql_signal_state_change_cb);
if(ret != MBTK_ERR_OK)
{
QL_NW_LOGE("[%s] set nw signal cb fail.[%d]", __func__, ret);
goto error_2;
}
ret = mbtk_net_reg_state_change_cb_reg(ql_net_state_change_cb);
if(ret != MBTK_ERR_OK)
{
QL_NW_LOGE("[%s] set nw signal cb fail.[%d]", __func__, ret);
goto error_2;
}
ret = mbtk_ril_ser_state_change_cb_reg(ql_nw_server_change_cb);
if(ret != MBTK_ERR_OK)
{
QL_NW_LOGE("[%s] set sim server cb fail.[%d]", __func__, ret);
goto error_2;
}
nw_handle->signal_cb = NULL;
nw_handle->voice_cb = NULL;
nw_handle->control[0] = -1;
nw_handle->control[1] = -1;
nw_handle->cb_thread_id = 0;
}
return QL_ERR_OK;
error_2:
if(nw_handle->handle)
{
mbtk_ril_close(MBTK_AT_PORT_DEF);;
nw_handle->handle = NULL;
}
error_1:
if(nw_handle)
{
free(nw_handle);
nw_handle = NULL;
}
return QL_ERR_FAILED;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief Deinitializes NW service.
@return Whether the NW service was deinitialized successfully.
@retval QL_ERR_OK successful.
@retval Other error code defined by ql_type.h.
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_deinit(void)
{
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
int ret = 0;
nw_handle->voice_cb = NULL;
nw_handle->signal_cb = NULL;
if(NULL != nw_handle->handle)
{
ret = mbtk_ril_close(MBTK_AT_PORT_DEF);
if(ret != MBTK_ERR_OK)
{
QL_NW_LOGE("[%s] mbtk handle deinit fail.[%d]", __func__, ret);
return QL_ERR_FAILED;
}
nw_handle->handle = NULL;
}
ret = ql_cb_thread_free(nw_handle);
if(ret != QL_ERR_OK)
{
QL_NW_LOGE("[%s] cb thread free deinit fail.", __func__);
return QL_ERR_FAILED;
}
free(nw_handle);
nw_handle = NULL;
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief scan network status.
@param[out] async_index The index of request msg
@param[in] async_cb The callback function of request msg
@return Whether to successfully trigger the network scan operation
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_network_scan(int *async_index, ql_nw_network_scan_async_cb async_cb)
{
UNUSED(async_index);
UNUSED(async_cb);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief set power mode.
@param[in] lower_mode, defined by QL_NW_LOWER_POWER_MASK_XXX
@return Whether to successfully set the power mode
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_set_power_mode(uint8_t lower_mode)
{
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
uint32 mode = 0;
if((lower_mode & QL_NW_LOWER_POWER_MASK_NORMAL) == QL_NW_LOWER_POWER_MASK_NORMAL)
{
mode |= 0x1;
}
if((lower_mode & QL_NW_LOWER_POWER_MASK_NETWORK) == QL_NW_LOWER_POWER_MASK_NETWORK)
{
mode |= 0x1;
}
if((lower_mode & QL_NW_LOWER_POWER_MASK_SIM) == QL_NW_LOWER_POWER_MASK_SIM)
{
mode |= 0x2;
}
if((lower_mode & QL_NW_LOWER_POWER_MASK_SMS) == QL_NW_LOWER_POWER_MASK_SMS)
{
mode |= 0x4;
}
if((lower_mode & QL_NW_LOWER_POWER_MASK_VOICE) == QL_NW_LOWER_POWER_MASK_VOICE)
{
mode |= 0x8;
}
int ret = 0;
ret = mbtk_wakeup_state_set(nw_handle->handle, mode);
if(ret != MBTK_ERR_OK)
{
QL_NW_LOGE("[%s] wakeup state set fail.[%d]", ret);
return QL_ERR_FAILED;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief set perferred NW mode and roaming indicator.
@param[in] p_info Pointer that point to ql_nw_pref_nwmode_roaming_info_t
@return Whether to successfully set nwmode and roaming
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_set_pref_nwmode_roaming(ql_nw_pref_nwmode_roaming_info_t *p_info)
{
UNUSED(p_info);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief get perferred NW mode and roaming indicator.
@param[out] p_info Pointer that point to ql_nw_pref_nwmode_roaming_info_t
@return Whether to successfully get nwmode and roaming
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_get_pref_nwmode_roaming(ql_nw_pref_nwmode_roaming_info_t *p_info)
{
UNUSED(p_info);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief get mobile operator name.
@param[out] p_info Pointer that point to ql_nw_mobile_operator_name_info_t
@return Whether to successfully get the mobile operator name
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_get_mobile_operator_name(ql_nw_mobile_operator_name_info_t *p_info)
{
UNUSED(p_info);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief get cell information.
@param[out] p_info Pointer that point to ql_nw_cell_info_t
@return Whether to successfully get the cell information
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_get_cell_info(ql_nw_cell_info_t *p_info)
{
UNUSED(p_info);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief get voice registration status.
@param[out] p_info Pointer that point to ql_nw_reg_status_info_t
@return Whether to successfully get the voice registration status
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_get_voice_reg_status(ql_nw_reg_status_info_t *p_info)
{
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
if(NULL == p_info)
{
QL_NW_LOGE("[%s] p_info is NULL.", __func__);
return QL_ERR_INVALID_ARG;
}
int ret = 0;
ql_nw_reg_status_info_t reg_status_info = {0};
memset(&reg_status_info, 0x0, sizeof(ql_nw_reg_status_info_t));
reg_status_info.tech_domain = QL_NW_TECH_DOMAIN_3GPP; //default
//get radio_tech mcc mnc
ret = ql_get_cops_state(&reg_status_info, nw_handle);
if(ret != QL_ERR_OK)
{
QL_NW_LOGE("[%s] get cops state fail.[%d]", __func__, ret);
return QL_ERR_FAILED;
}
//get roaming deny_reason reg_state cid lac
ret = ql_get_creg_state(&reg_status_info, nw_handle, QL_NW_REG_TYPE_VOICE);
if(ret != QL_ERR_OK)
{
QL_NW_LOGE("[%s] get creg fail.[%d]", __func__, ret);
return QL_ERR_FAILED;
}
memcpy(p_info, &reg_status_info, sizeof(ql_nw_reg_status_info_t));
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief get data registration status.
@param[out] p_info Pointer that point to ql_nw_reg_status_info_t
@return Whether to successfully get the data registration status
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_get_data_reg_status(ql_nw_reg_status_info_t *p_info)
{
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
if(NULL == p_info)
{
QL_NW_LOGE("[%s] p_info is NULL.", __func__);
return QL_ERR_INVALID_ARG;
}
int ret = 0;
ql_nw_reg_status_info_t reg_status_info = {0};
memset(&reg_status_info, 0x0, sizeof(ql_nw_reg_status_info_t));
reg_status_info.tech_domain = QL_NW_TECH_DOMAIN_3GPP; //default
//get radio_tech mcc mnc
ret = ql_get_cops_state(&reg_status_info, nw_handle);
if(ret != QL_ERR_OK)
{
QL_NW_LOGE("[%s] get cops state fail.[%d]", __func__, ret);
return QL_ERR_FAILED;
}
//get roaming deny_reason reg_state cid lac
ret = ql_get_creg_state(&reg_status_info, nw_handle, QL_NW_REG_TYPE_DATA);
if(ret != QL_ERR_OK)
{
QL_NW_LOGE("[%s] get creg fail.[%d]", __func__, ret);
return QL_ERR_FAILED;
}
memcpy(p_info, &reg_status_info, sizeof(ql_nw_reg_status_info_t));
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief get current signal strength.
@param[out] p_info Pointer that point to ql_nw_signal_strength_info_t
@param[out] p_level: signal strength level
@return Whether to successfully get the signal strength
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_get_signal_strength(ql_nw_signal_strength_info_t *p_info, QL_NW_SIGNAL_STRENGTH_LEVEL_E* p_level)
{
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
if(NULL == p_info || NULL == p_level)
{
QL_NW_LOGE("[%s] param is NULL.", __func__);
return QL_ERR_INVALID_ARG;
}
int ret = 0;
mbtk_signal_info_t signal;
memset(&signal, 0x0, sizeof(mbtk_signal_info_t));
ret = mbtk_net_signal_get(nw_handle->handle, &signal);
if(ret != MBTK_ERR_OK)
{
QL_NW_LOGE("[%s] net signal get fail.[%d]", __func__, ret);
return QL_ERR_FAILED;
}
memset(p_info, 0x0, sizeof(ql_nw_signal_strength_info_t));
switch(signal.type)
{
case MBTK_RADIO_TECH_GSM:
case MBTK_RADIO_TECH_GSM_COMPACT:
case MBTK_RADIO_TECH_GSM_EGPRS:
{
p_info->has_gsm = TRUE;
p_info->gsm.rssi = rssi_convert_to_dBm(signal.rssi);
break;
}
case MBTK_RADIO_TECH_E_UTRAN:
{
p_info->has_lte = TRUE;
p_info->lte.rssi = rssi_convert_to_dBm(signal.rssi);
p_info->lte.rsrq = rsrq_convert_to_dB(signal.rsrq);
p_info->lte.rsrp = rsrp_convert_to_dBm(signal.rsrp);
p_info->lte.snr = 0x7FFF;//->MBTK??????(?????rssnr,??INT_MAX:0x7FFFFFFFF?????),????0x7FFFFFFFF
break;
}
case MBTK_RADIO_TECH_UTRAN:
case MBTK_RADIO_TECH_UTRAN_HSDPA:
case MBTK_RADIO_TECH_UTRAN_HSUPA:
case MBTK_RADIO_TECH_UTRAN_HSDPA_HSUPA:
case MBTK_RADIO_TECH_UTRAN_HSPA:
{
p_info->has_wcdma = TRUE;
p_info->wcdma.rssi = rssi_convert_to_dBm(signal.rssi);
p_info->wcdma.ecio = ecno_convert_to_dB(signal.ecno);
break;
}
default:
{
QL_NW_LOGE("[%s] unknown reg type.[%d]", __func__, signal.type);
break;
}
}
*p_level = ql_rssi_convert_level(signal.rssi);
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief get current cell acccess status.
@param[out] p_info Pointer that point to QL_NW_CELL_ACCESS_STATE_TYPE_E
@return Whether to successfully get the cell access status
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_get_cell_access_status(QL_NW_CELL_ACCESS_STATE_TYPE_E *p_info)
{
UNUSED(p_info);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief get network time.
@param[out] p_info Pointer that point to ql_nw_nitz_time_info_t
@return Whether to successfully get the network time
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_get_nitz_time_info(ql_nw_nitz_time_info_t *p_info)
{
UNUSED(p_info);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief register voice registration event.
@param[in] cb_func Voice registration indication callback function
@return Whether the voice registration event was successfully registered.
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_set_voice_reg_ind_cb(ql_nw_voice_reg_ind_cb cb_func)
{
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
int ret = QL_ERR_OK;
if(NULL != cb_func)
{
ret = ql_cb_thread_creat(nw_handle);
if(ret != QL_ERR_OK)
{
QL_NW_LOGE("[%s] cb thread creat fail.", __func__);
}
}
else
{
ret = ql_cb_thread_free(nw_handle);
if(ret != QL_ERR_OK)
{
QL_NW_LOGE("[%s] cb thread free deinit fail.", __func__);
return QL_ERR_FAILED;
}
}
nw_handle->voice_cb = cb_func;
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief register data registration event.
@param[in] cb_func Data registration indication callback function
@return Whether the data registration event was successfully registered.
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_set_data_reg_ind_cb(ql_nw_data_reg_ind_cb cb_func)
{
UNUSED(cb_func);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief register signal strength event.
@param[in] cb_func Signal strength indication callback function
@return Whether the signal strength event was successfully registered
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_set_signal_strength_ind_cb(ql_nw_signal_strength_ind_cb cb_func)
{
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
int ret = QL_ERR_OK;
if(NULL != cb_func)
{
ret = ql_cb_thread_creat(nw_handle);
if(ret != QL_ERR_OK)
{
QL_NW_LOGE("[%s] cb thread creat fail.", __func__);
}
}
else
{
ret = ql_cb_thread_free(nw_handle);
if(ret != QL_ERR_OK)
{
QL_NW_LOGE("[%s] cb thread free deinit fail.", __func__);
return QL_ERR_FAILED;
}
}
nw_handle->signal_cb = cb_func;
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief register cell access status event.
@param[in] cb_func Cell access status indication callback function
@return Whether the cell access status event was successfully registered
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_set_cell_access_status_ind_cb(ql_nw_cell_access_status_ind_cb cb_func)
{
UNUSED(cb_func);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief register network time event.
@param[in] cb_func nitz time update indication callback function
@return Whether the network time event was successfully registered
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_set_nitz_time_update_ind_cb(ql_nw_nitz_time_update_ind_cb cb_func)
{
UNUSED(cb_func);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief register wea alert event.
@param[in] cb_func wea alert indication callback function
@return Whether the network time event was successfully registered
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_set_wea_alert_ind_cb(ql_nw_wea_reg_ind_cb cb_func)
{
UNUSED(cb_func);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief register etws alert event.
@param[in] cb_func etws alert indication callback function
@return Whether the network time event was successfully registered
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_set_etws_alert_ind_cb(ql_nw_etws_reg_ind_cb cb_func)
{
UNUSED(cb_func);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief set wea alert config.
@param[in] item Items to set.
@param[in] p_info Pointer that point to ql_nw_wea_config_t.
@return Whether to successfully set the wea config.
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_set_wea_config(int item, ql_nw_wea_config_t *p_info)
{
UNUSED(p_info);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief Gets wea config.
@param[out] p_config wea config.
@return Whether the wea config was successfully obtained.
@retval QL_ERR_OK successful.
@retval QL_ERR_INVALID_ARG invalid argument.
@retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
@retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
@retval Other error code defined by ql_type.h.
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_get_wea_config(ql_nw_wea_config_t *p_config)
{
UNUSED(p_config);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief set etws alert config.
@param[in] etws config.
@return Whether to successfully set the etws config.
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_set_etws_config(uint8_t enable_etws)
{
UNUSED(enable_etws);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief get etws alert config.
@param[out] p_enable_etws Pointer.
@return Whether to successfully set the etws config.
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_get_etws_config(uint8_t* p_enable_etws)
{
UNUSED(p_enable_etws);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief bind subscription
@param[in] sub_type subscription type
@return Whether to successfully bind subscription.
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_bind_subscription(QL_NW_BIND_SUB_TYPE_E sub_type)
{
UNUSED(sub_type);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief get high capability subscription.
@param[out] p_high_cap pointer that point to QL_NW_BIND_SUB_TYPE_E
@return Whether the high capability subscription was successfully obtained.
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_get_high_cap_sub(QL_NW_BIND_SUB_TYPE_E *p_high_cap)
{
UNUSED(p_high_cap);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief set the SIM card index that can uniquely register to the 5G network.
the main difference between high and non-high capability subscription is that high capability
subscription can register to 5G network while non-high capability subscription can only
register to LTE or GSM.
@param[in] high_cap high capability subscription
@return Whether to successfully set the high capability subscription.
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_set_high_cap_sub(QL_NW_BIND_SUB_TYPE_E high_cap)
{
UNUSED(high_cap);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@brief Disable NR5G, NR5G_SA and NR5G_NSA can be disabled individually or together.
@param[in] opt_mask Option mask value. Value:
0 - Do not disable NR5G
QL_NW_NR5G_SO_SA - Disable NR5G SA
QL_NW_NR5G_SO_NSA - Disable NR5G NSA
@return Whether to successfully disable NR5G mode.
@retval QL_ERR_OK successful
@retval QL_ERR_NOT_INIT uninitialized
@retval QL_ERR_SERVICE_NOT_READY service is not ready
@retval QL_ERR_INVALID_ARG Invalid arguments
@retval Other error code defined by ql_type.h
*/
/*-----------------------------------------------------------------------------------------------*/
int ql_nw_disable_nr5g(uint16_t opt_mask)
{
UNUSED(opt_mask);
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
return QL_ERR_OK;
}
/*-----------------------------------------------------------------------------------------------*/
/**
@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_nw_set_service_error_cb(ql_nw_service_error_cb_f cb)
{
if(NULL == nw_handle)
{
QL_NW_LOGE("[%s] nw handle not init.", __func__);
return QL_ERR_NOT_INIT;
}
nw_handle->server_cb = cb;
return QL_ERR_OK;
}