/** @file mlan_uap_ioctl.c * * @brief This file contains the handling of AP mode ioctls * * Copyright (C) 2009-2011, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which * is available by writing to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE * ARE EXPRESSLY DISCLAIMED. The License provides additional details about * this warranty disclaimer. */ /******************************************************** Change log: 02/05/2009: initial version ********************************************************/ #include "mlan.h" #include "mlan_util.h" #include "mlan_fw.h" #ifdef STA_SUPPORT #include "mlan_join.h" #endif #include "mlan_main.h" #include "mlan_uap.h" #include "mlan_sdio.h" #include "mlan_11n.h" #include "mlan_fw.h" #include "mlan_11h.h" /******************************************************** Global Variables ********************************************************/ extern t_u8 tos_to_tid_inv[]; /******************************************************** Local Functions ********************************************************/ /** * @brief Stop BSS * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_bss_ioctl_stop(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; ENTER(); ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_STOP, HostCmd_ACT_GEN_SET, 0, (t_void *) pioctl_req, MNULL); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Callback to finish BSS IOCTL START * Not to be called directly to initiate bss_start * * @param priv A pointer to mlan_private structure (cast from t_void*) * * @return MLAN_STATUS_PENDING --success, otherwise fail * @sa wlan_uap_bss_ioctl_start */ static mlan_status wlan_uap_callback_bss_ioctl_start(IN t_void * priv) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = (mlan_private *) priv; mlan_callbacks *pcb = (mlan_callbacks *) & pmpriv->adapter->callbacks; wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb; t_u8 old_channel; ENTER(); /* clear callback now that we're here */ puap_state_chan_cb->get_chan_callback = MNULL; /* * Check if the region and channel requires we check for radar. */ if ((puap_state_chan_cb->band_config & BAND_CONFIG_5GHZ) && wlan_11h_radar_detect_required(pmpriv, puap_state_chan_cb->channel)) { /* first check if channel is under NOP */ if (wlan_11h_is_channel_under_nop(pmpriv->adapter, puap_state_chan_cb->channel)) { /* recently we've seen radar on this channel */ ret = MLAN_STATUS_FAILURE; } /* Check cached radar check on the channel */ if (ret == MLAN_STATUS_SUCCESS) ret = wlan_11h_check_chan_report(pmpriv, puap_state_chan_cb->channel); /* Found radar: try to switch to a non-dfs channel */ if (ret != MLAN_STATUS_SUCCESS) { old_channel = puap_state_chan_cb->channel; ret = wlan_11h_switch_non_dfs_chan(pmpriv, &puap_state_chan_cb->channel); if (ret == MLAN_STATUS_SUCCESS) { ret = wlan_uap_set_channel(pmpriv, pmpriv->uap_state_chan_cb. band_config, puap_state_chan_cb->channel); if (ret == MLAN_STATUS_SUCCESS) { PRINTM(MMSG, "Radar found on channel %d," "switch to new channel %d.\n", old_channel, puap_state_chan_cb->channel); } else { PRINTM(MMSG, "Radar found on channel %d," " switch to new channel %d failed.\n", old_channel, puap_state_chan_cb->channel); pcb->moal_ioctl_complete(pmpriv->adapter->pmoal_handle, puap_state_chan_cb-> pioctl_req_curr, MLAN_STATUS_FAILURE); goto done; } } else { PRINTM(MMSG, "Radar found on channel %d, no switch channel available.\n", old_channel); /* No command sent with the ioctl, need manually signal completion */ pcb->moal_ioctl_complete(pmpriv->adapter->pmoal_handle, puap_state_chan_cb->pioctl_req_curr, MLAN_STATUS_FAILURE); goto done; } } else { PRINTM(MINFO, "No Radar found on channel %d\n", puap_state_chan_cb->channel); } } /* else okay to send command: not DFS channel or no radar */ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_BSS_START, HostCmd_ACT_GEN_SET, 0, (t_void *) puap_state_chan_cb->pioctl_req_curr, MNULL); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; done: puap_state_chan_cb->pioctl_req_curr = MNULL; // prevent re-use LEAVE(); return ret; } /** * @brief Start BSS * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ /** * @sa wlan_uap_callback_bss_ioctl_start */ static mlan_status wlan_uap_bss_ioctl_start(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; ENTER(); /* First check channel report, defer BSS_START CMD to callback. */ /* store params, issue command to get UAP channel, whose CMD_RESP will callback remainder of bss_start handling */ pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req; pmpriv->uap_state_chan_cb.get_chan_callback = wlan_uap_callback_bss_ioctl_start; ret = wlan_uap_get_channel(pmpriv); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief reset BSS * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_bss_ioctl_reset(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; t_u8 i = 0; ENTER(); /* * Reset any uap private parameters here */ for (i = 0; i < pmadapter->max_mgmt_ie_index; i++) { memset(pmadapter, &pmpriv->mgmt_ie[i], 0, sizeof(custom_ie)); } pmpriv->add_ba_param.timeout = MLAN_DEFAULT_BLOCK_ACK_TIMEOUT; pmpriv->add_ba_param.tx_win_size = MLAN_AMPDU_DEF_TXWINSIZE; pmpriv->add_ba_param.rx_win_size = MLAN_AMPDU_DEF_RXWINSIZE; for (i = 0; i < MAX_NUM_TID; i++) { pmpriv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; pmpriv->aggr_prio_tbl[i].amsdu = BA_STREAM_NOT_ALLOWED; pmpriv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT; } /* hs_configured, hs_activated are reset by main loop */ pmadapter->hs_cfg.conditions = HOST_SLEEP_DEF_COND; pmadapter->hs_cfg.gpio = HOST_SLEEP_DEF_GPIO; pmadapter->hs_cfg.gap = HOST_SLEEP_DEF_GAP; ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_RESET, HostCmd_ACT_GEN_SET, 0, (t_void *) pioctl_req, MNULL); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Set/Get MAC address * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_bss_ioctl_mac_address(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_bss *bss = MNULL; mlan_status ret = MLAN_STATUS_SUCCESS; t_u16 cmd_action = 0; ENTER(); bss = (mlan_ds_bss *) pioctl_req->pbuf; if (pioctl_req->action == MLAN_ACT_SET) { memcpy(pmadapter, pmpriv->curr_addr, &bss->param.mac_addr, MLAN_MAC_ADDR_LENGTH); cmd_action = HostCmd_ACT_GEN_SET; } else cmd_action = HostCmd_ACT_GEN_GET; /* Send request to firmware */ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action, 0, (t_void *) pioctl_req, MNULL); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Get Uap statistics * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_get_stats(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; ENTER(); ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, HostCmd_ACT_GEN_GET, 0, (t_void *) pioctl_req, MNULL); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Set/Get AP config * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_bss_ioctl_config(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_status ret = MLAN_STATUS_SUCCESS; t_u16 cmd_action = 0; ENTER(); if (pioctl_req->action == MLAN_ACT_SET) cmd_action = HostCmd_ACT_GEN_SET; else cmd_action = HostCmd_ACT_GEN_GET; /* Send request to firmware */ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action, 0, (t_void *) pioctl_req, MNULL); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief deauth sta * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_bss_ioctl_deauth_sta(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_bss *bss = MNULL; ENTER(); bss = (mlan_ds_bss *) pioctl_req->pbuf; ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_STA_DEAUTH, HostCmd_ACT_GEN_SET, 0, (t_void *) pioctl_req, (t_void *) & bss->param.deauth_param); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Get station list * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_get_sta_list(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_status ret = MLAN_STATUS_SUCCESS; ENTER(); /* Send request to firmware */ ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_STA_LIST, HostCmd_ACT_GEN_GET, 0, (t_void *) pioctl_req, MNULL); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief soft_reset * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_misc_ioctl_soft_reset(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_status ret = MLAN_STATUS_SUCCESS; ENTER(); ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_SOFT_RESET, HostCmd_ACT_GEN_SET, 0, (t_void *) pioctl_req, MNULL); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Tx data pause * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_misc_ioctl_txdatapause(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_misc_cfg *pmisc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; mlan_status ret = MLAN_STATUS_SUCCESS; t_u16 cmd_action = 0; ENTER(); if (pioctl_req->action == MLAN_ACT_SET) cmd_action = HostCmd_ACT_GEN_SET; else cmd_action = HostCmd_ACT_GEN_GET; ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_CFG_TX_DATA_PAUSE, cmd_action, 0, (t_void *) pioctl_req, &(pmisc->param.tx_datapause)); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Set/Get Power mode * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_pm_ioctl_mode(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_pm_cfg *pm = MNULL; mlan_status ret = MLAN_STATUS_SUCCESS; t_u16 cmd_action = 0; t_u32 cmd_oid = 0; ENTER(); pm = (mlan_ds_pm_cfg *) pioctl_req->pbuf; if (pioctl_req->action == MLAN_ACT_SET) { if (pm->param.ps_mgmt.ps_mode == PS_MODE_INACTIVITY) { cmd_action = EN_AUTO_PS; cmd_oid = BITMAP_UAP_INACT_PS; } else if (pm->param.ps_mgmt.ps_mode == PS_MODE_PERIODIC_DTIM) { cmd_action = EN_AUTO_PS; cmd_oid = BITMAP_UAP_DTIM_PS; } else { cmd_action = DIS_AUTO_PS; cmd_oid = BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS; } } else { cmd_action = GET_PS; cmd_oid = BITMAP_UAP_INACT_PS | BITMAP_UAP_DTIM_PS; } /* Send request to firmware */ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH, cmd_action, cmd_oid, (t_void *) pioctl_req, (t_void *) & pm->param.ps_mgmt); if ((ret == MLAN_STATUS_SUCCESS) && (pioctl_req->action == MLAN_ACT_SET) && (cmd_action == DIS_AUTO_PS)) { ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH, GET_PS, 0, MNULL, MNULL); } if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Set WAPI IE * * @param priv A pointer to mlan_private structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_set_wapi_ie(mlan_private * priv, pmlan_ioctl_req pioctl_req) { mlan_ds_misc_cfg *misc = MNULL; mlan_status ret = MLAN_STATUS_SUCCESS; ENTER(); misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; if (misc->param.gen_ie.len) { if (misc->param.gen_ie.len > sizeof(priv->wapi_ie)) { PRINTM(MWARN, "failed to copy WAPI IE, too big \n"); pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; LEAVE(); return MLAN_STATUS_FAILURE; } memcpy(priv->adapter, priv->wapi_ie, misc->param.gen_ie.ie_data, misc->param.gen_ie.len); priv->wapi_ie_len = misc->param.gen_ie.len; PRINTM(MIOCTL, "Set wapi_ie_len=%d IE=%#x\n", priv->wapi_ie_len, priv->wapi_ie[0]); DBG_HEXDUMP(MCMD_D, "wapi_ie", priv->wapi_ie, priv->wapi_ie_len); if (priv->wapi_ie[0] == WAPI_IE) priv->sec_info.wapi_enabled = MTRUE; } else { memset(priv->adapter, priv->wapi_ie, 0, sizeof(priv->wapi_ie)); priv->wapi_ie_len = misc->param.gen_ie.len; PRINTM(MINFO, "Reset wapi_ie_len=%d IE=%#x\n", priv->wapi_ie_len, priv->wapi_ie[0]); priv->sec_info.wapi_enabled = MFALSE; } /* Send request to firmware */ ret = wlan_prepare_cmd(priv, HOST_CMD_APCMD_SYS_CONFIGURE, HostCmd_ACT_GEN_SET, 0, (t_void *) pioctl_req, MNULL); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Set generic IE * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_misc_ioctl_gen_ie(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_misc_cfg *misc = MNULL; IEEEtypes_VendorHeader_t *pvendor_ie = MNULL; ENTER(); misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; if ((misc->param.gen_ie.type == MLAN_IE_TYPE_GEN_IE) && (pioctl_req->action == MLAN_ACT_SET)) { if (misc->param.gen_ie.len) { pvendor_ie = (IEEEtypes_VendorHeader_t *) misc->param.gen_ie.ie_data; if (pvendor_ie->element_id == WAPI_IE) { /* IE is a WAPI IE so call set_wapi function */ ret = wlan_uap_set_wapi_ie(pmpriv, pioctl_req); } } else { /* clear WAPI IE */ ret = wlan_uap_set_wapi_ie(pmpriv, pioctl_req); } } LEAVE(); return ret; } /** * @brief Set/Get WAPI status * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_SUCCESS --success */ static mlan_status wlan_uap_sec_ioctl_wapi_enable(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_sec_cfg *sec = MNULL; ENTER(); sec = (mlan_ds_sec_cfg *) pioctl_req->pbuf; if (pioctl_req->action == MLAN_ACT_GET) { if (pmpriv->wapi_ie_len) sec->param.wapi_enabled = MTRUE; else sec->param.wapi_enabled = MFALSE; } else { if (sec->param.wapi_enabled == MFALSE) { memset(pmpriv->adapter, pmpriv->wapi_ie, 0, sizeof(pmpriv->wapi_ie)); pmpriv->wapi_ie_len = 0; PRINTM(MINFO, "Reset wapi_ie_len=%d IE=%#x\n", pmpriv->wapi_ie_len, pmpriv->wapi_ie[0]); pmpriv->sec_info.wapi_enabled = MFALSE; } } pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE; LEAVE(); return ret; } /** * @brief Set encrypt key * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_sec_ioctl_set_encrypt_key(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_sec_cfg *sec = MNULL; ENTER(); sec = (mlan_ds_sec_cfg *) pioctl_req->pbuf; if (pioctl_req->action != MLAN_ACT_SET) { pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; LEAVE(); return MLAN_STATUS_FAILURE; } if (!sec->param.encrypt_key.key_len) { PRINTM(MCMND, "Skip set key with key_len = 0\n"); LEAVE(); return ret; } ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL, HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, (t_void *) pioctl_req, &sec->param.encrypt_key); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Get BSS information * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_SUCCESS --success */ static mlan_status wlan_uap_get_bss_info(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_status ret = MLAN_STATUS_SUCCESS; mlan_ds_get_info *info; ENTER(); info = (mlan_ds_get_info *) pioctl_req->pbuf; /* Connection status */ info->param.bss_info.media_connected = pmpriv->media_connected; /* Radio status */ info->param.bss_info.radio_on = pmadapter->radio_on; /* BSSID */ memcpy(pmadapter, &info->param.bss_info.bssid, pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH); info->param.bss_info.is_hs_configured = pmadapter->is_hs_configured; pioctl_req->data_read_written = sizeof(mlan_bss_info) + MLAN_SUB_COMMAND_SIZE; LEAVE(); return ret; } /** * @brief Set Host Sleep configurations * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_SUCCES/MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_pm_ioctl_deepsleep(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_pm_cfg *pm = MNULL; mlan_ds_auto_ds auto_ds; t_u32 mode; ENTER(); if (pioctl_req->buf_len < sizeof(mlan_ds_pm_cfg)) { PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n"); pioctl_req->data_read_written = 0; pioctl_req->buf_len_needed = sizeof(mlan_ds_pm_cfg); pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; LEAVE(); return MLAN_STATUS_RESOURCE; } pm = (mlan_ds_pm_cfg *) pioctl_req->pbuf; if (pioctl_req->action == MLAN_ACT_GET) { if (pmadapter->is_deep_sleep) { pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_ON; pm->param.auto_deep_sleep.idletime = pmadapter->idle_time; } else pm->param.auto_deep_sleep.auto_ds = DEEP_SLEEP_OFF; } else { if (pmadapter->is_deep_sleep && pm->param.auto_deep_sleep.auto_ds == DEEP_SLEEP_ON) { PRINTM(MMSG, "uAP already in deep sleep mode\n"); LEAVE(); return MLAN_STATUS_FAILURE; } if (((mlan_ds_pm_cfg *) pioctl_req->pbuf)->param.auto_deep_sleep. auto_ds == DEEP_SLEEP_ON) { auto_ds.auto_ds = DEEP_SLEEP_ON; mode = EN_AUTO_PS; PRINTM(MINFO, "Auto Deep Sleep: on\n"); } else { mode = DIS_AUTO_PS; auto_ds.auto_ds = DEEP_SLEEP_OFF; PRINTM(MINFO, "Auto Deep Sleep: off\n"); } if (((mlan_ds_pm_cfg *) pioctl_req->pbuf)->param.auto_deep_sleep. idletime) auto_ds.idletime = ((mlan_ds_pm_cfg *) pioctl_req->pbuf)->param.auto_deep_sleep. idletime; else auto_ds.idletime = pmadapter->idle_time; ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_PS_MODE_ENH, (t_u16) mode, BITMAP_AUTO_DS, (t_void *) pioctl_req, &auto_ds); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; } LEAVE(); return ret; } /** * @brief Set SNMP MIB for 11D * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail */ static mlan_status wlan_uap_snmp_mib_11d(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_snmp_mib *snmp = MNULL; state_11d_t flag; ENTER(); if (pioctl_req->buf_len < sizeof(mlan_ds_snmp_mib)) { PRINTM(MWARN, "MLAN snmp_mib IOCTL length is too short.\n"); pioctl_req->data_read_written = 0; pioctl_req->buf_len_needed = sizeof(mlan_ds_snmp_mib); LEAVE(); return MLAN_STATUS_RESOURCE; } if ((pioctl_req->action == MLAN_ACT_SET) && pmpriv->uap_bss_started) { PRINTM(MIOCTL, "11D setting cannot be changed while UAP bss is started.\n"); pioctl_req->data_read_written = 0; LEAVE(); return MLAN_STATUS_FAILURE; } snmp = (mlan_ds_snmp_mib *) pioctl_req->pbuf; flag = (snmp->param.oid_value) ? ENABLE_11D : DISABLE_11D; ret = wlan_11d_enable(pmpriv, (t_void *) pioctl_req, flag); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Callback to finish domain_info handling * Not to be called directly to initiate domain_info setting. * * @param pmpriv A pointer to mlan_private structure (cast from t_void*) * * @return MLAN_STATUS_PENDING --success, otherwise fail * @sa wlan_uap_domain_info */ static mlan_status wlan_uap_callback_domain_info(IN t_void * priv) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = (mlan_private *) priv; wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb; mlan_ds_11d_cfg *cfg11d; t_u8 band; ENTER(); /* clear callback now that we're here */ puap_state_chan_cb->get_chan_callback = MNULL; cfg11d = (mlan_ds_11d_cfg *) puap_state_chan_cb->pioctl_req_curr->pbuf; band = (puap_state_chan_cb->band_config & BAND_CONFIG_5GHZ) ? BAND_A : BAND_B; ret = wlan_11d_handle_uap_domain_info(pmpriv, band, cfg11d->param.domain_tlv, puap_state_chan_cb->pioctl_req_curr); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; puap_state_chan_cb->pioctl_req_curr = MNULL; // prevent re-use LEAVE(); return ret; } /** * @brief Set Domain Info for 11D * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail * @sa wlan_uap_callback_domain_info */ static mlan_status wlan_uap_domain_info(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; ENTER(); if (pioctl_req->buf_len < sizeof(mlan_ds_11d_cfg)) { PRINTM(MWARN, "MLAN 11d_cfg IOCTL length is too short.\n"); pioctl_req->data_read_written = 0; pioctl_req->buf_len_needed = sizeof(mlan_ds_11d_cfg); LEAVE(); return MLAN_STATUS_RESOURCE; } if ((pioctl_req->action == MLAN_ACT_SET) && pmpriv->uap_bss_started) { PRINTM(MIOCTL, "Domain_info cannot be changed while UAP bss is started.\n"); pioctl_req->data_read_written = 0; LEAVE(); return MLAN_STATUS_FAILURE; } /* store params, issue command to get UAP channel, whose CMD_RESP will callback remainder of domain_info handling */ pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req; pmpriv->uap_state_chan_cb.get_chan_callback = wlan_uap_callback_domain_info; ret = wlan_uap_get_channel(pmpriv); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Callback to finish 11H channel check handling. * Not to be called directly to initiate channel check. * * @param priv A pointer to mlan_private structure (cast from t_void*) * * @return MLAN_STATUS_SUCCESS/PENDING --success, otherwise fail * @sa wlan_uap_11h_channel_check_req */ static mlan_status wlan_uap_callback_11h_channel_check_req(IN t_void * priv) { mlan_status ret = MLAN_STATUS_FAILURE; mlan_private *pmpriv = (mlan_private *) priv; mlan_callbacks *pcb = (mlan_callbacks *) & pmpriv->adapter->callbacks; wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb; /* keep copy as local variable */ pmlan_ioctl_req pioctl = puap_state_chan_cb->pioctl_req_curr; ENTER(); /* clear callback now that we're here */ puap_state_chan_cb->get_chan_callback = MNULL; /* clear early to avoid race condition */ puap_state_chan_cb->pioctl_req_curr = MNULL; /* * Check if the region and channel requires a channel availability * check. */ if ((puap_state_chan_cb->band_config & BAND_CONFIG_5GHZ) && wlan_11h_radar_detect_required(pmpriv, puap_state_chan_cb->channel) && !wlan_11h_is_channel_under_nop(pmpriv->adapter, puap_state_chan_cb->channel)) { /* * Radar detection is required for this channel, make sure * 11h is activated in the firmware */ ret = wlan_11h_activate(pmpriv, MNULL, MTRUE); ret = wlan_11h_config_master_radar_det(pmpriv, MTRUE); ret = wlan_11h_check_update_radar_det_state(pmpriv); /* Check for radar on the channel */ ret = wlan_11h_issue_radar_detect(pmpriv, pioctl, puap_state_chan_cb->channel); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; } else { /* No command sent with the ioctl, need manually signal completion */ pcb->moal_ioctl_complete(pmpriv->adapter->pmoal_handle, pioctl, MLAN_STATUS_FAILURE); } LEAVE(); return ret; } /** * @brief 802.11h uap start channel check * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail * @sa wlan_uap_callback_11h_channel_check_req */ static mlan_status wlan_uap_11h_channel_check_req(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; ENTER(); if (pioctl_req->buf_len < sizeof(mlan_ds_11h_cfg)) { PRINTM(MWARN, "MLAN 11h_cfg IOCTL length is too short.\n"); pioctl_req->data_read_written = 0; pioctl_req->buf_len_needed = sizeof(mlan_ds_11h_cfg); LEAVE(); return MLAN_STATUS_RESOURCE; } /* store params, issue command to get UAP channel, whose CMD_RESP will callback remainder of 11H channel check handling */ pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req; pmpriv->uap_state_chan_cb.get_chan_callback = wlan_uap_callback_11h_channel_check_req; ret = wlan_uap_get_channel(pmpriv); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /** * @brief Callback to finish 11H handling * Not to be called directly to initiate 11H setting. * * @param pmpriv A pointer to mlan_private structure (cast from t_void*) * * @return MLAN_STATUS_PENDING --success, otherwise fail * @sa wlan_uap_snmp_mib_11h */ static mlan_status wlan_uap_callback_snmp_mib_11h(IN t_void * priv) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = (mlan_private *) priv; wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb; mlan_ds_snmp_mib *snmp; t_bool enable_11h; ENTER(); /* clear callback now that we're here */ puap_state_chan_cb->get_chan_callback = MNULL; snmp = (mlan_ds_snmp_mib *) puap_state_chan_cb->pioctl_req_curr->pbuf; enable_11h = (snmp->param.oid_value) ? MTRUE : MFALSE; if (enable_11h) { if ((puap_state_chan_cb->band_config & BAND_CONFIG_5GHZ) && wlan_11h_radar_detect_required(pmpriv, puap_state_chan_cb->channel)) { if (!wlan_11h_is_master_radar_det_active(pmpriv)) wlan_11h_config_master_radar_det(pmpriv, MTRUE); } } ret = wlan_11h_activate(pmpriv, (t_void *) puap_state_chan_cb->pioctl_req_curr, enable_11h); wlan_11h_check_update_radar_det_state(pmpriv); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; puap_state_chan_cb->pioctl_req_curr = MNULL; // prevent re-use LEAVE(); return ret; } /** * @brief Set SNMP MIB for 11H * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_PENDING --success, otherwise fail * @sa wlan_uap_callback_snmp_mib_11h */ static mlan_status wlan_uap_snmp_mib_11h(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_snmp_mib *snmp = MNULL; t_bool enable; ENTER(); if (pioctl_req->buf_len < sizeof(mlan_ds_snmp_mib)) { PRINTM(MWARN, "MLAN snmp_mib IOCTL length is too short.\n"); pioctl_req->data_read_written = 0; pioctl_req->buf_len_needed = sizeof(mlan_ds_snmp_mib); LEAVE(); return MLAN_STATUS_RESOURCE; } snmp = (mlan_ds_snmp_mib *) pioctl_req->pbuf; enable = (snmp->param.oid_value) ? MTRUE : MFALSE; if (enable) { /* first enable 11D if it is not enabled */ if (!wlan_11d_is_enabled(pmpriv)) { ret = wlan_11d_enable(pmpriv, MNULL, ENABLE_11D); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to first enable 11D before enabling 11H.\n"); LEAVE(); return ret; } } } /* store params, issue command to get UAP channel, whose CMD_RESP will callback remainder of 11H handling (and radar detect if DFS chan) */ pmpriv->uap_state_chan_cb.pioctl_req_curr = pioctl_req; pmpriv->uap_state_chan_cb.get_chan_callback = wlan_uap_callback_snmp_mib_11h; ret = wlan_uap_get_channel(pmpriv); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } /******************************************************** Global Functions ********************************************************/ /** * @brief Issue CMD to UAP firmware to get current channel * * @param pmpriv A pointer to mlan_private structure * * @return MLAN_STATUS_SUCCESS --success, otherwise fail */ mlan_status wlan_uap_get_channel(IN pmlan_private pmpriv) { MrvlIEtypes_channel_band_t tlv_chan_band; mlan_status ret = MLAN_STATUS_SUCCESS; ENTER(); memset(pmpriv->adapter, &tlv_chan_band, 0, sizeof(tlv_chan_band)); tlv_chan_band.header.type = TLV_TYPE_UAP_CHAN_BAND_CONFIG; tlv_chan_band.header.len = sizeof(MrvlIEtypes_channel_band_t) - sizeof(MrvlIEtypesHeader_t); ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, HostCmd_ACT_GEN_GET, 0, MNULL, &tlv_chan_band); LEAVE(); return ret; } /** * @brief Issue CMD to UAP firmware to set current channel * * @param pmpriv A pointer to mlan_private structure * @param uap_band_cfg UAP band configuration * @param channel New channel * * @return MLAN_STATUS_SUCCESS --success, otherwise fail */ mlan_status wlan_uap_set_channel(IN pmlan_private pmpriv, IN t_u8 uap_band_cfg, IN t_u8 channel) { MrvlIEtypes_channel_band_t tlv_chan_band; mlan_status ret = MLAN_STATUS_SUCCESS; ENTER(); memset(pmpriv->adapter, &tlv_chan_band, 0, sizeof(tlv_chan_band)); tlv_chan_band.header.type = TLV_TYPE_UAP_CHAN_BAND_CONFIG; tlv_chan_band.header.len = sizeof(MrvlIEtypes_channel_band_t) - sizeof(MrvlIEtypesHeader_t); tlv_chan_band.band_config = uap_band_cfg; tlv_chan_band.channel = channel; ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, HostCmd_ACT_GEN_SET, 0, MNULL, &tlv_chan_band); LEAVE(); return ret; } /** * @brief Issue CMD to UAP firmware to get current beacon and dtim periods * * @param pmpriv A pointer to mlan_private structure * * @return MLAN_STATUS_SUCCESS --success, otherwise fail */ mlan_status wlan_uap_get_beacon_dtim(IN pmlan_private pmpriv) { t_u8 tlv_buffer[sizeof(MrvlIEtypes_beacon_period_t) + sizeof(MrvlIEtypes_dtim_period_t)]; MrvlIEtypes_beacon_period_t *ptlv_beacon_pd; MrvlIEtypes_dtim_period_t *ptlv_dtim_pd; mlan_status ret = MLAN_STATUS_SUCCESS; ENTER(); memset(pmpriv->adapter, &tlv_buffer, 0, sizeof(tlv_buffer)); ptlv_beacon_pd = (MrvlIEtypes_beacon_period_t *) tlv_buffer; ptlv_beacon_pd->header.type = TLV_TYPE_UAP_BEACON_PERIOD; ptlv_beacon_pd->header.len = sizeof(MrvlIEtypes_beacon_period_t) - sizeof(MrvlIEtypesHeader_t); ptlv_dtim_pd = (MrvlIEtypes_dtim_period_t *) (tlv_buffer + sizeof (MrvlIEtypes_beacon_period_t)); ptlv_dtim_pd->header.type = TLV_TYPE_UAP_DTIM_PERIOD; ptlv_dtim_pd->header.len = sizeof(MrvlIEtypes_dtim_period_t) - sizeof(MrvlIEtypesHeader_t); ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, HostCmd_ACT_GEN_GET, 0, MNULL, tlv_buffer); LEAVE(); return ret; } /** * @brief MLAN uap ioctl handler * * @param adapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * * @return MLAN_STATUS_SUCCESS --success, otherwise fail */ mlan_status wlan_ops_uap_ioctl(t_void * adapter, pmlan_ioctl_req pioctl_req) { pmlan_adapter pmadapter = (pmlan_adapter) adapter; mlan_status status = MLAN_STATUS_SUCCESS; mlan_ds_bss *bss = MNULL; mlan_ds_get_info *pget_info = MNULL; mlan_ds_misc_cfg *misc = MNULL; mlan_ds_sec_cfg *sec = MNULL; mlan_ds_pm_cfg *pm = MNULL; mlan_ds_snmp_mib *snmp = MNULL; mlan_ds_11d_cfg *cfg11d = MNULL; mlan_ds_11h_cfg *cfg11h = MNULL; mlan_ds_radio_cfg *radiocfg = MNULL; mlan_ds_rate *rate = MNULL; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; ENTER(); switch (pioctl_req->req_id) { case MLAN_IOCTL_BSS: bss = (mlan_ds_bss *) pioctl_req->pbuf; if (bss->sub_command == MLAN_OID_BSS_MAC_ADDR) status = wlan_uap_bss_ioctl_mac_address(pmadapter, pioctl_req); else if (bss->sub_command == MLAN_OID_BSS_STOP) status = wlan_uap_bss_ioctl_stop(pmadapter, pioctl_req); else if (bss->sub_command == MLAN_OID_BSS_START) status = wlan_uap_bss_ioctl_start(pmadapter, pioctl_req); else if (bss->sub_command == MLAN_OID_UAP_BSS_CONFIG) status = wlan_uap_bss_ioctl_config(pmadapter, pioctl_req); else if (bss->sub_command == MLAN_OID_UAP_DEAUTH_STA) status = wlan_uap_bss_ioctl_deauth_sta(pmadapter, pioctl_req); else if (bss->sub_command == MLAN_OID_UAP_BSS_RESET) status = wlan_uap_bss_ioctl_reset(pmadapter, pioctl_req); #if defined(STA_SUPPORT) && defined(UAP_SUPPORT) else if (bss->sub_command == MLAN_OID_BSS_ROLE) status = wlan_bss_ioctl_bss_role(pmadapter, pioctl_req); #endif #ifdef WIFI_DIRECT_SUPPORT else if (bss->sub_command == MLAN_OID_WIFI_DIRECT_MODE) status = wlan_bss_ioctl_wifi_direct_mode(pmadapter, pioctl_req); #endif break; case MLAN_IOCTL_GET_INFO: pget_info = (mlan_ds_get_info *) pioctl_req->pbuf; if (pget_info->sub_command == MLAN_OID_GET_VER_EXT) status = wlan_get_info_ver_ext(pmadapter, pioctl_req); else if (pget_info->sub_command == MLAN_OID_GET_DEBUG_INFO) status = wlan_get_info_debug_info(pmadapter, pioctl_req); else if (pget_info->sub_command == MLAN_OID_GET_STATS) status = wlan_uap_get_stats(pmadapter, pioctl_req); else if (pget_info->sub_command == MLAN_OID_UAP_STA_LIST) status = wlan_uap_get_sta_list(pmadapter, pioctl_req); else if (pget_info->sub_command == MLAN_OID_GET_BSS_INFO) status = wlan_uap_get_bss_info(pmadapter, pioctl_req); else if (pget_info->sub_command == MLAN_OID_GET_FW_INFO) { pioctl_req->data_read_written = sizeof(mlan_fw_info) + MLAN_SUB_COMMAND_SIZE; memcpy(pmadapter, &pget_info->param.fw_info.mac_addr, pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH); pget_info->param.fw_info.fw_ver = pmadapter->fw_release_number; pget_info->param.fw_info.fw_bands = pmadapter->fw_bands; pget_info->param.fw_info.hw_dev_mcs_support = pmadapter->hw_dev_mcs_support; } break; case MLAN_IOCTL_MISC_CFG: misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; if (misc->sub_command == MLAN_OID_MISC_INIT_SHUTDOWN) status = wlan_misc_ioctl_init_shutdown(pmadapter, pioctl_req); if (misc->sub_command == MLAN_OID_MISC_SOFT_RESET) status = wlan_uap_misc_ioctl_soft_reset(pmadapter, pioctl_req); if (misc->sub_command == MLAN_OID_MISC_HOST_CMD) status = wlan_misc_ioctl_host_cmd(pmadapter, pioctl_req); if (misc->sub_command == MLAN_OID_MISC_GEN_IE) status = wlan_uap_misc_ioctl_gen_ie(pmadapter, pioctl_req); if (misc->sub_command == MLAN_OID_MISC_CUSTOM_IE) status = wlan_misc_ioctl_custom_ie_list(pmadapter, pioctl_req, MTRUE); if (misc->sub_command == MLAN_OID_MISC_TX_DATAPAUSE) status = wlan_uap_misc_ioctl_txdatapause(pmadapter, pioctl_req); if (misc->sub_command == MLAN_OID_MISC_RX_MGMT_IND) status = wlan_reg_rx_mgmt_ind(pmadapter, pioctl_req); #ifdef DEBUG_LEVEL1 if (misc->sub_command == MLAN_OID_MISC_DRVDBG) status = wlan_set_drvdbg(pmadapter, pioctl_req); #endif break; case MLAN_IOCTL_PM_CFG: pm = (mlan_ds_pm_cfg *) pioctl_req->pbuf; if (pm->sub_command == MLAN_OID_PM_CFG_PS_MODE) status = wlan_uap_pm_ioctl_mode(pmadapter, pioctl_req); if (pm->sub_command == MLAN_OID_PM_CFG_DEEP_SLEEP) status = wlan_uap_pm_ioctl_deepsleep(pmadapter, pioctl_req); if (pm->sub_command == MLAN_OID_PM_CFG_HS_CFG) { status = wlan_pm_ioctl_hscfg(pmadapter, pioctl_req); } if (pm->sub_command == MLAN_OID_PM_INFO) { status = wlan_get_pm_info(pmadapter, pioctl_req); } break; case MLAN_IOCTL_SNMP_MIB: snmp = (mlan_ds_snmp_mib *) pioctl_req->pbuf; if (snmp->sub_command == MLAN_OID_SNMP_MIB_DOT11D) status = wlan_uap_snmp_mib_11d(pmadapter, pioctl_req); if (snmp->sub_command == MLAN_OID_SNMP_MIB_DOT11H) status = wlan_uap_snmp_mib_11h(pmadapter, pioctl_req); break; case MLAN_IOCTL_SEC_CFG: sec = (mlan_ds_sec_cfg *) pioctl_req->pbuf; if (sec->sub_command == MLAN_OID_SEC_CFG_ENCRYPT_KEY) status = wlan_uap_sec_ioctl_set_encrypt_key(pmadapter, pioctl_req); if (sec->sub_command == MLAN_OID_SEC_CFG_WAPI_ENABLED) status = wlan_uap_sec_ioctl_wapi_enable(pmadapter, pioctl_req); break; case MLAN_IOCTL_11N_CFG: status = wlan_11n_cfg_ioctl(pmadapter, pioctl_req); break; case MLAN_IOCTL_11D_CFG: cfg11d = (mlan_ds_11d_cfg *) pioctl_req->pbuf; if (cfg11d->sub_command == MLAN_OID_11D_DOMAIN_INFO) status = wlan_uap_domain_info(pmadapter, pioctl_req); break; case MLAN_IOCTL_11H_CFG: cfg11h = (mlan_ds_11h_cfg *) pioctl_req->pbuf; if (cfg11h->sub_command == MLAN_OID_11H_CHANNEL_CHECK) status = wlan_uap_11h_channel_check_req(pmadapter, pioctl_req); #if defined(DFS_TESTING_SUPPORT) if (cfg11h->sub_command == MLAN_OID_11H_DFS_TESTING) status = wlan_11h_ioctl_dfs_testing(pmadapter, pioctl_req); #endif break; case MLAN_IOCTL_RADIO_CFG: radiocfg = (mlan_ds_radio_cfg *) pioctl_req->pbuf; if (radiocfg->sub_command == MLAN_OID_RADIO_CTRL) status = wlan_radio_ioctl_radio_ctl(pmadapter, pioctl_req); #ifdef WIFI_DIRECT_SUPPORT if (radiocfg->sub_command == MLAN_OID_REMAIN_CHAN_CFG) status = wlan_radio_ioctl_remain_chan_cfg(pmadapter, pioctl_req); #endif if (radiocfg->sub_command == MLAN_OID_ANT_CFG) status = wlan_radio_ioctl_ant_cfg(pmadapter, pioctl_req); break; case MLAN_IOCTL_RATE: rate = (mlan_ds_rate *) pioctl_req->pbuf; if (rate->sub_command == MLAN_OID_RATE_CFG) status = wlan_rate_ioctl_cfg(pmadapter, pioctl_req); break; default: pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; break; } LEAVE(); return status; }