blob: 4c6f1b4bc34750a44a2f685fe52f31f4293eba63 [file] [log] [blame]
// Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "global.h"
#include "wm_ioctl.h"
#include "error.h"
#include "handle.h"
#include "sdk.h"
#include "wimax.h"
#include "nds.h"
#include "device.h"
#include "io.h"
#include "fload.h"
#include "hci.h"
#include "log.h"
#if defined(CONFIG_ENABLE_SERVICE_FLOW)
#include "sf.h"
extern void dev_update_service_flow(int dev_idx, struct hci *pkt);
#endif // CONFIG_ENABLE_SERVICE_FLOW
#include "eap.h"
#define LOG_FILE_PREFIX "sdk"
#define LOG_FILE_EXT "log"
#define LOG_FILE "sdk.log"
#define LOCK_PATH "/var/lock/gct/"
#define LOCK_FILE LOCK_PATH "gct_sdk.lock"
sdk_mng_t sdk_mng;
extern void array_DB2H(u32 *arr, int n);
extern void array_B2H(u16 *arr, int n);
int sdk_on_ind_event(sdk_internal_t *sdk, int dev_idx, fsm_event_t event);
int sdk_on_app_event(sdk_internal_t *sdk, int dev_idx, fsm_event_t event);
static int sdk_set_ioctl_profile_id(int dev_idx, u32 profile_id);
const char *sdk_version(void)
{
return SDK_VERSION;
}
static int sdk_check_lock_file(void)
{
int fd;
if (access(LOCK_PATH, F_OK))
mkdir(LOCK_PATH, 0755);
if (access(LOCK_FILE, F_OK) < 0) {
if ((fd = open(LOCK_FILE, O_CREAT|O_WRONLY|O_TRUNC, 0755)) < 0) {
xprintf(SDK_STD_ERR, "Creating fail(%s)\n", LOCK_FILE);
return -1;
}
close(fd);
return 0;
}
xprintf(SDK_STD_ERR, "API is locked.(%s)\n", LOCK_FILE);
return -1;
}
static int sdk_delete_lock_file(void)
{
xprintf(SDK_DBG, "unlink %s\n", LOCK_FILE);
return unlink(LOCK_FILE);
}
static void sdk_init_seed(void)
{
struct timeval now;
gettimeofday(&now, NULL);
srand(now.tv_sec+now.tv_usec);
}
sdk_internal_t *sdk_get_rw_handle(void)
{
struct list_head *head = hand_get_api_handle_list();
api_hand_t *handle;
sdk_internal_t *ret = NULL;
pthread_mutex_lock(&api_handle_lock);
list_for_each_entry(handle, head, list) {
if (!handle->sdk->ro) {
ret = handle->sdk;
break;
}
}
pthread_mutex_unlock(&api_handle_lock);
return ret;
}
static void sdk_set_logpath(char *buf, const char *dir)
{
time_t t;
struct tm *tms;
char time_buf[256];
time(&t);
tms = localtime(&t);
sprintf(time_buf, "%04d%02d%02d-%02d.%02d.%02d",
tms->tm_year+1900, tms->tm_mon+1, tms->tm_mday,
tms->tm_hour, tms->tm_min, tms->tm_sec);
sprintf(buf, "%s/%s_%s.%s", dir, LOG_FILE_PREFIX, time_buf, LOG_FILE_EXT);
}
static void path_trim(char *path)
{
int len;
len = strlen(path) - 1/*move to last char*/;
while (path[len] == '/' || path[len] == '\\')
path[len--] = 0;
}
int sdk_init(GCT_WIMAX_SDK_MODE mode, GCT_WIMAX_API_PARAM *sdk_param)
{
int log_level;
char log_file[512];
int ret;
assert(sizeof(struct wm_req_s) <= sizeof(struct ifreq));
assert(SIOC_DATA_END <= SIOC_DATA_MAX);
if (sdk_param) {
strcpy(sdk_mng.nonvolatile_dir, sdk_param->nonvolatile_dir);
strcpy(sdk_mng.log_path, sdk_param->log_path);
path_trim(sdk_mng.nonvolatile_dir);
path_trim(sdk_mng.log_path);
log_level = sdk_param->log_level;
}
else {
strcpy(sdk_mng.nonvolatile_dir, "./");
strcpy(sdk_mng.log_path, "./sdklog");
log_level = 1;
}
if (mode & GCT_WIMAX_SDK_EMBEDDED_EAP_ENABLED)
sdk_mng.eeap_enabled = TRUE;
if (mode & GCT_WIMAX_SDK_OMA_DM_ENABLED)
sdk_mng.odm_enabled = TRUE;
sdk_init_seed();
if ((ret = mkdir(sdk_mng.log_path, 0644)) < 0 && errno != EEXIST) {
fprintf(stderr, "Make directory(%s) failed %s(%d)\n",
sdk_mng.log_path, strerror(errno), errno);
}
sdk_set_logpath(log_file, sdk_mng.log_path);
#if defined(SDK_TEST)
unlink(LOG_FILE);
strcpy(log_file, LOG_FILE);
printf("####################################################\n");
printf("############## NOTE: SDK_TEST Enabled ##############\n");
printf("############## LOG FILE PATH: %s ##############\n", log_file);
printf("####################################################\n");
#endif
timer_module_init();
log_init(log_file, log_level);
hand_init();
ret = dm_init();
hci_receiver_create(&sdk_mng.hci_recvr);
return ret;
}
int sdk_deinit(void)
{
int ret;
hci_receiver_delete(&sdk_mng.hci_recvr);
ret = dm_deinit();
log_deinit();
hand_deinit();
timer_module_deinit();
if (sdk_get_rw_handle())
sdk_delete_lock_file();
return ret;
}
int sdk_check_handle(api_hand_t *api_hand, int dev_idx)
{
api_hand_t *api = api_hand;
sdk_internal_t *sdk = api->sdk;
int ret = 0;
if (api_hand == NULL) {
xprintf(SDK_ERR, "API handle is NULL\n", api_hand);
ret = sdk_set_errno(ERR_INVALID);
goto out;
}
if (sdk->struct_size != sizeof(sdk_internal_t)) {
xprintf(SDK_ERR, "Wrong structure size(%d!=%d)\n", sdk->struct_size, sizeof(api_hand_t));
ret = sdk_set_errno(ERR_INVALID);
goto out;
}
if (NO_DEV != dev_idx) {
if (dev_idx < DEV_BASE_IDX || dev_idx >= MAX_DEVICE) {
xprintf(SDK_ERR, "Device index %d is wrong\n", dev_idx);
ret = sdk_set_errno(ERR_INVALID_DEV);
goto out;
}
if (!sdk->dev_open[dev_idx]) {
xprintf(SDK_ERR, "Device(%d) was not opened!\n", dev_idx);
ret = sdk_set_errno(ERR_INVALID);
goto out;
}
if (!dm_tst_dev(dev_idx)) {
xprintf(SDK_ERR, "Device(%d) was not inserted!\n", dev_idx);
ret = sdk_set_errno(ERR_INVALID_DEV);
goto out;
}
}
out:
return ret;
}
void *sdk_ind_thread(void *sdk_ptr)
{
sdk_internal_t *sdk = (sdk_internal_t *) sdk_ptr;
int prim;
ind_msg_t *msg;
dev_hand_t dev_hand;
bool dev_opened;
SDKIndRcvHCIPacket recv_hci;
SDKIndDeviceInsertRemove insert_remove;
SDKIndControlPowerManagement pow_mng;
SDKIndDeviceStatusUpdate stat_update;
SDKIndConnectToNetwork connect_net;
SDKIndDisconnectFromNetwork disconnect_net;
SDKIndNetworkSearchWideScan net_search_wscan;
SDKIndProvisioningOperation provisioning;
SDKIndPackageUpdate package_update;
SDKIndNotification notification;
SDKIndModeChange power_mode;
dev_hand.api = sdk->api;
xfunc_in();
while (1) {
if (msg_recv(&sdk->ind.msg_cb, &prim, (void **)&msg) < 0) {
xprintf(SDK_ERR, "msg_recv error\n");
break;
}
if (msg == THREAD_EXIT_MSG) {
xprintf(SDK_INFO, "%s thread exit...\n", __FUNCTION__);
break;
}
dev_hand.dev_idx = msg->dev_idx;
dev_opened = sdk->dev_open[msg->dev_idx] && dm_tst_dev(msg->dev_idx);
xprintf(SDK_DBG, "recv ind msg: prim=%d, dev_opened=%d\n", prim, dev_opened);
switch (prim) {
case ind_recv_hci:
recv_hci = sdk->ind.recv_hci;
if (dev_opened && recv_hci)
recv_hci(&dev_hand, msg->u.recv_hci.buf, msg->u.recv_hci.len);
sdk_free(msg->u.recv_hci.buf);
break;
case ind_insert_remove:
insert_remove = sdk->ind.insert_remove;
if (insert_remove)
insert_remove(&dev_hand, msg->u.insert_remove.presence);
break;
case ind_pow_mng:
pow_mng = sdk->ind.pow_mng;
if (dev_opened && pow_mng)
pow_mng(&dev_hand, msg->u.pow_mng.state);
break;
case ind_stat_update:
stat_update = sdk->ind.stat_update;
if (dev_opened && stat_update)
stat_update(&dev_hand, msg->u.stat_update.device_status,
msg->u.stat_update.status_reason, msg->u.stat_update.progress_info);
break;
case ind_connect_net:
connect_net = sdk->ind.connect_net;
if (dev_opened && connect_net)
connect_net(&dev_hand, msg->u.connect_net.response);
break;
case ind_disconnect_net:
disconnect_net = sdk->ind.disconnect_net;
if (dev_opened && disconnect_net)
disconnect_net(&dev_hand, msg->u.disconnect_net.response);
break;
case ind_net_search_wscan:
net_search_wscan = sdk->ind.net_search_wscan;
if (dev_opened && net_search_wscan)
net_search_wscan(&dev_hand,
msg->u.net_search_wscan.nsp_list, msg->u.net_search_wscan.list_cnt);
break;
case ind_provisioning:
provisioning = sdk->ind.provisioning;
if (dev_opened && provisioning)
provisioning(&dev_hand,
msg->u.provisioning.operation, msg->u.provisioning.contact_type);
break;
case ind_package_update:
package_update = sdk->ind.package_update;
if (dev_opened && package_update)
package_update(&dev_hand, msg->u.package_update.update);
break;
case ind_notification:
notification = sdk->ind.notification;
if (dev_opened && notification)
notification(&dev_hand,
msg->u.notification.category, msg->u.notification.type,
msg->u.notification.buf_len, msg->u.notification.buf);
break;
case ind_mode_change:
power_mode = sdk->ind.power_mode;
if (dev_opened && power_mode)
power_mode(&dev_hand, msg->u.power_mode.power_mode);
break;
default:
break;
}
sdk_free(msg);
}
msg_deinit(&sdk->ind.msg_cb);
xprintf(SDK_INFO, "Exit sdk-ind-thread\n");
xfunc_out();
return NULL;
}
void sdk_init_ind(sdk_internal_t *sdk)
{
msg_init(&sdk->ind.msg_cb);
pthread_create(&sdk->ind.thread, NULL, sdk_ind_thread, sdk);
}
void sdk_deinit_ind(sdk_internal_t *sdk)
{
pthread_t thread;
xfunc_in("thread=0x%08X", (int) sdk->ind.thread);
if ((thread = sdk->ind.thread)) {
sdk->ind.thread = (pthread_t) NULL;
msg_send(&sdk->ind.msg_cb, 0, THREAD_EXIT_MSG);
pthread_join(thread, NULL);
}
xfunc_out();
}
api_hand_t *sdk_api_open(int mode)
{
api_hand_t *api_hand = NULL;;
sdk_internal_t *sdk;
int ro = mode & sdk_read_only;
xfunc_in("mode=0x%X", mode);
if (!ro && (sdk_check_lock_file() < 0)) {
sdk_set_errno(ERR_PERM);
goto out;
}
api_hand = hand_alloc_api();
if (api_hand) {
sdk = api_hand->sdk = (sdk_internal_t *) sdk_malloc(sizeof(sdk_internal_t));
assert(sdk != NULL);
memset(sdk, 0, sizeof(sdk_internal_t));
sdk->struct_size = sizeof(sdk_internal_t);
sdk->api = api_hand;
sdk->ro = ro;
sdk->mode = mode;
sdk_init_ind(sdk);
}
out:
xfunc_out("api_hand=0x%08X", api_hand);
return api_hand;
}
int sdk_api_close(api_hand_t *api_hand)
{
sdk_internal_t *sdk = api_hand->sdk;
int ret, i;
xfunc_in();
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
for (i = 1; i < MAX_DEVICE; i++) {
if (sdk->dev_open[i]) {
ret = sdk_device_close(api_hand, i);
xprintf(SDK_DBG, "device(%d) has been closed with %d.\n", i, ret);
}
}
if (!sdk->ro)
sdk_delete_lock_file();
sdk_deinit_ind(sdk);
ret = hand_free_api(api_hand);
sdk_free(sdk);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_debug_level(api_hand_t *api_hand, int level)
{
int ret;
xfunc_in();
if (sdk_check_handle(api_hand, NO_DEV) < 0)
ret = -1;
else
ret = log_set_level(level);
xfunc_out();
return ret;
}
int sdk_print_log(api_hand_t *api_hand, int flag, const char *title, const char *str)
{
int ret;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
ret = -1;
else
ret = log_printf_string(SDK_API_LOG, flag, title, str);
return ret;
}
int sdk_get_device_list(api_hand_t *api_hand, WIMAX_API_HW_DEVICE_ID *dev_list,
u32 *list_cnt)
{
dev_mng_t *dm = dm_get_dev_mng();
int cnt = 0, i;
xfunc_in("list_cnt=%d", *list_cnt);
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
pthread_mutex_lock(&dm->detect_lock);
for (i = DEV_BASE_IDX; i < MAX_DEVICE; i++) {
if (dm->devices[i] && dm->devices[i]->inserted) {
if (cnt >= *list_cnt)
break;
dev_list[cnt].deviceIndex = i;
mbstowcs((wchar_t *)dev_list[cnt].deviceName, dm->devices[i]->name,
strlen(dm->devices[i]->name)+1);
dev_list[cnt].deviceType = WIMAX_API_DEV_TYPE_WIMAX;
cnt++;
}
if (cnt == dm->dev_cnt)
break;
}
*list_cnt = cnt;
pthread_mutex_unlock(&dm->detect_lock);
xfunc_out("list_cnt=%d", *list_cnt);
return 0;
}
int sdk_device_open(api_hand_t *api_hand, int dev_idx)
{
sdk_internal_t *sdk = api_hand->sdk;
device_t *dev;
int ret;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
if (dev_idx < DEV_BASE_IDX || dev_idx >= MAX_DEVICE)
return sdk_set_errno(ERR_INVALID_DEV);
ret = dm_open_device(dev_idx);
if (!ret) {
if (!(dev = dm_get_dev(dev_idx)))
goto out;
sdk->dev_open[dev_idx] = TRUE;
if (dev->open_cnt == 1) {
if (!sdk->ro) {
ret = wm_set_capability(dev_idx, DEFAULT_CAPABILITY);
if (ret < 0)
goto put;
}
ret = wm_init_device_info(dev_idx);
if (ret < 0)
goto put;
if (!sdk->ro) {
#if defined(CONFIG_ENABLE_SERVICE_FLOW)
sf_init(dev_idx);
#endif // CONFIG_ENABLE_SERVICE_FLOW
ret = wm_set_eap(dev_idx, FALSE);
if (ret < 0)
goto put;
wm_init_scan(dev_idx);
if (!api_hand->sdk->ro)
dm_set_status(dev_idx, M_INIT, C_INIT);
ret = wm_set_run_mode(dev_idx, sdk->mode);
if (ret < 0)
goto put;
}
}
ret = sdk_on_app_event(sdk, dev_idx, AM_Open);
put:
if (ret < 0)
sdk->dev_open[dev_idx] = FALSE;
dm_put_dev(dev_idx);
}
out:
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_internal_device_close(struct sdk_internal_s *sdk, int dev_idx)
{
int ret = 1;
xfunc_in("dev=%d", dev_idx);
if (sdk->dev_open[dev_idx]) {
if (!sdk->ro) {
wm_deinit_scan(dev_idx);
#if defined(CONFIG_ENABLE_SERVICE_FLOW)
sf_deinit(dev_idx);
#endif // CONFIG_ENABLE_SERVICE_FLOW
}
sdk_on_app_event(sdk, dev_idx, AM_Close);
sdk->dev_open[dev_idx] = FALSE;
ret = dm_close_device(dev_idx);
}
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_device_close(api_hand_t *api_hand, int dev_idx)
{
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (api_hand && api_hand->sdk && !api_hand->sdk->dev_open[dev_idx]) {
xprintf(SDK_DBG, "device(%d) has been closed or was not opened!\n");
goto out;
}
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
ret = sdk_internal_device_close(api_hand->sdk, dev_idx);
out:
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_get_status(sdk_internal_t *sdk, int dev_idx, int *m_status, int *c_status)
{
device_t *dev;
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (!(dev = dm_get_dev(dev_idx)))
return -1;
if (sdk && sdk->ro)
ret = dm_get_status(dev_idx, m_status, c_status);
else {
*m_status = dev->fsm.m_status;
*c_status = dev->fsm.c_status;
}
dm_put_dev(dev_idx);
xfunc_out("m_status=%d, c_status=%d", *m_status, *c_status);
return ret;
}
int sdk_set_status(sdk_internal_t *sdk, int dev_idx, int m_status, int c_status)
{
device_t *dev;
int ret = 0;
fsm_t fsm;
xfunc_in("dev=%d, m_status=%d, c_status=%d", dev_idx, m_status, c_status);
if (!(dev = dm_get_dev(dev_idx)))
return -1;
if (!sdk || !sdk->ro) {
fsm = dev->fsm;
dev->fsm.m_status = m_status;
dev->fsm.c_status = c_status;
ret = dm_set_status(dev_idx, m_status, c_status);
if (!ret) {
if (m_status == M_CONNECTED)
net_updown(dev_idx, TRUE);
else if (fsm.m_status == M_CONNECTED)
net_updown(dev_idx, FALSE);
}
}
dm_put_dev(dev_idx);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_convert_status(int dev_idx, WIMAX_API_DEVICE_STATUS_P status,
WIMAX_API_CONNECTION_PROGRESS_INFO_P connect_prog_info,
int m_status, int c_status)
{
/*
return value
0: ok. Status-Indication is called.
1: ok. Status-Indication is NOT called.
-1: error.
*/
int ret = 0;
if ((u32)m_status >= M_FSM_END || (u32)c_status >= C_FSM_END) {
xprintf(SDK_ERR, "Unknown status: m_s=%d, c_s=%d\n", m_status, c_status);
return sdk_set_errno(ERR_UNKNOWN_STAT);
}
switch(m_status) {
case M_INIT:
*status = WIMAX_API_DEVICE_STATUS_UnInitialized;
break;
case M_OPEN_OFF:
*status = WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW;
break;
case M_OPEN_ON:
*status = WIMAX_API_DEVICE_STATUS_Ready;
break;
case M_SCAN:
*status = WIMAX_API_DEVICE_STATUS_Scanning;
break;
case M_CONNECTING:
*status = WIMAX_API_DEVICE_STATUS_Connecting;
switch(c_status) {
case C_INIT:
*connect_prog_info = WIMAX_API_DEVICE_CONNECTION_PROGRESS_Ranging;
ret = 1;
break;
case C_CONNSTART:
*connect_prog_info = WIMAX_API_DEVICE_CONNECTION_PROGRESS_Ranging;
break;
case C_ASSOCSTART:
*connect_prog_info = WIMAX_API_DEVICE_CONNECTION_PROGRESS_Ranging;
ret = 1;
break;
case C_RNG:
*connect_prog_info = WIMAX_API_DEVICE_CONNECTION_PROGRESS_Ranging;
ret = 1;
break;
case C_SBC:
*connect_prog_info = WIMAX_API_DEVICE_CONNECTION_PROGRESS_SBC;
break;
case C_AUTH:
*connect_prog_info = WIMAX_API_DEVICE_CONNECTION_PROGRESS_EAP_authentication_User;
break;
case C_REG:
*connect_prog_info = WIMAX_API_DEVICE_CONNECTION_PROGRESS_Registration;
break;
case C_DSX:
*connect_prog_info = WIMAX_API_DEVICE_CONNECTION_PROGRESS_Registration_DSX;
break;
case C_ASSOCCOMPLETE:
*connect_prog_info = WIMAX_API_DEVICE_CONNECTION_PROGRESS_Registered;
ret = 1;
break;
case C_CONNCOMPLETE:
*connect_prog_info = WIMAX_API_DEVICE_CONNECTION_PROGRESS_Registered;
break;
default:
ret = -1;
break;
}
break;
case M_CONNECTED:
*status = WIMAX_API_DEVICE_STATUS_Data_Connected;
break;
default:
ret = -1;
break;
}
return ret;
}
int sdk_get_device_status(api_hand_t *api_hand, int dev_idx,
WIMAX_API_DEVICE_STATUS_P status,
WIMAX_API_CONNECTION_PROGRESS_INFO_P connect_prog_info)
{
int m_status, c_status;
int ret;
xfunc_in();
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
ret = sdk_get_status(api_hand->sdk, dev_idx, &m_status, &c_status);
if (!ret) {
ret = sdk_convert_status(dev_idx, status, connect_prog_info, m_status, c_status);
if (ret >= 0)
ret = 0;
}
xfunc_out("ret=%d, m_s=%d, c_s=%d", ret, m_status, c_status);
return ret;
}
static void sdk_hook_writing_hci(int dev_idx, void *buf, int len)
{
hci_t *hci = (hci_t *) buf;
hci_image_payload_t *img;
unsigned short cmd_evt;
cmd_evt = B2H(hci->cmd_evt);
switch (cmd_evt) {
case WIMAX_DL_IMAGE:
img = (hci_image_payload_t *) hci->data;
switch (B2H(img->type)) {
case DLIMG_OMA_XML:
if (DB2H(img->offset) == -1/*EOF*/) {
xprintf(SDK_DBG, "Hooked HCI(%04x)\n", cmd_evt);
wm_sync_subscription(dev_idx);
}
break;
}
break;
}
}
int sdk_write_hci_packet(api_hand_t *api_hand, int dev_idx, void *buf, int len)
{
int ret;
xfunc_in("[%d] len=%d", dev_idx, len);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
ret = io_send(dev_idx, buf, len);
if (ret == len) {
sdk_hook_writing_hci(dev_idx, buf, len);
ret = 0;
}
else
ret = -1;
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_set_power_control(api_hand_t *api_hand, int dev_idx, rf_stat_t rf_stat)
{
//#define NO_CHECK_POWER_CONTROL
sdk_internal_t *sdk = api_hand->sdk;
#if !defined(NO_CHECK_POWER_CONTROL)
rf_stat_t get_rf_stat;
#endif
int ret = -1;
xfunc_in("rf=%s", (rf_stat==rf_on) ? "On" : "Off");
if (sdk_check_handle(api_hand, dev_idx) < 0)
goto out;
if (sdk->ro) {
ret = sdk_set_errno(ERR_PERM);
goto out;
}
#if defined(NO_CHECK_POWER_CONTROL)
ret = wm_set_rf_state(dev_idx, rf_stat, SDK_RF_UPDOWN_RESP_TIMEOUT_SEC);
#else
ret = wm_get_rf_state(dev_idx, &get_rf_stat);
if (!ret && get_rf_stat != rf_stat)
ret = wm_set_rf_state(dev_idx, rf_stat, SDK_RF_UPDOWN_RESP_TIMEOUT_SEC);
#endif
out:
xfunc_out();
return ret;
}
int sdk_get_device_info(api_hand_t *api_hand, int dev_idx,
WIMAX_API_DEVICE_INFO_P dev_info)
{
device_t *dev;
wimax_t *wm;
wm_device_info_t *devi;
wm_rev_info_t *rev;
char str[256];
int ret;
u8 *p, *p2;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (!(dev = dm_get_dev(dev_idx)))
return -1;
wm = dev->wimax;
devi = &wm->dev_info;
rev = &devi->revision;
dev_info->structureSize = sizeof(WIMAX_API_DEVICE_INFO);
dev_info->hwVersion.structureSize = sizeof(WIMAX_API_DEVICE_VERSION);
wcscpy((wchar_t *)dev_info->hwVersion.name, L"GCT H/W");
p = (u8 *) &rev->phy_hw_ver;
ret = sprintf(str, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
mbstowcs((wchar_t *)dev_info->hwVersion.version, str, ret+1);
dev_info->swVersion.structureSize = sizeof(WIMAX_API_DEVICE_VERSION);
wcscpy((wchar_t *)dev_info->swVersion.name, L"GCT S/W");
p = (u8 *) &rev->rel_ver;
p2 = (u8 *) &rev->fw_ver;
ret = sprintf(str, "FW(%d.%d.%d.%d : %d.%d.%d.%d)",
p[0], p[1], p[2], p[3], p2[0], p2[1], p2[2], p2[3]);
mbstowcs((wchar_t *)dev_info->swVersion.version, str, ret+1);
dev_info->rfVersion.structureSize = sizeof(WIMAX_API_DEVICE_VERSION);
wcscpy((wchar_t *)dev_info->rfVersion.name, L"GCT RF");
wcscpy((wchar_t *)dev_info->rfVersion.version, (wchar_t *)dev_info->hwVersion.version);
dev_info->asicVersion.structureSize = sizeof(WIMAX_API_DEVICE_VERSION);
wcscpy((wchar_t *)dev_info->asicVersion.name, L"GCT ASIC");
wcscpy((wchar_t *)dev_info->asicVersion.version, (wchar_t *)dev_info->hwVersion.version);
memcpy(dev_info->macAddress, devi->device_mac, sizeof(devi->device_mac));
mbstowcs((wchar_t*)dev_info->vendorName, (char *)devi->vendor_name,
strlen((char *)devi->vendor_name)+1);
dev_info->vendorSpecificInfoIncl = FALSE;
memset(dev_info->vendorSpecificInfo, 0, sizeof(dev_info->vendorSpecificInfo));
dm_put_dev(dev_idx);
xfunc_out();
return 0;
}
int sdk_get_profile_list(api_hand_t *api_hand, int dev_idx,
WIMAX_API_PROFILE_INFO_P list, int *list_cnt)
{
device_t *dev;
wimax_t *wm;
struct list_head *head;
wm_subscription_info_t *ss_info;
u8 profile_name[MAX_SIZE_OF_STRING_BUFFER];
int cnt = 0;
xfunc_in("dev=%d, list_cnt=%d", dev_idx, *list_cnt);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (!(dev = dm_get_dev(dev_idx)))
return -1;
wm = dev->wimax;
head = &wm->subs_list.head;
xprintf(SDK_DBG, "subs_list.cnt=%d\n", wm->subs_list.cnt);
list_for_each_entry(ss_info, head, list) {
if (cnt >= *list_cnt)
break;
list[cnt].structureSize = sizeof(WIMAX_API_PROFILE_INFO);
list[cnt].profileID = U82U24(ss_info->subscription_id.hnspid.id);
set_msb(list[cnt].profileID, ss_info->idx);
sprintf((char *)profile_name, "%s:%s",
ss_info->subscription_id.user_hnai,
ss_info->subscription_id.hnspid.name);
mbstowcs((wchar_t*)list[cnt].profileName, (char *)profile_name,
strlen((char *)profile_name)+1);
cnt++;
}
*list_cnt = cnt;
xfunc_out("list_cnt=%d", *list_cnt);
dm_put_dev(dev_idx);
return 0;
}
int sdk_set_profile(api_hand_t *api_hand, int dev_idx, u32 profile_id)
{
sdk_internal_t *sdk = api_hand->sdk;
device_t *dev;
u8 nspid[NSP_ID_SIZE];
u8 subs_idx;
int ret = 0;
xfunc_in("dev=%d, profile_id=0x%08x", dev_idx, profile_id);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (sdk->ro)
return sdk_set_errno(ERR_PERM);
if (!(dev = dm_get_dev(dev_idx)))
return -1;
subs_idx = get_msb(profile_id);
U242U8(nspid, profile_id);
if (!(dev->wimax->scan.selected_subs = wm_get_subscription(dev_idx, subs_idx, nspid))) {
ret = -1;
goto out;
}
wm_set_scan_type(dev_idx, wm_scan_curr_subscription);
ret = sdk_set_ioctl_profile_id(dev_idx, profile_id);
out:
dm_put_dev(dev_idx);
xfunc_out();
return ret;
}
int sdk_set_scan_interval(api_hand_t *api_hand, int dev_idx, u32 interval_sec)
{
device_t *dev;
int ret;
xfunc_in("dev=%d, interval=%d", dev_idx, interval_sec);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (!(dev = dm_get_dev(dev_idx)))
return -1;
if (dev->wimax->scan.selected_subs)
wm_set_scan_type(dev_idx, wm_scan_curr_subscription);
else
wm_set_scan_type(dev_idx, wm_scan_all_subscriptions);
ret = wm_active_scan_interval(dev_idx, interval_sec);
dm_put_dev(dev_idx);
xfunc_out();
return ret;
}
static void sdk_init_cr801(wimax_t *wm)
{
wm_eap_param_t *eapp;
eapp = &wm->dev_info.eapp;
if (eapp->cr801_enabled)
eapp->cr801_mode = CR801_TTLS;
else
eapp->cr801_mode = CR801_DISABLE;
xprintf(SDK_DBG, "cr801_mode=%d\n", eapp->cr801_mode);
}
int sdk_set_eap(api_hand_t *api_hand, int dev_idx, GCT_API_EAP_PARAM_P eap)
{
sdk_internal_t *sdk = api_hand->sdk;
device_t *dev;
wm_eap_param_t *eapp;
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (!(dev = dm_get_dev(dev_idx)))
return -1;
eapp = &dev->wimax->dev_info.eapp;
memset(eapp, 0, sizeof(*eapp));
eapp->type = eap->type;
if (eapp->type == GCT_WIMAX_NO_EAP) {
if (!sdk->ro)
ret = wm_set_eap(dev_idx, FALSE);
return ret;
}
assert(GCT_WIMAX_EAP_TLS == W_EAP_TLS);
if (eap && GCT_API_IS_EAP_TLS(eap->type)) {
if (!(eapp->use_nv_info = eap->useNvramParam)) {
strcpy(eapp->userid, (char *) eap->userId);
strcpy(eapp->userid_pwd, (char *) eap->userIdPwd);
strcpy(eapp->anony_id, (char *) eap->anonymousId);
strcpy(eapp->pri_key_pwd, (char *) eap->privateKeyPwd);
}
eapp->frag_size = eap->fragSize;
eapp->use_delimiter = eap->useDelimiter;
eapp->dev_cert_null = eap->devCertNULL;
eapp->ca_cert_null = eap->caCertNULL;
eapp->disable_resumptoin = eap->disableResumption;
eapp->cr801_enabled = eap->cr801Enable;
eapp->disable_sessionticket = eap->disableSessionTicket;
strcpy(eapp->decoration[DECORATION_IDX1], (char *) eap->decoration);
eapp->log_enabled = eap->logEnable;
if (!sdk->ro)
eap_prepare_log_env(dev_idx, eapp->log_enabled);
}
sdk_init_cr801(dev->wimax);
if (!sdk->ro)
ret = wm_set_eap(dev_idx, TRUE);
dm_put_dev(dev_idx);
xfunc_out();
return ret;
}
int sdk_get_statistics(api_hand_t *api_hand, int dev_idx,
WIMAX_API_CONNECTION_STAT_P statistics)
{
wm_net_info_t net_info;
int ret;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
ret = wm_get_netinfo(dev_idx, &net_info);
if (!ret) {
statistics->structureSize = sizeof(WIMAX_API_CONNECTION_STAT);
statistics->totalRxByte = net_info.rx_bytes;
statistics->totalTxByte = net_info.tx_bytes;
statistics->totalRxPackets = net_info.rx_packets;
statistics->totalTxPackets = net_info.tx_packets;
}
xfunc_out();
return ret;
}
int sdk_get_linkstatus(api_hand_t *api_hand, int dev_idx,
WIMAX_API_LINK_STATUS_INFO_P link_status)
{
device_t *dev;
struct wimax_s *wm;
wm_link_status_t link_s;
int ret;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (!(dev = dm_get_dev(dev_idx)))
return -1;
wm = dev->wimax;
ret = wm_get_linkinfo(dev_idx, &link_s);
if (!ret) {
link_status->structureSize = sizeof(WIMAX_API_LINK_STATUS_INFO);
link_status->centerFrequency = link_s.cur_freq;
link_status->RSSI = link_s.rssi;
link_status->CINR = link_s.cinr;
link_status->txPWR = link_s.tx_power;
memcpy(link_status->bsId, wm->conn_comp.net_id.bs.id, BS_ID_SIZE);
}
dm_put_dev(dev_idx);
xfunc_out();
return ret;
}
static int get_connected_nsp(int dev_idx, WIMAX_API_CONNECTED_NSP_INFO_P nsp_info)
{
device_t *dev;
wimax_t *wm;
wm_nsp_t *nsp;
struct list_head *head;
int ret = -1;
xfunc_in("dev=%d", dev_idx);
if (!(dev = dm_get_dev(dev_idx)))
return -1;
wm = dev->wimax;
head = &wm->scan_list.head;
nsp_info->structureSize = sizeof(WIMAX_API_CONNECTED_NSP_INFO);
nsp_info->activated = TRUE;
nsp_info->NSPid = U82U24(wm->conn_comp.net_id.nsp.id);
pthread_mutex_lock(&wm->scan_list.lock);
list_for_each_entry(nsp, head, list) {
if (nsp_info->NSPid == nsp->id) {
mbstowcs((wchar_t *)nsp_info->NSPName, (char *)nsp->name,
strlen((char *)nsp->name)+1);
nsp_info->RSSI = nsp->rssi;
nsp_info->CINR = nsp->cinr;
nsp_info->networkType = nsp->type;
#if defined( NO_IMPLIMENT )
nsp_info->NSPRealm
#else
memset(nsp_info->NSPRealm, 0, sizeof(nsp_info->NSPRealm));
#endif
ret = 0;
break;
}
}
pthread_mutex_unlock(&wm->scan_list.lock);
xfunc_out("ret=%d", ret);
dm_put_dev(dev_idx);
return ret;
}
int sdk_set_ioctl_connected_nsp(sdk_internal_t *sdk, int dev_idx)
{
WIMAX_API_CONNECTED_NSP_INFO nsp_info;
int ret = -1;
xfunc_in("dev=%d, ro=%d", dev_idx, sdk->ro);
if (sdk->ro)
return 0;
if (!(ret = get_connected_nsp(dev_idx, &nsp_info))) {
ret = net_ioctl_set_data(dev_idx, SIOC_DATA_CONNNSP, &nsp_info, sizeof(nsp_info));
if (ret > 0) ret = 0;
}
xfunc_out("ret=%d", ret);
dm_put_dev(dev_idx);
return ret;
}
int sdk_get_ioctl_connected_nsp(int dev_idx, WIMAX_API_CONNECTED_NSP_INFO_P nsp_info)
{
int ret;
xfunc_in("dev=%d", dev_idx);
ret = net_ioctl_get_data(dev_idx, SIOC_DATA_CONNNSP, nsp_info, sizeof(*nsp_info));
if (ret > 0) ret = 0;
xfunc_out("ret=%d", ret);
dm_put_dev(dev_idx);
return ret;
}
int sdk_get_connected_nsp(api_hand_t *api_hand, int dev_idx,
WIMAX_API_CONNECTED_NSP_INFO_P nsp_info)
{
#define GET_CURRENT_LINK
#if defined(GET_CURRENT_LINK)
wm_link_status_t link_s;
#endif
int ret;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (api_hand->sdk->ro)
ret = sdk_get_ioctl_connected_nsp(dev_idx, nsp_info);
else
ret = get_connected_nsp(dev_idx, nsp_info);
#if defined(GET_CURRENT_LINK)
if (!wm_get_linkinfo(dev_idx, &link_s)) {
nsp_info->RSSI = link_s.rssi;
nsp_info->CINR = link_s.cinr;
}
#endif
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_set_ioctl_complete_info(int dev_idx)
{
device_t *dev;
wimax_t *wm;
int ret = -1;
xfunc_in("dev=%d", dev_idx);
if (!(dev = dm_get_dev(dev_idx)))
return -1;
wm = dev->wimax;
ret = net_ioctl_set_data(dev_idx, SIOC_DATA_CONNCOMP,
&wm->conn_comp, sizeof(wm->conn_comp));
if (ret > 0) ret = 0;
dm_put_dev(dev_idx);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_load_ioctl_complete_info(int dev_idx)
{
device_t *dev;
wimax_t *wm;
int ret;
xfunc_in("dev=%d", dev_idx);
if (!(dev = dm_get_dev(dev_idx)))
return -1;
wm = dev->wimax;
ret = net_ioctl_get_data(dev_idx, SIOC_DATA_CONNCOMP,
&wm->conn_comp, sizeof(wm->conn_comp));
if (ret > 0) ret = 0;
dm_put_dev(dev_idx);
xfunc_out("ret=%d", ret);
return ret;
}
static int sdk_set_ioctl_profile_id(int dev_idx, u32 profile_id)
{
int ret = -1;
xfunc_in("dev=%d", dev_idx);
ret = net_ioctl_set_data(dev_idx, SIOC_DATA_PROFILEID,
&profile_id, sizeof(profile_id));
if (ret > 0) ret = 0;
dm_put_dev(dev_idx);
xfunc_out("ret=%d", ret);
return ret;
}
static int sdk_load_ioctl_profile_id(int dev_idx)
{
device_t *dev;
u32 profile_id = 0;
u8 nspid[NSP_ID_SIZE];
u8 subs_idx;
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (!(dev = dm_get_dev(dev_idx)))
return -1;
if (dev->wimax->scan.type != wm_scan_curr_subscription) {
xprintf(SDK_DBG, "Scan type(%d) does not need loading profile_id\n",
dev->wimax->scan.type);
goto out;
}
if ((ret = net_ioctl_get_data(dev_idx, SIOC_DATA_PROFILEID,
&profile_id, sizeof(profile_id))) < 0)
goto out;
ret = 0;
subs_idx = get_msb(profile_id);
U242U8(nspid, profile_id);
if (!(dev->wimax->scan.selected_subs = wm_get_subscription(dev_idx, subs_idx, nspid)))
ret = -1;
out:
dm_put_dev(dev_idx);
xfunc_out("ret=%d, *profile_id=0x%08X", ret, profile_id);
return ret;
}
static int get_network_list(int dev_idx, WIMAX_API_NSP_INFO_P list, u32 *list_cnt)
{
device_t *dev;
wimax_t *wm;
wm_nsp_t *nsp;
struct list_head *head;
int cnt = 0;
xfunc_in("dev=%d, list_cnt=%d", dev_idx, *list_cnt);
if (!(dev = dm_get_dev(dev_idx)))
return -1;
wm = dev->wimax;
head = &wm->scan_list.head;
pthread_mutex_lock(&wm->scan_list.lock);
xprintf(SDK_DBG, "scan_list.cnt=%d\n", wm->scan_list.cnt);
list_for_each_entry(nsp, head, list) {
if (cnt >= *list_cnt)
break;
list[cnt].structureSize = sizeof(WIMAX_API_NSP_INFO);
mbstowcs((wchar_t *)list[cnt].NSPName, (char *)nsp->name,
strlen((char *)nsp->name)+1);
list[cnt].NSPid = nsp->id;
list[cnt].RSSI = nsp->rssi;
list[cnt].CINR = nsp->cinr;
list[cnt].networkType = nsp->type;
cnt++;
}
*list_cnt = cnt;
pthread_mutex_unlock(&wm->scan_list.lock);
xfunc_out("cnt=%d", cnt);
dm_put_dev(dev_idx);
return 0;
}
int sdk_set_ioctl_network_list(sdk_internal_t *sdk, int dev_idx)
{
device_t *dev;
wimax_t *wm;
WIMAX_API_NSP_INFO *nsp_info = NULL;
int ret = 0, cnt, cnt2;
xfunc_in("dev=%d, ro=%d", dev_idx, sdk->ro);
if (sdk->ro)
return 0;
if (!(dev = dm_get_dev(dev_idx)))
return -1;
wm = dev->wimax;
cnt = cnt2 = wm->scan_list.cnt;
if (!cnt)
goto out;
nsp_info = (WIMAX_API_NSP_INFO *) sdk_malloc(sizeof(WIMAX_API_NSP_INFO) * cnt);
assert(nsp_info);
ret = get_network_list(dev_idx, nsp_info, (u32 *)&cnt2);
if (ret < 0)
goto out;
assert(cnt == cnt2);
ret = net_ioctl_set_data(dev_idx, SIOC_DATA_NETLIST,
nsp_info, sizeof(*nsp_info) * cnt);
if (ret > 0) ret = 0;
out:
if (nsp_info)
sdk_free(nsp_info);
xfunc_out("ret=%d", ret);
dm_put_dev(dev_idx);
return ret;
}
int sdk_get_ioctl_network_list(int dev_idx, WIMAX_API_NSP_INFO_P list, u32 *list_cnt)
{
device_t *dev;
int ret;
xfunc_in("dev=%d", dev_idx);
if (!(dev = dm_get_dev(dev_idx)))
return -1;
if ((ret = net_ioctl_get_data(dev_idx, SIOC_DATA_NETLIST,
list, sizeof(*list) * *list_cnt)) > 0) {
assert(ret % sizeof(WIMAX_API_NSP_INFO) == 0);
*list_cnt = ret / sizeof(WIMAX_API_NSP_INFO);
}
xfunc_out("ret=%d", ret);
dm_put_dev(dev_idx);
return ret;
}
int sdk_get_network_list(api_hand_t *api_hand, int dev_idx, WIMAX_API_NSP_INFO_P list,
u32 *list_cnt)
{
int ret;
xfunc_in("dev=%d, list_cnt=%d", dev_idx, *list_cnt);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (api_hand->sdk->ro)
ret = sdk_get_ioctl_network_list(dev_idx, list, list_cnt);
else
ret = get_network_list(dev_idx, list, list_cnt);
xfunc_out("ret=%d, cnt=%d", ret, *list_cnt);
return ret;
}
static bool is_connection_ready(sdk_internal_t *sdk, int dev_idx, char *state)
{
int m_status, c_status;
bool ret = FALSE;
sdk_get_status(sdk, dev_idx, &m_status, &c_status);
switch (m_status) {
case M_INIT:
case M_OPEN_OFF:
strcpy(state, "RF-off");
break;
case M_OPEN_ON:
strcpy(state, "Ready");
ret = TRUE;
break;
case M_SCAN:
strcpy(state, "Scanning");
ret = TRUE;
break;
case M_CONNECTING:
strcpy(state, "Connecting");
break;
case M_CONNECTED:
strcpy(state, "Connected");
break;
default:
strcpy(state, "Unknown");
break;
}
return ret;
}
int sdk_connect_network(api_hand_t *api_hand, int dev_idx, uchar *nsp_name, u32 profile_id)
{
device_t *dev = NULL;
wimax_t *wm;
wm_nsp_t *nsp;
u8 hnspid[NSP_ID_SIZE], vnspid[NSP_ID_SIZE];
u8 srched_nspid[NSP_ID_SIZE];
u8 nspname[WM_MAX_NSP_NAME_LEN];
char conn_state[128];
wm_subscription_info_t *subs;
int ret;
xfunc_in("[%d], nsp=%S, 0x%08x", dev_idx, nsp_name, profile_id);
if ((ret = sdk_check_handle(api_hand, dev_idx)) < 0)
goto out;
if (api_hand->sdk->ro) {
ret = sdk_set_errno(ERR_PERM);
goto out;
}
if (!(dev = dm_get_dev(dev_idx))) {
ret = -1;
goto out;
}
if (!is_connection_ready(api_hand->sdk, dev_idx, conn_state)) {
xprintf(SDK_ERR, "Current state(%s) is not connectable state!!\n", conn_state);
ret = -1;
goto out;
}
wm = dev->wimax;
if (wm->scan.sf_mode) {
u8 nspid[NSP_ID_SIZE];
WIMAX_API_NSP_INFO net_info;
u32 cnt = 1;
if (!get_network_list(dev_idx, &net_info, &cnt)) {
if (cnt == 1) {
U242U8(nspid, net_info.NSPid);
if ((subs = wm_get_subscription(dev_idx, 0, nspid))) {
wm->scan.selected_subs = subs;
xprintf(SDK_INFO, "user_hnai=%s\n",
wm->scan.selected_subs->subscription_id.hnspid.name);
}
}
else
xprintf(SDK_ERR, "get_network_list is %d\n", cnt);
}
}
if (!wm->scan.selected_subs && wm->scan.type != wm_scan_all_channels && !profile_id) {
xprintf(SDK_ERR, "There is no selected subscription\n");
goto out;
}
wcstombs((char *)nspname, (wchar_t *)nsp_name, wcslen((wchar_t *)nsp_name)+1);
xprintf(SDK_DBG, "nspname=%s(%d)\n", nspname, strlen((char *)nspname));
if (wm->scan.type == wm_scan_all_channels)
U242U8(hnspid, WIDE_SCAN_HNSP_ID);
else {
if (profile_id) {
if (!wm->scan.selected_subs) {
u8 subs_idx = get_msb(profile_id);
U242U8(hnspid, profile_id);
wm->scan.selected_subs = wm_get_subscription(dev_idx, subs_idx, hnspid);
}
}
if (!wm->scan.selected_subs) {
xprintf(SDK_ERR, "selected_subs is NULL\n");
ret = -1;
goto out;
}
memcpy(hnspid, wm->scan.selected_subs->subscription_id.hnspid.id, NSP_ID_SIZE);
}
if (profile_id) {
U242U8(srched_nspid, profile_id);
if ((nsp = wm_lookup_nsp_by_id(wm, srched_nspid)) == NULL) {
xprintf(SDK_ERR, "[%d] NSP(%06x) is not found\n",
dev_idx, U82U24(srched_nspid));
ret = sdk_set_errno(ERR_NO_NSPID);
goto out;
}
}
else {
if ((nsp = wm_lookup_nsp_by_name(wm, nspname)) == NULL) {
xprintf(SDK_ERR, "[%d] NSP(%s) is not found\n", dev_idx, nspname);
ret = sdk_set_errno(ERR_NO_NSPID);
goto out;
}
}
U242U8(vnspid, nsp->id);
if (wm->dev_info.eapp.cr801_enabled) {
wm->dev_info.eapp.cr801_server_reject_cnt = 0;
sdk_init_cr801(wm);
if (E_EAP_TLS_ENABLED(dev))
wm_set_eap(dev_idx, TRUE);
}
ret = wm_connect_network(dev_idx, hnspid, vnspid);
out:
xfunc_out("ret=%d", ret);
if (dev)
dm_put_dev(dev_idx);
return ret;
}
int sdk_disconnect_network(api_hand_t *api_hand, int dev_idx)
{
int ret;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (api_hand->sdk->ro)
return sdk_set_errno(ERR_PERM);
ret = wm_disconnect_network(dev_idx, SDK_DISCONN_RESP_TIMEOUT_SEC);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_get_rf_info(api_hand_t *api_hand, int dev_idx, GCT_API_RF_INFORM_P rf_info)
{
int ret;
xfunc_in("dev=%d rf_info=0x%08x", dev_idx, rf_info);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
ret = wm_get_rf_info(dev_idx, rf_info);
dm_put_dev(dev_idx);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_get_bl_ver(api_hand_t *api_hand, int dev_idx, char *buf, int size)
{
device_t *dev;
char str[64];
u8 *ver;
int ret;
xfunc_in("dev=%d size=%d", dev_idx, size);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (!(dev = dm_get_dev(dev_idx)))
return -1;
ver = (u8 *) &dev->wimax->dev_info.revision.bl_ver;
ret = sprintf(str, "%d.%d.%d.%d", ver[0], ver[1], ver[2], ver[3]);
xprintf(SDK_DBG, "%s\n", str);
if (size < ret)
ret = -1;
else {
strcpy(buf, str);
ret = 0;
}
dm_put_dev(dev_idx);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_get_capability(api_hand_t *api_hand, int dev_idx, u32 *cap)
{
device_t *dev;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (!(dev = dm_get_dev(dev_idx)))
return -1;
*cap = dev->capability;
dm_put_dev(dev_idx);
xfunc_out("dev->capability=%d", dev->capability);
return 0;
}
int sdk_set_capability(api_hand_t *api_hand, int dev_idx, u32 cap)
{
device_t *dev;
int ret;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (!(dev = dm_get_dev(dev_idx)))
return -1;
ret = wm_set_capability(dev_idx, cap);
dm_put_dev(dev_idx);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_get_neighbor_list(api_hand_t *api_hand, int dev_idx,
GCT_API_NEIGHBOR_LIST_P list, int *list_cnt)
{
device_t *dev;
wm_bs_neigh_t *neigh = NULL;
int cnt, ret, i;
xfunc_in("dev=%d, list_cnt=%d", dev_idx, *list_cnt);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (!(dev = dm_get_dev(dev_idx)))
return -1;
cnt = *list_cnt;
neigh = (wm_bs_neigh_t *) sdk_malloc(sizeof(wm_bs_neigh_t) * cnt);
assert(neigh);
if (!(ret = wm_get_neighbor_list(dev_idx, neigh, &cnt))) {
for (i = 0; i < cnt; i++) {
list[i].structureSize = sizeof(*list);
memcpy(list[i].bsId, neigh[i].bsid, sizeof(list[i].bsId));
list[i].rssi = neigh[i].rssi;
list[i].cinr = neigh[i].cinr;
list[i].preamble = neigh[i].preamble;
list[i].frequency = neigh[i].frequency;
}
*list_cnt = cnt;
}
else
*list_cnt = 0;
sdk_free(neigh);
dm_put_dev(dev_idx);
xfunc_out("ret=%d, cnt=%d", ret, cnt);
return ret;
}
int sdk_net_search_scan(api_hand_t *api_hand, int dev_idx, GCT_API_SCAN_TYPE type)
{
sdk_internal_t *sdk;
int ret;
xfunc_in("dev=%d, type=%d", dev_idx, type);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
sdk = api_hand->sdk;
if (sdk->ro)
return sdk_set_errno(ERR_PERM);
ret = wm_net_search_scan(dev_idx, type);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_cancel_scan(api_hand_t *api_hand, int dev_idx)
{
int ret;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (api_hand->sdk->ro)
return sdk_set_errno(ERR_PERM);
ret = wm_cancel_scan(dev_idx);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_cmd_mac_state(api_hand_t *api_hand, int dev_idx, GCT_API_CMD_MAC_STATE_TYPE type)
{
int ret;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (api_hand->sdk->ro)
return sdk_set_errno(ERR_PERM);
ret = wm_cmd_mac_state(dev_idx, type);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_set_idle_mode_timeout(api_hand_t *api_hand, int dev_idx, u16 timeoutSec)
{
int ret;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (api_hand->sdk->ro)
return sdk_set_errno(ERR_PERM);
ret = wm_set_idle_mode_timeout(dev_idx, timeoutSec);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_get_phy_mac_basic(api_hand_t *api_hand, int dev_idx, GCT_API_MAC_PHY_MAC_BASIC_P pData)
{
int ret;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
ret = wm_get_phy_mac_basic(dev_idx, pData);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_get_phy_mcs(api_hand_t *api_hand, int dev_idx, GCT_API_MAC_PHY_MCS_P pData)
{
int ret;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
ret = wm_get_phy_mcs(dev_idx, pData);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_get_phy_cinr_rssi(api_hand_t *api_hand, int dev_idx, GCT_API_MAC_PHY_CINR_RSSI_P pData)
{
int ret;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
ret = wm_get_phy_cinr_rssi(dev_idx, pData);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_on_app_event(sdk_internal_t *sdk, int dev_idx, fsm_event_t event)
{
device_t *dev;
wimax_t *wm;
int m_status, c_status;
rf_stat_t rf_stat;
int ret = 0;
int evt_mask = SDK_INFO;
xfunc_in("dev=%d, event=%d", dev_idx, event);
if (!(dev = dm_get_dev(dev_idx)))
return -1;
wm = dev->wimax;
#if 0
if ((ret = dm_get_status(dev_idx, &m_status, &c_status)) < 0) {
ret = -1;
goto out;
}
#else
if ((ret = sdk_get_status(sdk, dev_idx, &m_status, &c_status)) < 0) {
ret = -1;
goto out;
}
#endif
dev->a_status = event;
switch ((int)event) {
case AM_Open:
xprintf(evt_mask, "[%d] %s: m_s=%d, c_s=%d\n",
dev_idx, STR(AM_Open), m_status, c_status);
if (sdk->ro) {
if (m_status == M_CONNECTED)
sdk_load_ioctl_complete_info(dev_idx);
break;
}
if (m_status == M_INIT) {
sdk_set_status(sdk, dev_idx, M_OPEN_OFF, C_INIT);
ret = wm_get_rf_state(dev_idx, &rf_stat);
if (ret < 0)
break;
if (rf_stat == rf_on) {
#if 1
ret = wm_set_rf_state(dev_idx, rf_off, SDK_RF_UPDOWN_RESP_TIMEOUT_SEC);
#else
ret = sdk_on_ind_event(sdk, dev_idx, NM_RadioOn);
#endif
}
}
break;
case AM_Scan:
xprintf(evt_mask, "[%d] %s: m_s=%d, c_s=%d\n",
dev_idx, STR(AM_Scan), m_status, c_status);
if (sdk->ro)
break;
if (m_status == M_OPEN_ON) {
ret = sdk_set_status(sdk, dev_idx, M_SCAN, C_INIT);
wm_set_scan_type(dev_idx, wm_scan_all_channels);
}
break;
case AM_Close:
xprintf(evt_mask, "[%d] %s: m_s=%d, c_s=%d\n",
dev_idx, STR(AM_Close), m_status, c_status);
if (sdk->ro)
break;
sdk_set_status(sdk, dev_idx, M_INIT, C_INIT);
switch (m_status) {
case M_CONNECTING:
case M_CONNECTED:
#if 0
if (dev->inserted)
wm_disconnect_network(dev_idx, SDK_DISCONN_RESP_TIMEOUT_SEC);
#endif
case M_OPEN_ON:
case M_SCAN:
if (dev->inserted) {
sdk_set_status(sdk, dev_idx, M_INIT, C_INIT);
#if 1
wm_set_rf_state(dev_idx, rf_off, 0);
#else
wm_set_rf_state(dev_idx, rf_off, SDK_RF_UPDOWN_RESP_TIMEOUT_SEC);
#endif
}
break;
}
break;
}
out:
dm_put_dev(dev_idx);
xfunc_out("m_s=%d, c_s=%d", m_status, c_status);
return ret;
}
int sdk_on_ind_event(sdk_internal_t *sdk, int dev_idx, fsm_event_t event)
{
device_t *dev;
wimax_t *wm;
int m_status, c_status;
int ret = 0;
int evt_mask = SDK_INFO;
if (!(dev = dm_get_dev(dev_idx)))
return -1;
wm = dev->wimax;
pthread_mutex_lock(&wm->fsm_lock);
sdk_get_status(sdk, dev_idx, &m_status, &c_status);
xfunc_in("dev=%d, event=%d, m_s=%d, c_s=%d", dev_idx, event, m_status, c_status);
switch ((int)event) {
case NM_RadioOn:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NM_RadioOn));
if (m_status == M_OPEN_OFF) {
sdk_set_status(sdk, dev_idx, M_OPEN_ON, C_INIT);
sdk_ind_power_ctrl(sdk, dev_idx, TRUE);
if (!sdk->ro)
ret = wm_req_scan(dev_idx);
}
break;
case NM_RadioOff:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NM_RadioOff));
switch (m_status) {
case M_OPEN_ON:
case M_SCAN:
case M_CONNECTING:
case M_CONNECTED:
sdk_set_status(sdk, dev_idx, M_OPEN_OFF, C_INIT);
sdk_ind_power_ctrl(sdk, dev_idx, FALSE);
if (!sdk->ro)
wm_clean_scan_info(dev_idx);
break;
}
break;
case NM_ScanComplete:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NM_ScanComplete));
if (!sdk->ro) {
if (m_status != M_CONNECTING) {
#if defined(CONFIG_ENABLE_BW_SWITCHING_FOR_KT)
nds_update_switching_bw(dev_idx);
#endif
sdk_set_ioctl_network_list(sdk, dev_idx);
if ((ret = sdk_set_status(sdk, dev_idx, M_OPEN_ON, C_INIT)) < 0)
break;
if ((ret = wm_req_interval_scan(dev_idx, 0)) < 0)
break;
if (wm->scan.type == wm_scan_all_channels)
ret = sdk_ind_net_search_wscan(sdk, dev_idx);
}
}
break;
case NC_ConnectStart:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_ConnectStart));
if (sdk->ro)
sdk_load_ioctl_profile_id(dev_idx);
break;
case NC_ConnectComplete:
xprintf(evt_mask, "[%d] %s(%d)\n", dev_idx, STR(NC_ConnectComplete), c_status);
if (c_status == C_ASSOCCOMPLETE) {
if (!sdk->ro) {
sdk_set_ioctl_connected_nsp(sdk, dev_idx);
sdk_set_ioctl_complete_info(dev_idx);
sdk_set_status(sdk, dev_idx, M_CONNECTED, C_CONNCOMPLETE);
}
sdk_ind_connect_net(sdk, dev_idx, TRUE);
}
else if (!sdk->ro)
wm_req_interval_scan(dev_idx, 100);
break;
case NC_ConnectFail:
xprintf(evt_mask, "[%d] %s(%d)\n", dev_idx, STR(NC_ConnectFail), c_status);
if (c_status == C_CONNSTART || c_status == C_ASSOCCOMPLETE) {
if (!sdk->ro && wm->dev_info.eapp.cr801_enabled) {
pthread_mutex_unlock(&wm->fsm_lock);
if (!wm_cr801_re_connect(dev_idx))
goto out_no_unlock;
}
sdk_set_status(sdk, dev_idx, M_OPEN_ON, C_INIT);
sdk_ind_connect_net(sdk, dev_idx, FALSE);
if (!sdk->ro) {
wm_req_interval_scan(dev_idx, 100);
}
}
break;
case NC_Disconnect:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_Disconnect));
if (m_status == M_CONNECTED) {
if (!sdk->ro) {
sdk_ind_disconnect_net(sdk, dev_idx, TRUE);
/*We should change the state after calling indication.*/
sdk_set_status(sdk, dev_idx, M_OPEN_ON, C_INIT);
wm_req_interval_scan(dev_idx, 100);
}
else
sdk_ind_disconnect_net(sdk, dev_idx, TRUE);
}
case NC_AssocStart:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_AssocStart));
if (c_status == C_CONNSTART || c_status == C_ASSOCCOMPLETE)
sdk_set_status(sdk, dev_idx, m_status, C_ASSOCSTART);
break;
case NC_AssocSuccess:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_AssocSuccess));
if (c_status == C_REG || c_status == C_DSX)
sdk_set_status(sdk, dev_idx, m_status, C_ASSOCCOMPLETE);
break;
case NC_AssocFail:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_AssocFail));
switch (c_status) {
case C_ASSOCSTART:
case C_RNG:
case C_SBC:
case C_AUTH:
case C_REG:
case C_DSX:
sdk_set_status(sdk, dev_idx, m_status, C_ASSOCCOMPLETE);
break;
}
break;
case NC_RangingStart:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_RangingStart));
if (c_status == C_ASSOCSTART)
sdk_set_status(sdk, dev_idx, m_status, C_RNG);
break;
case NC_RangingComplete:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_RangingComplete));
break;
case NC_SbcStart:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_SbcStart));
if (c_status == C_RNG)
sdk_set_status(sdk, dev_idx, m_status, C_SBC);
break;
case NC_SbcComplete:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_SbcComplete));
break;
case NC_AuthStart:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_AuthStart));
if (c_status == C_RNG || c_status == C_SBC)
sdk_set_status(sdk, dev_idx, m_status, C_AUTH);
break;
case NC_AuthComplete:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_AuthComplete));
if (E_EAP_TLS_ENABLED(dev) && wm->dev_info.eapp.log_enabled)
eap_start_e_eaplog_thread(dev_idx);
break;
case NC_RegStart:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_RegStart));
if (c_status == C_RNG || c_status == C_SBC || c_status == C_AUTH)
sdk_set_status(sdk, dev_idx, m_status, C_REG);
break;
case NC_RegComplete:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_RegComplete));
break;
case NC_DsxStart:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_DsxStart));
if (c_status == C_REG)
sdk_set_status(sdk, dev_idx, m_status, C_DSX);
break;
case NC_DsxComplete:
xprintf(evt_mask, "[%d] %s\n", dev_idx, STR(NC_DsxComplete));
break;
}
pthread_mutex_unlock(&wm->fsm_lock);
out_no_unlock:
dm_put_dev(dev_idx);
xfunc_out();
return ret;
}
int sdk_ind_event(int dev_idx, fsm_event_t event)
{
struct list_head *head = hand_get_api_handle_list();
api_hand_t *handle;
pthread_mutex_lock(&api_handle_lock);
list_for_each_entry(handle, head, list) {
if (handle->sdk && handle->sdk->dev_open[dev_idx] && dm_tst_dev(dev_idx))
sdk_on_ind_event(handle->sdk, dev_idx, event);
}
pthread_mutex_unlock(&api_handle_lock);
return 0;
}
#if defined(CONFIG_ENABLE_SERVICE_FLOW)
int sdk_sf_BeginSFRead(api_hand_t *api_hand, int dev_idx)
{
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
BeginSFRead(dev_idx);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_sf_EndSFRead(api_hand_t *api_hand, int dev_idx)
{
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
EndSFRead(dev_idx);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_sf_GetNextSF(api_hand_t *api_hand, int dev_idx,
WIMAX_SERVICE_FLOW *pSF,
UINT8 Direction,
WIMAX_SERVICE_FLOW **ppRetSF)
{
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
*ppRetSF = GetNextSF(dev_idx, pSF, Direction);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_sf_GetServiceFlow(api_hand_t *api_hand, int dev_idx,
UINT32 SFID,
WIMAX_SERVICE_FLOW **ppRetSF)
{
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
*ppRetSF = GetServiceFlow(dev_idx, SFID);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_sf_GetNextClfrRule(api_hand_t *api_hand, int dev_idx,
WIMAX_SERVICE_FLOW *pSF,
WIMAX_CLFR_RULE *pCLFRRule,
WIMAX_CLFR_RULE **ppRetCLFRRule)
{
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
*ppRetCLFRRule = GetNextClfrRule(pSF, pCLFRRule);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_sf_GetClfrRule(api_hand_t *api_hand, int dev_idx,
WIMAX_SERVICE_FLOW *pSF,
UINT16 PacketClassfierRuleIndex,
WIMAX_CLFR_RULE **ppRetCLFRRule)
{
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
*ppRetCLFRRule = GetClfrRule(pSF, PacketClassfierRuleIndex);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_sf_GetNextPHSRule(api_hand_t *api_hand, int dev_idx,
WIMAX_SERVICE_FLOW *pSF,
WIMAX_PHS_RULE *pPHSRule,
WIMAX_PHS_RULE **ppRetPHSRule)
{
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
*ppRetPHSRule = GetNextPHSRule(pSF, pPHSRule);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_sf_GetPHSRule(api_hand_t *api_hand, int dev_idx,
WIMAX_SERVICE_FLOW *pSF,
UINT8 PHSI,
WIMAX_PHS_RULE **ppRetPHSRule)
{
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
*ppRetPHSRule = GetPHSRule(pSF, PHSI);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_sf_CmdAddSF(api_hand_t *api_hand, int dev_idx,
WIMAX_SF_PARAM_P pSFParam,
WIMAX_CLFR_RULE_P pClfrRule,
WIMAX_PHS_RULE_P pPHSRule)
{
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (WIMAX_SF_SUCCESS != CmdAddSF(dev_idx, pSFParam, pClfrRule, pPHSRule)) {
ret = -1;
}
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_sf_CmdChangeSF(api_hand_t *api_hand, int dev_idx,
WIMAX_SF_PARAM_P pSFParam,
WIMAX_CLFR_DSC_ACTION CLFRDSCAction,
WIMAX_CLFR_RULE_P pClfrRule,
WIMAX_PHS_DSC_ACTION PHSDSCAction,
WIMAX_PHS_RULE_P pPHSRule)
{
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (WIMAX_SF_SUCCESS != CmdChangeSF(dev_idx, pSFParam, CLFRDSCAction, pClfrRule, PHSDSCAction, pPHSRule)) {
ret = -1;
}
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_sf_CmdDeleteSF(api_hand_t *api_hand, int dev_idx,
WIMAX_SF_PARAM_P pSFParam)
{
int ret = 0;
xfunc_in("dev=%d", dev_idx);
if (sdk_check_handle(api_hand, dev_idx) < 0)
return -1;
if (WIMAX_SF_SUCCESS != CmdDeleteSF(dev_idx, pSFParam)) {
ret = -1;
}
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_sf_recv_dsx_complete(int dev_idx, u8 *buf, int len)
{
struct hci *hci = (struct hci *)buf;
int ret = 0;
xfunc_in("dev=%d", dev_idx);
hci->cmd_evt = ntohs(hci->cmd_evt);
hci->length = ntohs(hci->length);
dev_update_service_flow(dev_idx, hci);
xfunc_out("ret=%d", ret);
return ret;
}
#endif // CONFIG_ENABLE_SERVICE_FLOW
int sdk_ind_recv_hci_pkt(int dev_idx, char *buf, int len)
{
struct list_head *head = hand_get_api_handle_list();
api_hand_t *handle;
xfunc_in("dev=%d, len=%d", dev_idx, len);
pthread_mutex_lock(&api_handle_lock);
list_for_each_entry(handle, head, list) {
if (handle->sdk->dev_open[dev_idx] && handle->sdk->ind.recv_hci
&& dm_tst_dev(dev_idx)) {
ind_msg_t *msg = (ind_msg_t *) sdk_malloc(sizeof(ind_msg_t));
msg->dev_idx = dev_idx;
msg->u.recv_hci.buf = sdk_malloc(len+1/*null char*/);
memcpy(msg->u.recv_hci.buf, buf, len);
#if 0
msg->u.recv_hci.buf[len] = 0; /*set null char*/
#endif
msg->u.recv_hci.len = len;
msg_send(&handle->sdk->ind.msg_cb, ind_recv_hci, msg);
}
}
pthread_mutex_unlock(&api_handle_lock);
xfunc_out();
return 0;
}
int sdk_ind_dev_insert_remove(int dev_idx, bool is_insert)
{
struct list_head *head = hand_get_api_handle_list();
api_hand_t *handle;
xfunc_in("dev=%d, %s", dev_idx, is_insert ? "insert" : "remove");
pthread_mutex_lock(&api_handle_lock);
list_for_each_entry(handle, head, list) {
if (handle->sdk->ind.insert_remove) {
ind_msg_t *msg;
msg = (ind_msg_t *) sdk_malloc(sizeof(ind_msg_t));
msg->dev_idx = dev_idx;
msg->u.insert_remove.presence = is_insert;
msg_send(&handle->sdk->ind.msg_cb, ind_insert_remove, msg);
}
}
pthread_mutex_unlock(&api_handle_lock);
xfunc_out();
return 0;
}
int sdk_ind_status_update(int dev_idx, u8 *buf, int len)
{
device_t *dev;
struct list_head *head = hand_get_api_handle_list();
api_hand_t *handle;
WIMAX_API_DEVICE_STATUS status;
WIMAX_API_STATUS_REASON reason = WIMAX_API_STATUS_REASON_Normal;
WIMAX_API_CONNECTION_PROGRESS_INFO conn_prog = 0;
int m_status, c_status;
int ret = 0;
if (len < (int) sizeof(int)*2) {
xprintf(SDK_ERR, "[%d] HCI length < %d\n", dev_idx, sizeof(int)*2);
return sdk_set_errno(ERR_HCI);
}
if (!(dev = dm_get_dev(dev_idx)))
return -1;
memcpy(&m_status, buf, sizeof(int));
memcpy(&c_status, &buf[sizeof(int)], sizeof(int));
xfunc_in("dev=%d, m_s=%d, c_s=%d", dev_idx, m_status, c_status);
if (dev->a_status == AM_Close) {
xprintf(SDK_DBG, "APP is in cloasing.\n");
goto out;
}
ret = sdk_convert_status(dev_idx, &status, &conn_prog, m_status, c_status);
if (!ret) {
pthread_mutex_lock(&api_handle_lock);
list_for_each_entry(handle, head, list) {
if (handle->sdk->dev_open[dev_idx] && handle->sdk->ind.stat_update
&& dm_tst_dev(dev_idx)) {
ind_msg_t *msg;
msg = (ind_msg_t *) sdk_malloc(sizeof(ind_msg_t));
msg->dev_idx = dev_idx;
msg->u.stat_update.device_status = status;
msg->u.stat_update.status_reason = reason;
msg->u.stat_update.progress_info = conn_prog;
msg_send(&handle->sdk->ind.msg_cb, ind_stat_update, msg);
}
}
pthread_mutex_unlock(&api_handle_lock);
}
out:
dm_put_dev(dev_idx);
xfunc_out();
return ret;
}
int sdk_ind_if_updown(int dev_idx, u8 *buf, int len)
{
sdk_internal_t *sdk = sdk_get_rw_handle();
device_t *dev;
bool if_updown;
int m_status, c_status;
int ret = 0;
xfunc_in("dev=%d, buf[0]=%d\n", dev_idx, *buf);
if (len < sizeof(if_updown)) {
xprintf(SDK_ERR, "[%d] HCI length < %d\n", dev_idx, sizeof(if_updown));
return sdk_set_errno(ERR_HCI);
}
if (!(dev = dm_get_dev(dev_idx)))
return -1;
if_updown = *buf;
sdk_get_status(sdk, dev_idx, &m_status, &c_status);
xprintf(SDK_INFO, "dev inserted=%d, if=%s, m_status=%d\n",
dev->inserted, if_updown==WIMAX_IF_UP ? "up" : "down", m_status);
if (dev->inserted && m_status == M_CONNECTED && if_updown == WIMAX_IF_DOWN) {
net_updown(dev_idx, TRUE);
xprintf(SDK_INFO, "Re-up network interface(%s)\n", dev->name);
}
dm_put_dev(dev_idx);
xfunc_out("ret=%d", ret);
return ret;
}
int sdk_ind_power_ctrl(sdk_internal_t *sdk, int dev_idx, bool on)
{
WIMAX_API_RF_STATE rf_state;
int ret = 0;
xfunc_in("dev=%d, power=%s", dev_idx, on ? "On" : "Off");
if (on)
rf_state = WIMAX_API_RF_ON;
else
rf_state = WIMAX_API_RF_OFF;
if (sdk->dev_open[dev_idx] && sdk->ind.pow_mng && dm_tst_dev(dev_idx)) {
ind_msg_t *msg = (ind_msg_t *) sdk_malloc(sizeof(ind_msg_t));
msg->dev_idx = dev_idx;
msg->u.pow_mng.state = rf_state;
msg_send(&sdk->ind.msg_cb, ind_pow_mng, msg);
}
xfunc_out();
return ret;
}
int sdk_ind_connect_net(sdk_internal_t *sdk, int dev_idx, bool success)
{
WIMAX_API_NETWORK_CONNECTION_RESP conn_status;
int ret = 0;
xfunc_in("dev=%d, connected=%d", dev_idx, success);
if (success)
conn_status = WIMAX_API_CONNECTION_SUCCESS;
else
conn_status = WIMAX_API_CONNECTION_FAILURE;
if (sdk->dev_open[dev_idx] && sdk->ind.connect_net && dm_tst_dev(dev_idx)) {
ind_msg_t *msg = (ind_msg_t *) sdk_malloc(sizeof(ind_msg_t));
msg->dev_idx = dev_idx;
msg->u.connect_net.response = conn_status;
msg_send(&sdk->ind.msg_cb, ind_connect_net, msg);
}
xfunc_out();
return ret;
}
int sdk_ind_disconnect_net(sdk_internal_t *sdk, int dev_idx, bool success)
{
WIMAX_API_NETWORK_CONNECTION_RESP conn_status;
int ret = 0;
xfunc_in("dev=%d, connected=%d", dev_idx, success);
if (success)
conn_status = WIMAX_API_CONNECTION_SUCCESS;
else
conn_status = WIMAX_API_CONNECTION_FAILURE;
if (sdk->dev_open[dev_idx] && sdk->ind.disconnect_net && dm_tst_dev(dev_idx)) {
ind_msg_t *msg = (ind_msg_t *) sdk_malloc(sizeof(ind_msg_t));
msg->dev_idx = dev_idx;
msg->u.disconnect_net.response = conn_status;
msg_send(&sdk->ind.msg_cb, ind_disconnect_net, msg);
}
xfunc_out();
return ret;
}
int sdk_ind_net_search_wscan(sdk_internal_t *sdk, int dev_idx)
{
device_t *dev;
wimax_t *wm;
WIMAX_API_NSP_INFO_P nsp_list;
int ret = 0;
u32 nsp_cnt;
xfunc_in("dev=%d", dev_idx);
if (!(dev = dm_get_dev(dev_idx)))
return -1;
wm = dev->wimax;
nsp_cnt = wm->scan_list.cnt;
nsp_list = (WIMAX_API_NSP_INFO_P) sdk_malloc(sizeof(WIMAX_API_NSP_INFO)*nsp_cnt);
if ((ret = get_network_list(dev_idx, nsp_list, &nsp_cnt)) < 0)
goto out;
if (sdk->dev_open[dev_idx] && sdk->ind.net_search_wscan && dm_tst_dev(dev_idx)) {
ind_msg_t *msg = (ind_msg_t *) sdk_malloc(sizeof(ind_msg_t));
msg->dev_idx = dev_idx;
msg->u.net_search_wscan.nsp_list = nsp_list;
msg->u.net_search_wscan.list_cnt = nsp_cnt;
msg_send(&sdk->ind.msg_cb, ind_net_search_wscan, msg);
}
out:
xfunc_out();
return ret;
}
int sdk_ind_rf_state(int dev_idx, u8 *buf, int len)
{
rf_stat_t rf_stat = buf[0];
fsm_event_t event;
xfunc_in("dev=%d, rf=%s", dev_idx, rf_stat==rf_on ? "On" : "Off");
event = (rf_stat==rf_on) ? NM_RadioOn : NM_RadioOff;
sdk_ind_event(dev_idx, event);
xfunc_out();
return 0;
}
int sdk_ind_provisioning_op(int dev_idx, WIMAX_API_PROV_OPERATION operation,
WIMAX_API_CONTACT_TYPE contact_type)
{
struct list_head *head = hand_get_api_handle_list();
api_hand_t *handle;
xfunc_in("dev=%d, %d, %d", dev_idx, operation, contact_type);
pthread_mutex_lock(&api_handle_lock);
list_for_each_entry(handle, head, list) {
if (handle->sdk->ind.provisioning) {
ind_msg_t *msg;
msg = (ind_msg_t *) sdk_malloc(sizeof(ind_msg_t));
msg->dev_idx = dev_idx;
msg->u.provisioning.operation = operation;
msg->u.provisioning.contact_type = contact_type;
msg_send(&handle->sdk->ind.msg_cb, ind_provisioning, msg);
}
}
pthread_mutex_unlock(&api_handle_lock);
xfunc_out();
return 0;
}
static void sdk_chk_cr801(int dev_idx, GCT_API_NOTI_CATEGORY category,
GCT_API_NOTI_TYPE type, char *buf, int len)
{
device_t *dev;
short code;
if (!(dev = dm_get_dev(dev_idx)))
return;
xfunc_in("dev=%d, category=%d, type=%d", dev_idx, category, type);
assert(dev->wimax->dev_info.eapp.cr801_enabled);
if (category == GCT_API_ERROR_NOTI_EAP && type == GCT_API_NOTI_TYPE_CODE) {
memcpy(&code, buf, sizeof(code));
code = B2H(code);
if (code == E_WM_CR801_EAP_FAILURE) {
dev->wimax->dev_info.eapp.cr801_server_reject_cnt++;
xprintf(SDK_DBG, "cr801_server_reject_cnt=%d\n",
dev->wimax->dev_info.eapp.cr801_server_reject_cnt);
}
dm_put_dev(dev);
}
xfunc_out();
}
int sdk_ind_noti(int dev_idx, GCT_API_NOTI_CATEGORY category,
GCT_API_NOTI_TYPE type, char *buf, int len)
{
device_t *dev;
struct list_head *head = hand_get_api_handle_list();
api_hand_t *handle;
int ret = 0;
xfunc_in("dev=%d, %d, %d", dev_idx, category, type);
if (!(dev = dm_get_dev(dev_idx)))
return -1;
if (E_EAP_TLS_ENABLED(dev)) {
if (dev->wimax->dev_info.eapp.cr801_enabled) {
xprintf(SDK_DBG, "cr801_enabled=%d\n", dev->wimax->dev_info.eapp.cr801_enabled);
sdk_chk_cr801(dev_idx, category, type, buf, len);
}
}
pthread_mutex_lock(&api_handle_lock);
list_for_each_entry(handle, head, list) {
if (handle->sdk->ind.notification) {
ind_msg_t *msg;
msg = (ind_msg_t *) sdk_malloc(sizeof(ind_msg_t));
msg->dev_idx = dev_idx;
msg->u.notification.category = category;
msg->u.notification.type = type;
if (len > sizeof(msg->u.notification.buf)) {
xprintf(SDK_ERR, "Notification buffer is too small(%d > %d).",
len, sizeof(msg->u.notification.buf));
ret = -1;
break;
}
assert(len < sizeof(msg->u.notification.buf));
memcpy(msg->u.notification.buf, buf, len);
msg->u.notification.buf[len] = 0;
msg->u.notification.buf_len = len;
msg_send(&handle->sdk->ind.msg_cb, ind_notification, msg);
}
}
pthread_mutex_unlock(&api_handle_lock);
xfunc_out();
dm_put_dev(dev);
return ret;
}
static GCT_API_POWER_MODE convert_hci_power_mode(u8 mode)
{
GCT_API_POWER_MODE m;
switch (mode) {
case MODE_W_AWAKE:
m = WiMAXPowerModeNormal;
break;
case MODE_W_IDLE:
m = WiMAXPowerModeIdle;
break;
case MODE_W_SLEEP:
m = WiMAXPowerModeSleep;
break;
default:
m = WiMAXPowerModeMaximum;
break;
}
return m;
}
int sdk_ind_power_mode_change(int dev_idx, u8 *buf, int len)
{
struct list_head *head = hand_get_api_handle_list();
api_hand_t *handle;
hci_mode_change_t *hci = (hci_mode_change_t *) buf;
xfunc_in("dev=%d", dev_idx);
xprintf(SDK_INFO, "status=%d, power_state=%d\n",
U82U24(hci->status), convert_hci_power_mode(hci->power_state));
pthread_mutex_lock(&api_handle_lock);
list_for_each_entry(handle, head, list) {
if (handle->sdk->ind.power_mode) {
ind_msg_t *msg;
msg = (ind_msg_t *) sdk_malloc(sizeof(ind_msg_t));
msg->dev_idx = dev_idx;
msg->u.power_mode.status = U82U24(hci->status);
msg->u.power_mode.power_mode = convert_hci_power_mode(hci->power_state);
msg_send(&handle->sdk->ind.msg_cb, ind_mode_change, msg);
}
}
pthread_mutex_unlock(&api_handle_lock);
xfunc_out();
return 0;
}
int sdk_reg_ind(const char *name, void_func_t *reg, void_func_t callback)
{
if (*reg && callback) {
xprintf(SDK_ERR, "%s(0x%08X-0x%08X) was registered already\n", name, *reg, callback);
return -ERR_ALREADY;
}
else if (!*reg && !callback) {
xprintf(SDK_ERR, "%s(NULL) was removed already\n", name);
return -ERR_ALREADY;
}
*reg = callback;
return 0;
}
int sdk_reg_recv_hci_packet(api_hand_t *api_hand, SDKIndRcvHCIPacket callback)
{
void_func_t *reg = (void_func_t *) &api_hand->sdk->ind.recv_hci;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
assert(api_hand->sdk != NULL && api_hand->sdk->struct_size == sizeof(sdk_internal_t));
return sdk_reg_ind(STR(SDKIndRcvHCIPacket), reg, (void_func_t) callback);
}
int sdk_reg_dev_insert_remove(api_hand_t *api_hand, SDKIndDeviceInsertRemove callback)
{
void_func_t *reg = (void_func_t *) &api_hand->sdk->ind.insert_remove;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
assert(api_hand->sdk != NULL && api_hand->sdk->struct_size == sizeof(sdk_internal_t));
return sdk_reg_ind(STR(SDKIndDeviceInsertRemove), reg, (void_func_t) callback);
}
int sdk_reg_ctrl_power_mng(api_hand_t *api_hand, SDKIndControlPowerManagement callback)
{
void_func_t *reg = (void_func_t *) &api_hand->sdk->ind.pow_mng;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
assert(api_hand->sdk != NULL && api_hand->sdk->struct_size == sizeof(sdk_internal_t));
return sdk_reg_ind(STR(SDKIndControlPowerManagement), reg, (void_func_t) callback);
}
int sdk_reg_dev_stat_update(api_hand_t *api_hand, SDKIndDeviceStatusUpdate callback)
{
void_func_t *reg = (void_func_t *) &api_hand->sdk->ind.stat_update;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
assert(api_hand->sdk != NULL && api_hand->sdk->struct_size == sizeof(sdk_internal_t));
return sdk_reg_ind(STR(SDKIndDeviceStatusUpdate), reg, (void_func_t) callback);
}
int sdk_reg_connect_network(api_hand_t *api_hand, SDKIndConnectToNetwork callback)
{
void_func_t *reg = (void_func_t *) &api_hand->sdk->ind.connect_net;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
assert(api_hand->sdk != NULL && api_hand->sdk->struct_size == sizeof(sdk_internal_t));
return sdk_reg_ind(STR(SDKIndConnectToNetwork), reg, (void_func_t) callback);
}
int sdk_reg_disconnect_network(api_hand_t *api_hand,
SDKIndDisconnectFromNetwork callback)
{
void_func_t *reg = (void_func_t *) &api_hand->sdk->ind.disconnect_net;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
assert(api_hand->sdk != NULL && api_hand->sdk->struct_size == sizeof(sdk_internal_t));
return sdk_reg_ind(STR(SDKIndDisconnectFromNetwork), reg, (void_func_t) callback);
}
int sdk_reg_network_search_wscn(api_hand_t *api_hand,
SDKIndNetworkSearchWideScan callback)
{
void_func_t *reg = (void_func_t *) &api_hand->sdk->ind.net_search_wscan;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
assert(api_hand->sdk != NULL && api_hand->sdk->struct_size == sizeof(sdk_internal_t));
return sdk_reg_ind(STR(SDKIndNetworkSearchWideScan), reg, (void_func_t) callback);
}
int sdk_reg_provisioning_op(api_hand_t *api_hand, SDKIndProvisioningOperation callback)
{
void_func_t *reg = (void_func_t *) &api_hand->sdk->ind.provisioning;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
assert(api_hand->sdk != NULL && api_hand->sdk->struct_size == sizeof(sdk_internal_t));
return sdk_reg_ind(STR(SDKIndProvisioningOperation), reg, (void_func_t) callback);
}
int sdk_reg_package_update(api_hand_t *api_hand, SDKIndPackageUpdate callback)
{
void_func_t *reg = (void_func_t *) &api_hand->sdk->ind.package_update;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
assert(api_hand->sdk != NULL && api_hand->sdk->struct_size == sizeof(sdk_internal_t));
return sdk_reg_ind(STR(SDKIndPackageUpdate), reg, (void_func_t) callback);
}
int sdk_reg_notification(api_hand_t *api_hand, SDKIndNotification callback)
{
void_func_t *reg = (void_func_t *) &api_hand->sdk->ind.notification;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
assert(api_hand->sdk != NULL && api_hand->sdk->struct_size == sizeof(sdk_internal_t));
return sdk_reg_ind(STR(SDKIndNotification), reg, (void_func_t) callback);
}
int sdk_reg_mode_change(api_hand_t *api_hand, SDKIndModeChange callback)
{
void_func_t *reg = (void_func_t *) &api_hand->sdk->ind.power_mode;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
assert(api_hand->sdk != NULL && api_hand->sdk->struct_size == sizeof(sdk_internal_t));
return sdk_reg_ind(STR(SDKIndModeChange), reg, (void_func_t) callback);
}
#if defined(CONFIG_ENABLE_SERVICE_FLOW)
int sdk_reg_noti_service_flow(api_hand_t *api_hand,
SDKIndNotiServiceFlow callback)
{
void_func_t *reg = (void_func_t *) &api_hand->sdk->ind.noti_service_flow;
if (sdk_check_handle(api_hand, NO_DEV) < 0)
return -1;
assert(api_hand->sdk != NULL && api_hand->sdk->struct_size == sizeof(sdk_internal_t));
return sdk_reg_ind(STR(SDKIndNotiServiceFlow), reg, (void_func_t) callback);
}
#endif // CONFIG_ENABLE_SERVICE_FLOW
int sdk_read_file(const char *file, void *buf, int size)
{
char *pbuf = (char *) buf;
int fd, len, total = 0;
if ((fd = open(file, O_RDONLY)) < 0) {
xprintf(SDK_STD_ERR, "open(%s) failed\n", file);
return -1;
}
while ((len = read(fd, &pbuf[total], size-total)) > 0) {
total += len;
if (size-total == 0)
break;
}
if (len < 0)
xprintf(SDK_STD_ERR,"read(%s) failed. ret=%d\n", file, len);
close(fd);
return total;
}
int sdk_write_file(const char *file, void *buf, int size, int flags)
{
char *pbuf = (char *) buf;
int fd, len = 0, total = 0;
mode_t mode = 0;
if (flags & O_CREAT)
mode = 0644;
if ((fd = open(file, flags, mode)) < 0) {
xprintf(SDK_STD_ERR, "open(%s) failed\n", file);
return -1;
}
if (size) {
while ((len = write(fd, &pbuf[total], size-total)) > 0) {
total += len;
if (size-total == 0)
break;
}
}
if (len < 0)
xprintf(SDK_STD_ERR, "write(%s) failed, ret=%d\n", file, len);
close(fd);
return total;
}