/** @file mlan_uap_cmdevent.c * * @brief This file contains the handling of AP mode command and event * * Copyright (C) 2009-2019, 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_11n.h" #include "mlan_11h.h" #include "mlan_11ac.h" #ifdef DRV_EMBEDDED_AUTHENTICATOR #include "authenticator_api.h" #endif #include "mlan_pcie.h" /******************************************************** Local Functions ********************************************************/ /** * @brief This function handles the command response error * * @param pmpriv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @param pioctl_buf A pointer to command buffer * * @return N/A */ static mlan_status uap_process_cmdresp_error(mlan_private *pmpriv, HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf) { mlan_adapter *pmadapter = pmpriv->adapter; mlan_status ret = MLAN_STATUS_FAILURE; ENTER(); if (resp->command != HostCmd_CMD_WMM_PARAM_CONFIG || resp->command != HostCmd_CMD_CHAN_REGION_CFG) PRINTM(MERROR, "CMD_RESP: cmd %#x error, result=%#x\n", resp->command, resp->result); if (pioctl_buf) pioctl_buf->status_code = resp->result; /* * Handling errors here */ switch (resp->command) { case HOST_CMD_APCMD_SYS_CONFIGURE: { HostCmd_DS_SYS_CONFIG *sys_config = (HostCmd_DS_SYS_CONFIG *)&resp->params. sys_config; t_u16 resp_len = 0, travel_len = 0, index; mlan_ds_misc_custom_ie *cust_ie = MNULL; mlan_ds_misc_cfg *misc = MNULL; custom_ie *cptr; if (!pioctl_buf || (pioctl_buf->req_id != MLAN_IOCTL_MISC_CFG)) break; misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf; if ((pioctl_buf->action == MLAN_ACT_SET) && (misc->sub_command == MLAN_OID_MISC_CUSTOM_IE)) { cust_ie = (mlan_ds_misc_custom_ie *)sys_config-> tlv_buffer; if (cust_ie) { cust_ie->type = wlan_le16_to_cpu(cust_ie->type); resp_len = cust_ie->len = wlan_le16_to_cpu(cust_ie->len); travel_len = 0; /* conversion for index, mask, len */ if (resp_len == sizeof(t_u16)) cust_ie->ie_data_list[0]. ie_index = wlan_cpu_to_le16 (cust_ie-> ie_data_list[0]. ie_index); while (resp_len > sizeof(t_u16)) { cptr = (custom_ie *)(((t_u8 *)cust_ie-> ie_data_list) + travel_len); index = cptr->ie_index = wlan_le16_to_cpu(cptr-> ie_index); cptr->mgmt_subtype_mask = wlan_le16_to_cpu(cptr-> mgmt_subtype_mask); cptr->ie_length = wlan_le16_to_cpu(cptr-> ie_length); travel_len += cptr->ie_length + sizeof(custom_ie) - MAX_IE_SIZE; resp_len -= cptr->ie_length + sizeof(custom_ie) - MAX_IE_SIZE; if ((pmpriv->mgmt_ie[index]. mgmt_subtype_mask == cptr->mgmt_subtype_mask) && (pmpriv->mgmt_ie[index]. ie_length == cptr->ie_length) && !memcmp(pmpriv->adapter, pmpriv-> mgmt_ie[index]. ie_buffer, cptr->ie_buffer, cptr->ie_length)) { PRINTM(MERROR, "set custom ie fail, remove ie index :%d\n", index); memset(pmadapter, &pmpriv-> mgmt_ie[index], 0, sizeof (custom_ie)); } } } } } break; case HostCmd_CMD_CHAN_REGION_CFG: ret = MLAN_STATUS_SUCCESS; PRINTM(MCMND, "FW don't support chan region cfg command!\n"); break; #if defined(DRV_EMBEDDED_AUTHENTICATOR) case HostCmd_CMD_CRYPTO: PRINTM(MCMND, "crypto cmd result=0x%x!\n", resp->result); ret = wlan_ret_crypto(pmpriv, resp, pioctl_buf); break; #endif default: break; } wlan_request_cmd_lock(pmadapter); wlan_insert_cmd_to_free_q(pmadapter, pmadapter->curr_cmd); pmadapter->curr_cmd = MNULL; wlan_release_cmd_lock(pmadapter); LEAVE(); return ret; } /** * @brief This function will return the pointer to station entry in station list * table which matches the give mac address * * @param priv A pointer to mlan_private * * @return A pointer to structure sta_node */ void wlan_notify_station_deauth(mlan_private *priv) { sta_node *sta_ptr; t_u8 event_buf[100]; mlan_event *pevent = (mlan_event *)event_buf; t_u8 *pbuf; ENTER(); sta_ptr = (sta_node *)util_peek_list(priv->adapter->pmoal_handle, &priv->sta_list, priv->adapter->callbacks. moal_spin_lock, priv->adapter->callbacks. moal_spin_unlock); if (!sta_ptr) { LEAVE(); return; } while (sta_ptr != (sta_node *)&priv->sta_list) { memset(priv->adapter, event_buf, 0, sizeof(event_buf)); pevent->bss_index = priv->bss_index; pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT; pevent->event_len = MLAN_MAC_ADDR_LENGTH + 2; pbuf = (t_u8 *)pevent->event_buf; /* reason field set to 0, Unspecified */ memcpy(priv->adapter, pbuf + 2, sta_ptr->mac_addr, MLAN_MAC_ADDR_LENGTH); wlan_recv_event(priv, pevent->event_id, pevent); sta_ptr = sta_ptr->pnext; } LEAVE(); return; } /** * @brief This function prepares command of hs_cfg. * * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @param cmd_action The action: GET or SET * @param pdata_buf A pointer to data buffer * * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_cmd_802_11_hs_cfg(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action, IN hs_config_param *pdata_buf) { pmlan_adapter pmadapter = pmpriv->adapter; HostCmd_DS_802_11_HS_CFG_ENH *phs_cfg = (HostCmd_DS_802_11_HS_CFG_ENH *)&(cmd->params.opt_hs_cfg); t_u8 *tlv = (t_u8 *)phs_cfg + sizeof(HostCmd_DS_802_11_HS_CFG_ENH); MrvlIEtypes_HsWakeHoldoff_t *holdoff_tlv = MNULL; MrvlIEtypes_HS_Antmode_t *antmode_tlv = MNULL; MrvlIEtypes_WakeupSourceGPIO_t *gpio_tlv = MNULL; MrvlIEtypes_MgmtFrameFilter_t *mgmt_filter_tlv = MNULL; MrvlIEtypes_WakeupExtend_t *ext_tlv = MNULL; ENTER(); cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_802_11_HS_CFG_ENH)); if (pdata_buf == MNULL) { phs_cfg->action = wlan_cpu_to_le16(HS_ACTIVATE); phs_cfg->params.hs_activate.resp_ctrl = wlan_cpu_to_le16(RESP_NEEDED); } else { phs_cfg->action = wlan_cpu_to_le16(HS_CONFIGURE); phs_cfg->params.hs_config.conditions = wlan_cpu_to_le32(pdata_buf->conditions); phs_cfg->params.hs_config.gpio = pdata_buf->gpio; phs_cfg->params.hs_config.gap = pdata_buf->gap; if (pmpriv->adapter->min_wake_holdoff) { cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof (HostCmd_DS_802_11_HS_CFG_ENH) + sizeof (MrvlIEtypes_HsWakeHoldoff_t)); holdoff_tlv = (MrvlIEtypes_HsWakeHoldoff_t *)tlv; holdoff_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_HS_WAKE_HOLDOFF); holdoff_tlv->header.len = wlan_cpu_to_le16(sizeof (MrvlIEtypes_HsWakeHoldoff_t) - sizeof(MrvlIEtypesHeader_t)); holdoff_tlv->min_wake_holdoff = wlan_cpu_to_le16(pmpriv->adapter-> min_wake_holdoff); tlv += sizeof(MrvlIEtypes_HsWakeHoldoff_t); } PRINTM(MCMND, "HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x holdoff=%d\n", phs_cfg->params.hs_config.conditions, phs_cfg->params.hs_config.gpio, phs_cfg->params.hs_config.gap, pmpriv->adapter->min_wake_holdoff); if (pmadapter->param_type_ind == 1) { cmd->size += sizeof(MrvlIEtypes_WakeupSourceGPIO_t); gpio_tlv = (MrvlIEtypes_WakeupSourceGPIO_t *) tlv; gpio_tlv->header.type = wlan_cpu_to_le16 (TLV_TYPE_HS_WAKEUP_SOURCE_GPIO); gpio_tlv->header.len = wlan_cpu_to_le16(sizeof (MrvlIEtypes_WakeupSourceGPIO_t) - sizeof(MrvlIEtypesHeader_t)); gpio_tlv->ind_gpio = (t_u8)pmadapter->ind_gpio; gpio_tlv->level = (t_u8)pmadapter->level; tlv += sizeof(MrvlIEtypes_WakeupSourceGPIO_t); } if (pmadapter->param_type_ext == 2) { cmd->size += sizeof(MrvlIEtypes_WakeupExtend_t); ext_tlv = (MrvlIEtypes_WakeupExtend_t *) tlv; ext_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_WAKEUP_EXTEND); ext_tlv->header.len = wlan_cpu_to_le16(sizeof (MrvlIEtypes_WakeupExtend_t) - sizeof(MrvlIEtypesHeader_t)); ext_tlv->event_force_ignore = wlan_cpu_to_le32(pmadapter->event_force_ignore); ext_tlv->event_use_ext_gap = wlan_cpu_to_le32(pmadapter->event_use_ext_gap); ext_tlv->ext_gap = pmadapter->ext_gap; ext_tlv->gpio_wave = pmadapter->gpio_wave; tlv += sizeof(MrvlIEtypes_WakeupExtend_t); } if (pmadapter->mgmt_filter[0].type) { int i = 0; mgmt_frame_filter mgmt_filter[MAX_MGMT_FRAME_FILTER]; memset(pmadapter, mgmt_filter, 0, MAX_MGMT_FRAME_FILTER * sizeof(mgmt_frame_filter)); mgmt_filter_tlv = (MrvlIEtypes_MgmtFrameFilter_t *) tlv; mgmt_filter_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_MGMT_FRAME_WAKEUP); tlv += sizeof(MrvlIEtypesHeader_t); while (i < MAX_MGMT_FRAME_FILTER && pmadapter->mgmt_filter[i].type) { mgmt_filter[i].action = (t_u8)pmadapter->mgmt_filter[i].action; mgmt_filter[i].type = (t_u8)pmadapter->mgmt_filter[i].type; mgmt_filter[i].frame_mask = wlan_cpu_to_le32(pmadapter-> mgmt_filter[i]. frame_mask); i++; } memcpy(pmadapter, (t_u8 *)mgmt_filter_tlv->filter, (t_u8 *)mgmt_filter, i * sizeof(mgmt_frame_filter)); tlv += i * sizeof(mgmt_frame_filter); mgmt_filter_tlv->header.len = wlan_cpu_to_le16(i * sizeof(mgmt_frame_filter)); cmd->size += i * sizeof(mgmt_frame_filter) + sizeof(MrvlIEtypesHeader_t); } if (pmadapter->hs_mimo_switch) { cmd->size += sizeof(MrvlIEtypes_HS_Antmode_t); antmode_tlv = (MrvlIEtypes_HS_Antmode_t *) tlv; antmode_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_HS_ANTMODE); antmode_tlv->header.len = wlan_cpu_to_le16(sizeof (MrvlIEtypes_HS_Antmode_t) - sizeof(MrvlIEtypesHeader_t)); antmode_tlv->txpath_antmode = ANTMODE_FW_DECISION; antmode_tlv->rxpath_antmode = ANTMODE_FW_DECISION; tlv += sizeof(MrvlIEtypes_HS_Antmode_t); PRINTM(MCMND, "hs_mimo_switch=%d, txpath_antmode=%d, rxpath_antmode=%d\n", pmadapter->hs_mimo_switch, antmode_tlv->txpath_antmode, antmode_tlv->rxpath_antmode); } } LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function prepares command of Tx data pause * * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @param cmd_action the action: GET or SET * @param pdata_buf A pointer to data buffer * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_cmd_txdatapause(pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action, IN t_void *pdata_buf) { HostCmd_DS_CMD_TX_DATA_PAUSE *pause_cmd = (HostCmd_DS_CMD_TX_DATA_PAUSE *)&cmd->params.tx_data_pause; mlan_ds_misc_tx_datapause *data_pause = (mlan_ds_misc_tx_datapause *)pdata_buf; ENTER(); cmd->command = wlan_cpu_to_le16(HostCmd_CMD_CFG_TX_DATA_PAUSE); cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_TX_DATA_PAUSE) + S_DS_GEN); pause_cmd->action = wlan_cpu_to_le16(cmd_action); if (cmd_action == HostCmd_ACT_GEN_SET) { pause_cmd->enable_tx_pause = (t_u8)data_pause->tx_pause; pause_cmd->pause_tx_count = (t_u8)data_pause->tx_buf_cnt; } LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function handles the command response of Tx data pause * * @param pmpriv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @param pioctl_buf A pointer to mlan_ioctl_req structure * * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_ret_txdatapause(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf) { HostCmd_DS_CMD_TX_DATA_PAUSE *pause_cmd = (HostCmd_DS_CMD_TX_DATA_PAUSE *)&resp->params.tx_data_pause; mlan_ds_misc_cfg *misc_cfg = MNULL; ENTER(); if (pioctl_buf) { misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf; misc_cfg->param.tx_datapause.tx_pause = pause_cmd->enable_tx_pause; misc_cfg->param.tx_datapause.tx_buf_cnt = pause_cmd->pause_tx_count; } LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function will process tx pause event * * @param priv A pointer to mlan_private * @param pevent A pointer to event buf * * @return N/A */ static void wlan_process_tx_pause_event(pmlan_private priv, pmlan_buffer pevent) { t_u16 tlv_type, tlv_len; int tlv_buf_left = pevent->data_len - sizeof(t_u32); MrvlIEtypesHeader_t *tlv = (MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset + sizeof(t_u32)); MrvlIEtypes_tx_pause_t *tx_pause_tlv; sta_node *sta_ptr = MNULL; t_u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; t_u32 total_pkts_queued; t_u16 tx_pkts_queued = 0;; ENTER(); total_pkts_queued = util_scalar_read(priv->adapter->pmoal_handle, &priv->wmm.tx_pkts_queued, MNULL, MNULL); while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) { tlv_type = wlan_le16_to_cpu(tlv->type); tlv_len = wlan_le16_to_cpu(tlv->len); if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) > (unsigned int)tlv_buf_left) { PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len, tlv_buf_left); break; } if (tlv_type == TLV_TYPE_TX_PAUSE) { tx_pause_tlv = (MrvlIEtypes_tx_pause_t *)tlv; if (!memcmp (priv->adapter, bc_mac, tx_pause_tlv->peermac, MLAN_MAC_ADDR_LENGTH)) tx_pkts_queued = wlan_update_ralist_tx_pause(priv, tx_pause_tlv-> peermac, tx_pause_tlv-> tx_pause); else if (!memcmp (priv->adapter, priv->curr_addr, tx_pause_tlv->peermac, MLAN_MAC_ADDR_LENGTH)) { if (tx_pause_tlv->tx_pause) priv->tx_pause = MTRUE; else priv->tx_pause = MFALSE; } else { sta_ptr = wlan_get_station_entry(priv, tx_pause_tlv-> peermac); if (sta_ptr) { if (sta_ptr->tx_pause != tx_pause_tlv->tx_pause) { sta_ptr->tx_pause = tx_pause_tlv->tx_pause; tx_pkts_queued = wlan_update_ralist_tx_pause (priv, tx_pause_tlv->peermac, tx_pause_tlv-> tx_pause); } } } if (!tx_pause_tlv->tx_pause) total_pkts_queued += tx_pkts_queued; PRINTM(MCMND, "TxPause: " MACSTR " pause=%d, pkts=%d pending=%d total=%d\n", MAC2STR(tx_pause_tlv->peermac), tx_pause_tlv->tx_pause, tx_pause_tlv->pkt_cnt, tx_pkts_queued, total_pkts_queued); } tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len); tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len + sizeof(MrvlIEtypesHeader_t)); } LEAVE(); return; } /** * @brief This function prepares command of Tx ampdu prot mode * * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @param cmd_action the action: GET or SET * @param pdata_buf A pointer to data buffer * @return MLAN_STATUS_SUCCESS */ mlan_status wlan_cmd_tx_ampdu_prot_mode(pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action, IN t_void *pdata_buf) { HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *cfg_cmd = (HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *) & cmd->params.tx_ampdu_prot_mode; mlan_ds_misc_tx_ampdu_prot_mode *cfg = (mlan_ds_misc_tx_ampdu_prot_mode *) pdata_buf; ENTER(); cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TX_AMPDU_PROT_MODE); cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CMD_TX_AMPDU_PROT_MODE) + S_DS_GEN); cfg_cmd->action = wlan_cpu_to_le16(cmd_action); if (cmd_action == HostCmd_ACT_GEN_SET) { cfg_cmd->mode = wlan_cpu_to_le16(cfg->mode); } LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function handles the command response of Tx ampdu prot mode * * @param pmpriv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @param pioctl_buf A pointer to mlan_ioctl_req structure * * @return MLAN_STATUS_SUCCESS */ mlan_status wlan_ret_tx_ampdu_prot_mode(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf) { HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *cfg_cmd = (HostCmd_DS_CMD_TX_AMPDU_PROT_MODE *) & resp->params.tx_ampdu_prot_mode; mlan_ds_misc_cfg *misc_cfg = MNULL; ENTER(); if (pioctl_buf) { misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf; misc_cfg->param.tx_ampdu_prot_mode.mode = wlan_le16_to_cpu(cfg_cmd->mode); } LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function prepares command for config uap settings * * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @param cmd_action the action: GET or SET * @param pioctl_buf A pointer to mlan_ioctl_req structure * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status wlan_uap_cmd_ap_config(pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action, IN pmlan_ioctl_req pioctl_buf) { mlan_ds_bss *bss = MNULL; HostCmd_DS_SYS_CONFIG *sys_config = (HostCmd_DS_SYS_CONFIG *)&cmd->params.sys_config; t_u8 *tlv = MNULL; MrvlIEtypes_MacAddr_t *tlv_mac = MNULL; MrvlIEtypes_SsIdParamSet_t *tlv_ssid = MNULL; MrvlIEtypes_beacon_period_t *tlv_beacon_period = MNULL; MrvlIEtypes_dtim_period_t *tlv_dtim_period = MNULL; MrvlIEtypes_RatesParamSet_t *tlv_rates = MNULL; MrvlIEtypes_tx_rate_t *tlv_txrate = MNULL; MrvlIEtypes_mcbc_rate_t *tlv_mcbc_rate = MNULL; MrvlIEtypes_tx_power_t *tlv_tx_power = MNULL; MrvlIEtypes_bcast_ssid_t *tlv_bcast_ssid = MNULL; MrvlIEtypes_antenna_mode_t *tlv_antenna = MNULL; MrvlIEtypes_pkt_forward_t *tlv_pkt_forward = MNULL; MrvlIEtypes_max_sta_count_t *tlv_sta_count = MNULL; MrvlIEtypes_sta_ageout_t *tlv_sta_ageout = MNULL; MrvlIEtypes_ps_sta_ageout_t *tlv_ps_sta_ageout = MNULL; MrvlIEtypes_rts_threshold_t *tlv_rts_threshold = MNULL; MrvlIEtypes_frag_threshold_t *tlv_frag_threshold = MNULL; MrvlIEtypes_retry_limit_t *tlv_retry_limit = MNULL; MrvlIEtypes_eapol_pwk_hsk_timeout_t *tlv_pairwise_timeout = MNULL; MrvlIEtypes_eapol_pwk_hsk_retries_t *tlv_pairwise_retries = MNULL; MrvlIEtypes_eapol_gwk_hsk_timeout_t *tlv_groupwise_timeout = MNULL; MrvlIEtypes_eapol_gwk_hsk_retries_t *tlv_groupwise_retries = MNULL; MrvlIEtypes_mgmt_ie_passthru_t *tlv_mgmt_ie_passthru = MNULL; MrvlIEtypes_2040_coex_enable_t *tlv_2040_coex_enable = MNULL; MrvlIEtypes_mac_filter_t *tlv_mac_filter = MNULL; MrvlIEtypes_channel_band_t *tlv_chan_band = MNULL; MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL; ChanScanParamSet_t *pscan_chan = MNULL; MrvlIEtypes_auth_type_t *tlv_auth_type = MNULL; MrvlIEtypes_encrypt_protocol_t *tlv_encrypt_protocol = MNULL; MrvlIEtypes_akmp_t *tlv_akmp = MNULL; MrvlIEtypes_pwk_cipher_t *tlv_pwk_cipher = MNULL; MrvlIEtypes_gwk_cipher_t *tlv_gwk_cipher = MNULL; MrvlIEtypes_rsn_replay_prot_t *tlv_rsn_prot = MNULL; MrvlIEtypes_passphrase_t *tlv_passphrase = MNULL; MrvlIEtypes_group_rekey_time_t *tlv_rekey_time = MNULL; MrvlIEtypes_wep_key_t *tlv_wep_key = MNULL; MrvlIETypes_HTCap_t *tlv_htcap = MNULL; MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = MNULL; t_u32 cmd_size = 0; t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 }; t_u16 i; t_u16 ac; ENTER(); if (pioctl_buf == MNULL) { LEAVE(); return MLAN_STATUS_FAILURE; } bss = (mlan_ds_bss *)pioctl_buf->pbuf; cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE); sys_config->action = wlan_cpu_to_le16(cmd_action); cmd_size = sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN; tlv = (t_u8 *)sys_config->tlv_buffer; if (memcmp (pmpriv->adapter, zero_mac, &bss->param.bss_config.mac_addr, MLAN_MAC_ADDR_LENGTH)) { tlv_mac = (MrvlIEtypes_MacAddr_t *)tlv; tlv_mac->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS); tlv_mac->header.len = wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH); memcpy(pmpriv->adapter, tlv_mac->mac, &bss->param.bss_config.mac_addr, MLAN_MAC_ADDR_LENGTH); cmd_size += sizeof(MrvlIEtypes_MacAddr_t); tlv += sizeof(MrvlIEtypes_MacAddr_t); } if (bss->param.bss_config.bandcfg.scanMode == SCAN_MODE_ACS) { /* ACS is not allowed when DFS repeater mode is on */ if (pmpriv->adapter->dfs_repeater) { PRINTM(MERROR, "ACS is not allowed when" "DFS repeater mode is on.\n"); return MLAN_STATUS_FAILURE; } } if (bss->param.bss_config.ssid.ssid_len) { tlv_ssid = (MrvlIEtypes_SsIdParamSet_t *)tlv; tlv_ssid->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID); tlv_ssid->header.len = wlan_cpu_to_le16((t_u16)bss->param.bss_config.ssid. ssid_len); memcpy(pmpriv->adapter, tlv_ssid->ssid, bss->param.bss_config.ssid.ssid, bss->param.bss_config.ssid.ssid_len); cmd_size += sizeof(MrvlIEtypesHeader_t) + bss->param.bss_config.ssid.ssid_len; tlv += sizeof(MrvlIEtypesHeader_t) + bss->param.bss_config.ssid.ssid_len; } if ((bss->param.bss_config.beacon_period >= MIN_BEACON_PERIOD) && (bss->param.bss_config.beacon_period <= MAX_BEACON_PERIOD)) { tlv_beacon_period = (MrvlIEtypes_beacon_period_t *)tlv; tlv_beacon_period->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD); tlv_beacon_period->header.len = wlan_cpu_to_le16(sizeof(t_u16)); tlv_beacon_period->beacon_period = wlan_cpu_to_le16(bss->param.bss_config.beacon_period); cmd_size += sizeof(MrvlIEtypes_beacon_period_t); tlv += sizeof(MrvlIEtypes_beacon_period_t); } if ((bss->param.bss_config.dtim_period >= MIN_DTIM_PERIOD) && (bss->param.bss_config.dtim_period <= MAX_DTIM_PERIOD)) { tlv_dtim_period = (MrvlIEtypes_dtim_period_t *)tlv; tlv_dtim_period->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD); tlv_dtim_period->header.len = wlan_cpu_to_le16(sizeof(t_u8)); tlv_dtim_period->dtim_period = bss->param.bss_config.dtim_period; cmd_size += sizeof(MrvlIEtypes_dtim_period_t); tlv += sizeof(MrvlIEtypes_dtim_period_t); } if (bss->param.bss_config.rates[0]) { tlv_rates = (MrvlIEtypes_RatesParamSet_t *)tlv; tlv_rates->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES); for (i = 0; i < MAX_DATA_RATES && bss->param.bss_config.rates[i]; i++) { tlv_rates->rates[i] = bss->param.bss_config.rates[i]; } tlv_rates->header.len = wlan_cpu_to_le16(i); cmd_size += sizeof(MrvlIEtypesHeader_t) + i; tlv += sizeof(MrvlIEtypesHeader_t) + i; } if (bss->param.bss_config.tx_data_rate <= DATA_RATE_54M) { tlv_txrate = (MrvlIEtypes_tx_rate_t *)tlv; tlv_txrate->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_TX_DATA_RATE); tlv_txrate->header.len = wlan_cpu_to_le16(sizeof(t_u16)); tlv_txrate->tx_data_rate = wlan_cpu_to_le16(bss->param.bss_config.tx_data_rate); cmd_size += sizeof(MrvlIEtypes_tx_rate_t); tlv += sizeof(MrvlIEtypes_tx_rate_t); } if (bss->param.bss_config.tx_beacon_rate <= DATA_RATE_54M) { tlv_txrate = (MrvlIEtypes_tx_rate_t *)tlv; tlv_txrate->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_TX_BEACON_RATE); tlv_txrate->header.len = wlan_cpu_to_le16(sizeof(t_u16)); tlv_txrate->tx_data_rate = wlan_cpu_to_le16(bss->param.bss_config.tx_beacon_rate); cmd_size += sizeof(MrvlIEtypes_tx_rate_t); tlv += sizeof(MrvlIEtypes_tx_rate_t); } if (bss->param.bss_config.mcbc_data_rate <= DATA_RATE_54M) { tlv_mcbc_rate = (MrvlIEtypes_mcbc_rate_t *)tlv; tlv_mcbc_rate->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_MCBC_DATA_RATE); tlv_mcbc_rate->header.len = wlan_cpu_to_le16(sizeof(t_u16)); tlv_mcbc_rate->mcbc_data_rate = wlan_cpu_to_le16(bss->param.bss_config.mcbc_data_rate); cmd_size += sizeof(MrvlIEtypes_mcbc_rate_t); tlv += sizeof(MrvlIEtypes_mcbc_rate_t); } if (bss->param.bss_config.tx_power_level <= MAX_TX_POWER) { tlv_tx_power = (MrvlIEtypes_tx_power_t *)tlv; tlv_tx_power->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_TX_POWER); tlv_tx_power->header.len = wlan_cpu_to_le16(sizeof(t_u8)); tlv_tx_power->tx_power = bss->param.bss_config.tx_power_level; cmd_size += sizeof(MrvlIEtypes_tx_power_t); tlv += sizeof(MrvlIEtypes_tx_power_t); } if (bss->param.bss_config.bcast_ssid_ctl <= MAX_BCAST_SSID_CTL) { tlv_bcast_ssid = (MrvlIEtypes_bcast_ssid_t *)tlv; tlv_bcast_ssid->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID_CTL); tlv_bcast_ssid->header.len = wlan_cpu_to_le16(sizeof(t_u8)); tlv_bcast_ssid->bcast_ssid_ctl = bss->param.bss_config.bcast_ssid_ctl; cmd_size += sizeof(MrvlIEtypes_bcast_ssid_t); tlv += sizeof(MrvlIEtypes_bcast_ssid_t); } if ((bss->param.bss_config.tx_antenna == ANTENNA_MODE_A) || (bss->param.bss_config.tx_antenna == ANTENNA_MODE_B)) { tlv_antenna = (MrvlIEtypes_antenna_mode_t *)tlv; tlv_antenna->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_ANTENNA_CTL); tlv_antenna->header.len = wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8)); tlv_antenna->which_antenna = TX_ANTENNA; tlv_antenna->antenna_mode = bss->param.bss_config.tx_antenna; cmd_size += sizeof(MrvlIEtypes_antenna_mode_t); tlv += sizeof(MrvlIEtypes_antenna_mode_t); } if ((bss->param.bss_config.rx_antenna == ANTENNA_MODE_A) || (bss->param.bss_config.rx_antenna == ANTENNA_MODE_B)) { tlv_antenna = (MrvlIEtypes_antenna_mode_t *)tlv; tlv_antenna->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_ANTENNA_CTL); tlv_antenna->header.len = wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8)); tlv_antenna->which_antenna = RX_ANTENNA; tlv_antenna->antenna_mode = bss->param.bss_config.rx_antenna; cmd_size += sizeof(MrvlIEtypes_antenna_mode_t); tlv += sizeof(MrvlIEtypes_antenna_mode_t); } if (bss->param.bss_config.pkt_forward_ctl <= MAX_PKT_FWD_CTRL) { tlv_pkt_forward = (MrvlIEtypes_pkt_forward_t *)tlv; tlv_pkt_forward->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_PKT_FWD_CTL); tlv_pkt_forward->header.len = wlan_cpu_to_le16(sizeof(t_u8)); tlv_pkt_forward->pkt_forward_ctl = bss->param.bss_config.pkt_forward_ctl; cmd_size += sizeof(MrvlIEtypes_pkt_forward_t); tlv += sizeof(MrvlIEtypes_pkt_forward_t); } if (bss->param.bss_config.max_sta_count <= MAX_STA_COUNT) { tlv_sta_count = (MrvlIEtypes_max_sta_count_t *)tlv; tlv_sta_count->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_MAX_STA_CNT); tlv_sta_count->header.len = wlan_cpu_to_le16(sizeof(t_u16)); tlv_sta_count->max_sta_count = wlan_cpu_to_le16(bss->param.bss_config.max_sta_count); cmd_size += sizeof(MrvlIEtypes_max_sta_count_t); tlv += sizeof(MrvlIEtypes_max_sta_count_t); } if (((bss->param.bss_config.sta_ageout_timer >= MIN_STAGE_OUT_TIME) && (bss->param.bss_config.sta_ageout_timer <= MAX_STAGE_OUT_TIME)) || (bss->param.bss_config.sta_ageout_timer == 0)) { tlv_sta_ageout = (MrvlIEtypes_sta_ageout_t *)tlv; tlv_sta_ageout->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_STA_AGEOUT_TIMER); tlv_sta_ageout->header.len = wlan_cpu_to_le16(sizeof(t_u32)); tlv_sta_ageout->sta_ageout_timer = wlan_cpu_to_le32(bss->param.bss_config. sta_ageout_timer); cmd_size += sizeof(MrvlIEtypes_sta_ageout_t); tlv += sizeof(MrvlIEtypes_sta_ageout_t); } if (((bss->param.bss_config.ps_sta_ageout_timer >= MIN_STAGE_OUT_TIME) && (bss->param.bss_config.ps_sta_ageout_timer <= MAX_STAGE_OUT_TIME)) || (bss->param.bss_config.ps_sta_ageout_timer == 0)) { tlv_ps_sta_ageout = (MrvlIEtypes_ps_sta_ageout_t *)tlv; tlv_ps_sta_ageout->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_PS_STA_AGEOUT_TIMER); tlv_ps_sta_ageout->header.len = wlan_cpu_to_le16(sizeof(t_u32)); tlv_ps_sta_ageout->ps_sta_ageout_timer = wlan_cpu_to_le32(bss->param.bss_config. ps_sta_ageout_timer); cmd_size += sizeof(MrvlIEtypes_ps_sta_ageout_t); tlv += sizeof(MrvlIEtypes_ps_sta_ageout_t); } if (bss->param.bss_config.rts_threshold <= MAX_RTS_THRESHOLD) { tlv_rts_threshold = (MrvlIEtypes_rts_threshold_t *)tlv; tlv_rts_threshold->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD); tlv_rts_threshold->header.len = wlan_cpu_to_le16(sizeof(t_u16)); tlv_rts_threshold->rts_threshold = wlan_cpu_to_le16(bss->param.bss_config.rts_threshold); cmd_size += sizeof(MrvlIEtypes_rts_threshold_t); tlv += sizeof(MrvlIEtypes_rts_threshold_t); } if ((bss->param.bss_config.frag_threshold >= MIN_FRAG_THRESHOLD) && (bss->param.bss_config.frag_threshold <= MAX_FRAG_THRESHOLD)) { tlv_frag_threshold = (MrvlIEtypes_frag_threshold_t *)tlv; tlv_frag_threshold->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD); tlv_frag_threshold->header.len = wlan_cpu_to_le16(sizeof(t_u16)); tlv_frag_threshold->frag_threshold = wlan_cpu_to_le16(bss->param.bss_config.frag_threshold); cmd_size += sizeof(MrvlIEtypes_frag_threshold_t); tlv += sizeof(MrvlIEtypes_frag_threshold_t); } if (bss->param.bss_config.retry_limit <= MAX_RETRY_LIMIT) { tlv_retry_limit = (MrvlIEtypes_retry_limit_t *)tlv; tlv_retry_limit->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT); tlv_retry_limit->header.len = wlan_cpu_to_le16(sizeof(t_u8)); tlv_retry_limit->retry_limit = (t_u8)bss->param.bss_config.retry_limit; cmd_size += sizeof(MrvlIEtypes_retry_limit_t); tlv += sizeof(MrvlIEtypes_retry_limit_t); } #ifdef DRV_EMBEDDED_AUTHENTICATOR if (IS_FW_SUPPORT_AUTHENTICATOR(pmpriv->adapter)) { #endif if (bss->param.bss_config.pairwise_update_timeout < (MAX_VALID_DWORD)) { tlv_pairwise_timeout = (MrvlIEtypes_eapol_pwk_hsk_timeout_t *)tlv; tlv_pairwise_timeout->header.type = wlan_cpu_to_le16 (TLV_TYPE_UAP_EAPOL_PWK_HSK_TIMEOUT); tlv_pairwise_timeout->header.len = wlan_cpu_to_le16(sizeof(t_u32)); tlv_pairwise_timeout->pairwise_update_timeout = wlan_cpu_to_le32(bss->param.bss_config. pairwise_update_timeout); cmd_size += sizeof(MrvlIEtypes_eapol_pwk_hsk_timeout_t); tlv += sizeof(MrvlIEtypes_eapol_pwk_hsk_timeout_t); } if (bss->param.bss_config.pwk_retries < (MAX_VALID_DWORD)) { tlv_pairwise_retries = (MrvlIEtypes_eapol_pwk_hsk_retries_t *)tlv; tlv_pairwise_retries->header.type = wlan_cpu_to_le16 (TLV_TYPE_UAP_EAPOL_PWK_HSK_RETRIES); tlv_pairwise_retries->header.len = wlan_cpu_to_le16(sizeof(t_u32)); tlv_pairwise_retries->pwk_retries = wlan_cpu_to_le32(bss->param.bss_config. pwk_retries); cmd_size += sizeof(MrvlIEtypes_eapol_pwk_hsk_retries_t); tlv += sizeof(MrvlIEtypes_eapol_pwk_hsk_retries_t); } if (bss->param.bss_config.groupwise_update_timeout < (MAX_VALID_DWORD)) { tlv_groupwise_timeout = (MrvlIEtypes_eapol_gwk_hsk_timeout_t *)tlv; tlv_groupwise_timeout->header.type = wlan_cpu_to_le16 (TLV_TYPE_UAP_EAPOL_GWK_HSK_TIMEOUT); tlv_groupwise_timeout->header.len = wlan_cpu_to_le16(sizeof(t_u32)); tlv_groupwise_timeout->groupwise_update_timeout = wlan_cpu_to_le32(bss->param.bss_config. groupwise_update_timeout); cmd_size += sizeof(MrvlIEtypes_eapol_gwk_hsk_timeout_t); tlv += sizeof(MrvlIEtypes_eapol_gwk_hsk_timeout_t); } if (bss->param.bss_config.gwk_retries < (MAX_VALID_DWORD)) { tlv_groupwise_retries = (MrvlIEtypes_eapol_gwk_hsk_retries_t *)tlv; tlv_groupwise_retries->header.type = wlan_cpu_to_le16 (TLV_TYPE_UAP_EAPOL_GWK_HSK_RETRIES); tlv_groupwise_retries->header.len = wlan_cpu_to_le16(sizeof(t_u32)); tlv_groupwise_retries->gwk_retries = wlan_cpu_to_le32(bss->param.bss_config. gwk_retries); cmd_size += sizeof(MrvlIEtypes_eapol_gwk_hsk_retries_t); tlv += sizeof(MrvlIEtypes_eapol_gwk_hsk_retries_t); } #ifdef DRV_EMBEDDED_AUTHENTICATOR } #endif if ((bss->param.bss_config.filter.filter_mode <= MAC_FILTER_MODE_BLOCK_MAC) && (bss->param.bss_config.filter.mac_count <= MAX_MAC_FILTER_NUM)) { tlv_mac_filter = (MrvlIEtypes_mac_filter_t *)tlv; tlv_mac_filter->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_STA_MAC_ADDR_FILTER); tlv_mac_filter->header.len = wlan_cpu_to_le16(2 + MLAN_MAC_ADDR_LENGTH * bss->param.bss_config.filter. mac_count); tlv_mac_filter->count = (t_u8)bss->param.bss_config.filter.mac_count; tlv_mac_filter->filter_mode = (t_u8)bss->param.bss_config.filter.filter_mode; memcpy(pmpriv->adapter, tlv_mac_filter->mac_address, (t_u8 *)bss->param.bss_config.filter.mac_list, MLAN_MAC_ADDR_LENGTH * bss->param.bss_config.filter.mac_count); cmd_size += sizeof(MrvlIEtypesHeader_t) + 2 + MLAN_MAC_ADDR_LENGTH * bss->param.bss_config.filter.mac_count; tlv += sizeof(MrvlIEtypesHeader_t) + 2 + MLAN_MAC_ADDR_LENGTH * bss->param.bss_config.filter.mac_count; } if (((bss->param.bss_config.bandcfg.scanMode == SCAN_MODE_MANUAL) && (bss->param.bss_config.channel > 0) && (bss->param.bss_config.channel <= MLAN_MAX_CHANNEL)) || (bss->param.bss_config.bandcfg.scanMode == SCAN_MODE_ACS)) { tlv_chan_band = (MrvlIEtypes_channel_band_t *)tlv; tlv_chan_band->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_CHAN_BAND_CONFIG); tlv_chan_band->header.len = wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8)); tlv_chan_band->bandcfg = bss->param.bss_config.bandcfg; tlv_chan_band->channel = bss->param.bss_config.channel; cmd_size += sizeof(MrvlIEtypes_channel_band_t); tlv += sizeof(MrvlIEtypes_channel_band_t); } if ((bss->param.bss_config.num_of_chan) && (bss->param.bss_config.num_of_chan <= MLAN_MAX_CHANNEL)) { tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv; tlv_chan_list->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST); tlv_chan_list->header.len = wlan_cpu_to_le16((t_u16) (sizeof(ChanScanParamSet_t) * bss->param.bss_config.num_of_chan)); pscan_chan = tlv_chan_list->chan_scan_param; for (i = 0; i < bss->param.bss_config.num_of_chan; i++) { pscan_chan->chan_number = bss->param.bss_config.chan_list[i].chan_number; pscan_chan->bandcfg = bss->param.bss_config.chan_list[i].bandcfg; pscan_chan++; } cmd_size += sizeof(tlv_chan_list->header) + (sizeof(ChanScanParamSet_t) * bss->param.bss_config.num_of_chan); tlv += sizeof(tlv_chan_list->header) + (sizeof(ChanScanParamSet_t) * bss->param.bss_config.num_of_chan); } if ((bss->param.bss_config.auth_mode <= MLAN_AUTH_MODE_SHARED) || (bss->param.bss_config.auth_mode == MLAN_AUTH_MODE_AUTO)) { tlv_auth_type = (MrvlIEtypes_auth_type_t *)tlv; tlv_auth_type->header.type = wlan_cpu_to_le16(TLV_TYPE_AUTH_TYPE); tlv_auth_type->header.len = wlan_cpu_to_le16(sizeof(t_u8)); tlv_auth_type->auth_type = (t_u8)bss->param.bss_config.auth_mode; cmd_size += sizeof(MrvlIEtypes_auth_type_t); tlv += sizeof(MrvlIEtypes_auth_type_t); } if (bss->param.bss_config.protocol) { tlv_encrypt_protocol = (MrvlIEtypes_encrypt_protocol_t *)tlv; tlv_encrypt_protocol->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_ENCRYPT_PROTOCOL); tlv_encrypt_protocol->header.len = wlan_cpu_to_le16(sizeof(t_u16)); tlv_encrypt_protocol->protocol = wlan_cpu_to_le16(bss->param.bss_config.protocol); cmd_size += sizeof(MrvlIEtypes_encrypt_protocol_t); tlv += sizeof(MrvlIEtypes_encrypt_protocol_t); } if ((bss->param.bss_config.protocol & PROTOCOL_WPA) || (bss->param.bss_config.protocol & PROTOCOL_WPA2) || (bss->param.bss_config.protocol & PROTOCOL_EAP)) { tlv_akmp = (MrvlIEtypes_akmp_t *)tlv; tlv_akmp->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_AKMP); tlv_akmp->key_mgmt = wlan_cpu_to_le16(bss->param.bss_config.key_mgmt); tlv_akmp->header.len = sizeof(t_u16); tlv_akmp->key_mgmt_operation = wlan_cpu_to_le16(bss->param.bss_config. key_mgmt_operation); tlv_akmp->header.len += sizeof(t_u16); tlv_akmp->header.len = wlan_cpu_to_le16(tlv_akmp->header.len); cmd_size += sizeof(MrvlIEtypes_akmp_t); tlv += sizeof(MrvlIEtypes_akmp_t); if (bss->param.bss_config.wpa_cfg. pairwise_cipher_wpa & VALID_CIPHER_BITMAP) { tlv_pwk_cipher = (MrvlIEtypes_pwk_cipher_t *)tlv; tlv_pwk_cipher->header.type = wlan_cpu_to_le16(TLV_TYPE_PWK_CIPHER); tlv_pwk_cipher->header.len = wlan_cpu_to_le16(sizeof(t_u16) + sizeof(t_u8) + sizeof(t_u8)); tlv_pwk_cipher->protocol = wlan_cpu_to_le16(PROTOCOL_WPA); tlv_pwk_cipher->pairwise_cipher = bss->param.bss_config.wpa_cfg. pairwise_cipher_wpa; cmd_size += sizeof(MrvlIEtypes_pwk_cipher_t); tlv += sizeof(MrvlIEtypes_pwk_cipher_t); } if (bss->param.bss_config.wpa_cfg. pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) { tlv_pwk_cipher = (MrvlIEtypes_pwk_cipher_t *)tlv; tlv_pwk_cipher->header.type = wlan_cpu_to_le16(TLV_TYPE_PWK_CIPHER); tlv_pwk_cipher->header.len = wlan_cpu_to_le16(sizeof(t_u16) + sizeof(t_u8) + sizeof(t_u8)); tlv_pwk_cipher->protocol = wlan_cpu_to_le16(PROTOCOL_WPA2); tlv_pwk_cipher->pairwise_cipher = bss->param.bss_config.wpa_cfg. pairwise_cipher_wpa2; cmd_size += sizeof(MrvlIEtypes_pwk_cipher_t); tlv += sizeof(MrvlIEtypes_pwk_cipher_t); } if (bss->param.bss_config.wpa_cfg. group_cipher & VALID_CIPHER_BITMAP) { tlv_gwk_cipher = (MrvlIEtypes_gwk_cipher_t *)tlv; tlv_gwk_cipher->header.type = wlan_cpu_to_le16(TLV_TYPE_GWK_CIPHER); tlv_gwk_cipher->header.len = wlan_cpu_to_le16(sizeof(t_u8) + sizeof(t_u8)); tlv_gwk_cipher->group_cipher = bss->param.bss_config.wpa_cfg.group_cipher; cmd_size += sizeof(MrvlIEtypes_gwk_cipher_t); tlv += sizeof(MrvlIEtypes_gwk_cipher_t); } if (bss->param.bss_config.wpa_cfg.rsn_protection <= MTRUE) { tlv_rsn_prot = (MrvlIEtypes_rsn_replay_prot_t *)tlv; tlv_rsn_prot->header.type = wlan_cpu_to_le16 (TLV_TYPE_UAP_RSN_REPLAY_PROTECT); tlv_rsn_prot->header.len = wlan_cpu_to_le16(sizeof(t_u8)); tlv_rsn_prot->rsn_replay_prot = bss->param.bss_config.wpa_cfg.rsn_protection; cmd_size += sizeof(MrvlIEtypes_rsn_replay_prot_t); tlv += sizeof(MrvlIEtypes_rsn_replay_prot_t); } #ifdef DRV_EMBEDDED_AUTHENTICATOR if (IS_FW_SUPPORT_AUTHENTICATOR(pmpriv->adapter)) { #endif if (bss->param.bss_config.wpa_cfg.length) { tlv_passphrase = (MrvlIEtypes_passphrase_t *)tlv; tlv_passphrase->header.type = wlan_cpu_to_le16 (TLV_TYPE_UAP_WPA_PASSPHRASE); tlv_passphrase->header.len = (t_u16)wlan_cpu_to_le16(bss->param. bss_config. wpa_cfg.length); memcpy(pmpriv->adapter, tlv_passphrase->passphrase, bss->param.bss_config.wpa_cfg.passphrase, bss->param.bss_config.wpa_cfg.length); cmd_size += sizeof(MrvlIEtypesHeader_t) + bss->param.bss_config.wpa_cfg.length; tlv += sizeof(MrvlIEtypesHeader_t) + bss->param.bss_config.wpa_cfg.length; } if (bss->param.bss_config.wpa_cfg.gk_rekey_time < MAX_GRP_TIMER) { tlv_rekey_time = (MrvlIEtypes_group_rekey_time_t *)tlv; tlv_rekey_time->header.type = wlan_cpu_to_le16 (TLV_TYPE_UAP_GRP_REKEY_TIME); tlv_rekey_time->header.len = wlan_cpu_to_le16(sizeof(t_u32)); tlv_rekey_time->gk_rekey_time = wlan_cpu_to_le32(bss->param.bss_config. wpa_cfg.gk_rekey_time); cmd_size += sizeof(MrvlIEtypes_group_rekey_time_t); tlv += sizeof(MrvlIEtypes_group_rekey_time_t); } #ifdef DRV_EMBEDDED_AUTHENTICATOR } #endif } else { if ((bss->param.bss_config.wep_cfg.key0.length) && ((bss->param.bss_config.wep_cfg.key0.length == 5) || (bss->param.bss_config.wep_cfg.key0.length == 10) || (bss->param.bss_config.wep_cfg.key0.length == 13) || (bss->param.bss_config.wep_cfg.key0.length == 26))) { tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv; tlv_wep_key->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_WEP_KEY); tlv_wep_key->header.len = wlan_cpu_to_le16(2 + bss->param.bss_config.wep_cfg. key0.length); tlv_wep_key->key_index = bss->param.bss_config.wep_cfg.key0.key_index; tlv_wep_key->is_default = bss->param.bss_config.wep_cfg.key0.is_default; memcpy(pmpriv->adapter, tlv_wep_key->key, bss->param.bss_config.wep_cfg.key0.key, bss->param.bss_config.wep_cfg.key0.length); cmd_size += sizeof(MrvlIEtypesHeader_t) + 2 + bss->param.bss_config.wep_cfg.key0.length; tlv += sizeof(MrvlIEtypesHeader_t) + 2 + bss->param.bss_config.wep_cfg.key0.length; } if ((bss->param.bss_config.wep_cfg.key1.length) && ((bss->param.bss_config.wep_cfg.key1.length == 5) || (bss->param.bss_config.wep_cfg.key1.length == 10) || (bss->param.bss_config.wep_cfg.key1.length == 13) || (bss->param.bss_config.wep_cfg.key1.length == 26))) { tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv; tlv_wep_key->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_WEP_KEY); tlv_wep_key->header.len = wlan_cpu_to_le16(2 + bss->param.bss_config.wep_cfg. key1.length); tlv_wep_key->key_index = bss->param.bss_config.wep_cfg.key1.key_index; tlv_wep_key->is_default = bss->param.bss_config.wep_cfg.key1.is_default; memcpy(pmpriv->adapter, tlv_wep_key->key, bss->param.bss_config.wep_cfg.key1.key, bss->param.bss_config.wep_cfg.key1.length); cmd_size += sizeof(MrvlIEtypesHeader_t) + 2 + bss->param.bss_config.wep_cfg.key1.length; tlv += sizeof(MrvlIEtypesHeader_t) + 2 + bss->param.bss_config.wep_cfg.key1.length; } if ((bss->param.bss_config.wep_cfg.key2.length) && ((bss->param.bss_config.wep_cfg.key2.length == 5) || (bss->param.bss_config.wep_cfg.key2.length == 10) || (bss->param.bss_config.wep_cfg.key2.length == 13) || (bss->param.bss_config.wep_cfg.key2.length == 26))) { tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv; tlv_wep_key->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_WEP_KEY); tlv_wep_key->header.len = wlan_cpu_to_le16(2 + bss->param.bss_config.wep_cfg. key2.length); tlv_wep_key->key_index = bss->param.bss_config.wep_cfg.key2.key_index; tlv_wep_key->is_default = bss->param.bss_config.wep_cfg.key2.is_default; memcpy(pmpriv->adapter, tlv_wep_key->key, bss->param.bss_config.wep_cfg.key2.key, bss->param.bss_config.wep_cfg.key2.length); cmd_size += sizeof(MrvlIEtypesHeader_t) + 2 + bss->param.bss_config.wep_cfg.key2.length; tlv += sizeof(MrvlIEtypesHeader_t) + 2 + bss->param.bss_config.wep_cfg.key2.length; } if ((bss->param.bss_config.wep_cfg.key3.length) && ((bss->param.bss_config.wep_cfg.key3.length == 5) || (bss->param.bss_config.wep_cfg.key3.length == 10) || (bss->param.bss_config.wep_cfg.key3.length == 13) || (bss->param.bss_config.wep_cfg.key3.length == 26))) { tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv; tlv_wep_key->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_WEP_KEY); tlv_wep_key->header.len = wlan_cpu_to_le16(2 + bss->param.bss_config.wep_cfg. key3.length); tlv_wep_key->key_index = bss->param.bss_config.wep_cfg.key3.key_index; tlv_wep_key->is_default = bss->param.bss_config.wep_cfg.key3.is_default; memcpy(pmpriv->adapter, tlv_wep_key->key, bss->param.bss_config.wep_cfg.key3.key, bss->param.bss_config.wep_cfg.key3.length); cmd_size += sizeof(MrvlIEtypesHeader_t) + 2 + bss->param.bss_config.wep_cfg.key3.length; tlv += sizeof(MrvlIEtypesHeader_t) + 2 + bss->param.bss_config.wep_cfg.key3.length; } } if ((bss->param.bss_config.ht_cap_info) ) { tlv_htcap = (MrvlIETypes_HTCap_t *)tlv; tlv_htcap->header.type = wlan_cpu_to_le16(HT_CAPABILITY); tlv_htcap->header.len = wlan_cpu_to_le16(sizeof(HTCap_t)); tlv_htcap->ht_cap.ht_cap_info = wlan_cpu_to_le16(bss->param.bss_config.ht_cap_info); tlv_htcap->ht_cap.ampdu_param = bss->param.bss_config.ampdu_param; memcpy(pmpriv->adapter, tlv_htcap->ht_cap.supported_mcs_set, bss->param.bss_config.supported_mcs_set, 16); tlv_htcap->ht_cap.ht_ext_cap = wlan_cpu_to_le16(bss->param.bss_config.ht_ext_cap); tlv_htcap->ht_cap.tx_bf_cap = wlan_cpu_to_le32(bss->param.bss_config.tx_bf_cap); tlv_htcap->ht_cap.asel = bss->param.bss_config.asel; cmd_size += sizeof(MrvlIETypes_HTCap_t); tlv += sizeof(MrvlIETypes_HTCap_t); } if (bss->param.bss_config.mgmt_ie_passthru_mask < (MAX_VALID_DWORD)) { tlv_mgmt_ie_passthru = (MrvlIEtypes_mgmt_ie_passthru_t *)tlv; tlv_mgmt_ie_passthru->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_MGMT_IE_PASSTHRU_MASK); tlv_mgmt_ie_passthru->header.len = wlan_cpu_to_le16(sizeof(t_u32)); /* keep copy in private data */ pmpriv->mgmt_frame_passthru_mask = bss->param.bss_config.mgmt_ie_passthru_mask; tlv_mgmt_ie_passthru->mgmt_ie_mask = wlan_cpu_to_le32(bss->param.bss_config. mgmt_ie_passthru_mask); cmd_size += sizeof(MrvlIEtypes_mgmt_ie_passthru_t); tlv += sizeof(MrvlIEtypes_mgmt_ie_passthru_t); } if (((bss->param.bss_config.enable_2040coex == 0) || (bss->param.bss_config.enable_2040coex == 1)) ) { tlv_2040_coex_enable = (MrvlIEtypes_2040_coex_enable_t *)tlv; tlv_2040_coex_enable->header.type = wlan_cpu_to_le16(TLV_TYPE_2040_BSS_COEX_CONTROL); tlv_2040_coex_enable->header.len = wlan_cpu_to_le16(sizeof(t_u8)); tlv_2040_coex_enable->enable_2040coex = bss->param.bss_config.enable_2040coex; cmd_size += sizeof(MrvlIEtypes_2040_coex_enable_t); tlv += sizeof(MrvlIEtypes_2040_coex_enable_t); } if (bss->param.bss_config.wmm_para.qos_info == 0x80 || bss->param.bss_config.wmm_para.qos_info == 0x00) { tlv_wmm_parameter = (MrvlIEtypes_wmm_parameter_t *)tlv; tlv_wmm_parameter->header.type = wlan_cpu_to_le16(TLV_TYPE_VENDOR_SPECIFIC_IE); tlv_wmm_parameter->header.len = wlan_cpu_to_le16(sizeof (bss->param.bss_config.wmm_para)); memcpy(pmpriv->adapter, tlv_wmm_parameter->wmm_para.ouitype, bss->param.bss_config.wmm_para.ouitype, sizeof(tlv_wmm_parameter->wmm_para.ouitype)); tlv_wmm_parameter->wmm_para.ouisubtype = bss->param.bss_config.wmm_para.ouisubtype; tlv_wmm_parameter->wmm_para.version = bss->param.bss_config.wmm_para.version; tlv_wmm_parameter->wmm_para.qos_info = bss->param.bss_config.wmm_para.qos_info; for (ac = 0; ac < 4; ac++) { tlv_wmm_parameter->wmm_para.ac_params[ac].aci_aifsn. aifsn = bss->param.bss_config.wmm_para.ac_params[ac]. aci_aifsn.aifsn; tlv_wmm_parameter->wmm_para.ac_params[ac].aci_aifsn. aci = bss->param.bss_config.wmm_para.ac_params[ac]. aci_aifsn.aci; tlv_wmm_parameter->wmm_para.ac_params[ac].ecw.ecw_max = bss->param.bss_config.wmm_para.ac_params[ac]. ecw.ecw_max; tlv_wmm_parameter->wmm_para.ac_params[ac].ecw.ecw_min = bss->param.bss_config.wmm_para.ac_params[ac]. ecw.ecw_min; tlv_wmm_parameter->wmm_para.ac_params[ac].tx_op_limit = wlan_cpu_to_le16(bss->param.bss_config.wmm_para. ac_params[ac].tx_op_limit); } cmd_size += sizeof(MrvlIEtypes_wmm_parameter_t); tlv += sizeof(MrvlIEtypes_wmm_parameter_t); } #ifdef DRV_EMBEDDED_AUTHENTICATOR if (!IS_FW_SUPPORT_AUTHENTICATOR(pmpriv->adapter)) AuthenticatorBssConfig(pmpriv->psapriv, (t_u8 *)&bss->param.bss_config, 0, 0, 0); #endif cmd->size = (t_u16)wlan_cpu_to_le16(cmd_size); PRINTM(MCMND, "AP config: cmd_size=%d\n", cmd_size); LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function prepares command of sys_config * * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @param cmd_action the action: GET or SET * @param pioctl_buf A pointer to mlan_ioctl_req structure * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status wlan_uap_cmd_sys_configure(pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action, IN pmlan_ioctl_req pioctl_buf, IN t_void *pdata_buf) { mlan_ds_bss *bss = MNULL; HostCmd_DS_SYS_CONFIG *sys_config = (HostCmd_DS_SYS_CONFIG *)&cmd->params.sys_config; MrvlIEtypes_MacAddr_t *mac_tlv = MNULL; MrvlIEtypes_channel_band_t *pdat_tlv_cb = MNULL; MrvlIEtypes_beacon_period_t *bcn_pd_tlv = MNULL, *pdat_tlv_bcnpd = MNULL; MrvlIEtypes_dtim_period_t *dtim_pd_tlv = MNULL, *pdat_tlv_dtimpd = MNULL; MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = MNULL; MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL; ChanScanParamSet_t *pscan_chan = MNULL; MrvlIEtypes_channel_band_t *chan_band_tlv = MNULL; MrvlIEtypes_chan_bw_oper_t *poper_class_tlv = MNULL; t_u8 length = 0; t_u8 curr_oper_class = 1; t_u8 *oper_class_ie = (t_u8 *)sys_config->tlv_buffer; t_u16 i = 0; t_u8 ac = 0; mlan_ds_misc_custom_ie *cust_ie = MNULL; mlan_ds_misc_cfg *misc = MNULL; MrvlIEtypesHeader_t *ie_header = (MrvlIEtypesHeader_t *)sys_config->tlv_buffer; MrvlIEtypesHeader_t *pdata_header = (MrvlIEtypesHeader_t *)pdata_buf; t_u8 *ie = (t_u8 *)sys_config->tlv_buffer + sizeof(MrvlIEtypesHeader_t); t_u16 req_len = 0, travel_len = 0; custom_ie *cptr = MNULL; mlan_status ret = MLAN_STATUS_SUCCESS; ENTER(); cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE); sys_config->action = wlan_cpu_to_le16(cmd_action); cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN); if (pioctl_buf == MNULL) { if (pdata_buf) { switch (pdata_header->type) { case TLV_TYPE_UAP_CHAN_BAND_CONFIG: pdat_tlv_cb = (MrvlIEtypes_channel_band_t *)pdata_buf; chan_band_tlv = (MrvlIEtypes_channel_band_t *) sys_config->tlv_buffer; cmd->size = wlan_cpu_to_le16(sizeof (HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + sizeof (MrvlIEtypes_channel_band_t)); chan_band_tlv->header.type = wlan_cpu_to_le16 (TLV_TYPE_UAP_CHAN_BAND_CONFIG); chan_band_tlv->header.len = wlan_cpu_to_le16(sizeof (MrvlIEtypes_channel_band_t) - sizeof (MrvlIEtypesHeader_t)); if (cmd_action) { chan_band_tlv->bandcfg = pdat_tlv_cb->bandcfg; chan_band_tlv->channel = pdat_tlv_cb->channel; } ret = MLAN_STATUS_SUCCESS; break; case TLV_TYPE_UAP_BEACON_PERIOD: pdat_tlv_bcnpd = (MrvlIEtypes_beacon_period_t *) pdata_buf; bcn_pd_tlv = (MrvlIEtypes_beacon_period_t *) sys_config->tlv_buffer; cmd->size = sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + sizeof(MrvlIEtypes_beacon_period_t); bcn_pd_tlv->header.type = wlan_cpu_to_le16 (TLV_TYPE_UAP_BEACON_PERIOD); bcn_pd_tlv->header.len = wlan_cpu_to_le16(sizeof (MrvlIEtypes_beacon_period_t) - sizeof (MrvlIEtypesHeader_t)); if (cmd_action) { bcn_pd_tlv->beacon_period = wlan_cpu_to_le16 (pdat_tlv_bcnpd->beacon_period); } /* Add TLV_UAP_DTIM_PERIOD if it follws in pdata_buf */ pdat_tlv_dtimpd = (MrvlIEtypes_dtim_period_t *)(((t_u8 *)pdata_buf) + sizeof (MrvlIEtypes_beacon_period_t)); if (TLV_TYPE_UAP_DTIM_PERIOD == pdat_tlv_dtimpd->header.type) { dtim_pd_tlv = (MrvlIEtypes_dtim_period_t *)(sys_config->tlv_buffer + sizeof (MrvlIEtypes_beacon_period_t)); cmd->size += sizeof (MrvlIEtypes_dtim_period_t); dtim_pd_tlv->header.type = wlan_cpu_to_le16 (TLV_TYPE_UAP_DTIM_PERIOD); dtim_pd_tlv->header.len = wlan_cpu_to_le16(sizeof (MrvlIEtypes_dtim_period_t) - sizeof (MrvlIEtypesHeader_t)); if (cmd_action) { dtim_pd_tlv->dtim_period = pdat_tlv_dtimpd-> dtim_period; } } /* Finalize cmd size */ cmd->size = wlan_cpu_to_le16(cmd->size); ret = MLAN_STATUS_SUCCESS; break; case TLV_TYPE_MGMT_IE: cust_ie = (mlan_ds_misc_custom_ie *)pdata_buf; cmd->size = wlan_cpu_to_le16(sizeof (HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + sizeof (MrvlIEtypesHeader_t) + cust_ie->len); ie_header->type = wlan_cpu_to_le16(TLV_TYPE_MGMT_IE); ie_header->len = wlan_cpu_to_le16(cust_ie->len); if (ie && cust_ie->ie_data_list) { req_len = cust_ie->len; travel_len = 0; /* conversion for index, mask, len */ if (req_len == sizeof(t_u16)) cust_ie->ie_data_list[0]. ie_index = wlan_cpu_to_le16 (cust_ie-> ie_data_list[0]. ie_index); while (req_len > sizeof(t_u16)) { cptr = (custom_ie *)(((t_u8 *)&cust_ie-> ie_data_list) + travel_len); travel_len += cptr->ie_length + sizeof(custom_ie) - MAX_IE_SIZE; req_len -= cptr->ie_length + sizeof(custom_ie) - MAX_IE_SIZE; cptr->ie_index = wlan_cpu_to_le16(cptr-> ie_index); cptr->mgmt_subtype_mask = wlan_cpu_to_le16(cptr-> mgmt_subtype_mask); cptr->ie_length = wlan_cpu_to_le16(cptr-> ie_length); } memcpy(pmpriv->adapter, ie, cust_ie->ie_data_list, cust_ie->len); } break; case REGULATORY_CLASS: poper_class_tlv = (MrvlIEtypes_chan_bw_oper_t *) pdata_buf; ret = wlan_get_curr_oper_class(pmpriv, poper_class_tlv-> ds_chan_bw_oper. channel, poper_class_tlv-> ds_chan_bw_oper. bandwidth, &curr_oper_class); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Can not get current oper class! bandwidth = %d, channel = %d\n", poper_class_tlv->ds_chan_bw_oper. bandwidth, poper_class_tlv->ds_chan_bw_oper. channel); } if (cmd_action == HostCmd_ACT_GEN_SET) length = wlan_add_supported_oper_class_ie(pmpriv, &oper_class_ie, curr_oper_class); cmd->size = wlan_cpu_to_le16(sizeof (HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + length); break; default: PRINTM(MERROR, "Wrong data, or missing TLV_TYPE 0x%04x handler.\n", *(t_u16 *)pdata_buf); break; } goto done; } else { mac_tlv = (MrvlIEtypes_MacAddr_t *)sys_config->tlv_buffer; cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + sizeof(MrvlIEtypes_MacAddr_t)); mac_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS); mac_tlv->header.len = wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH); ret = MLAN_STATUS_SUCCESS; goto done; } } if (pioctl_buf->req_id == MLAN_IOCTL_BSS) { bss = (mlan_ds_bss *)pioctl_buf->pbuf; if (bss->sub_command == MLAN_OID_BSS_MAC_ADDR) { mac_tlv = (MrvlIEtypes_MacAddr_t *)sys_config->tlv_buffer; cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + sizeof(MrvlIEtypes_MacAddr_t)); mac_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS); mac_tlv->header.len = wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH); if (cmd_action == HostCmd_ACT_GEN_SET) memcpy(pmpriv->adapter, mac_tlv->mac, &bss->param.mac_addr, MLAN_MAC_ADDR_LENGTH); } else if (bss->sub_command == MLAN_OID_UAP_CFG_WMM_PARAM) { tlv_wmm_parameter = (MrvlIEtypes_wmm_parameter_t *)sys_config-> tlv_buffer; cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + sizeof (MrvlIEtypes_wmm_parameter_t)); tlv_wmm_parameter->header.type = wlan_cpu_to_le16(TLV_TYPE_AP_WMM_PARAM); tlv_wmm_parameter->header.len = wlan_cpu_to_le16(sizeof (bss->param.ap_wmm_para)); if (cmd_action == HostCmd_ACT_GEN_SET) { for (ac = 0; ac < 4; ac++) { tlv_wmm_parameter->wmm_para. ac_params[ac].aci_aifsn.aifsn = bss->param.ap_wmm_para. ac_params[ac].aci_aifsn.aifsn; tlv_wmm_parameter->wmm_para. ac_params[ac].aci_aifsn.aci = bss->param.ap_wmm_para. ac_params[ac].aci_aifsn.aci; tlv_wmm_parameter->wmm_para. ac_params[ac].ecw.ecw_max = bss->param.ap_wmm_para. ac_params[ac].ecw.ecw_max; tlv_wmm_parameter->wmm_para. ac_params[ac].ecw.ecw_min = bss->param.ap_wmm_para. ac_params[ac].ecw.ecw_min; tlv_wmm_parameter->wmm_para. ac_params[ac].tx_op_limit = wlan_cpu_to_le16(bss->param. ap_wmm_para. ac_params[ac]. tx_op_limit); } } } else if (bss->sub_command == MLAN_OID_UAP_SCAN_CHANNELS) { tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)sys_config-> tlv_buffer; tlv_chan_list->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST); if (bss->param.ap_scan_channels.num_of_chan && bss->param.ap_scan_channels.num_of_chan <= MLAN_MAX_CHANNEL) { cmd->size = wlan_cpu_to_le16(sizeof (HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + sizeof(tlv_chan_list-> header) + sizeof (ChanScanParamSet_t) * bss->param. ap_scan_channels. num_of_chan); tlv_chan_list->header.len = wlan_cpu_to_le16((t_u16) (sizeof (ChanScanParamSet_t) * bss->param. ap_scan_channels. num_of_chan)); pscan_chan = tlv_chan_list->chan_scan_param; for (i = 0; i < bss->param.ap_scan_channels.num_of_chan; i++) { pscan_chan->chan_number = bss->param.ap_scan_channels. chan_list[i].chan_number; pscan_chan->bandcfg = bss->param.ap_scan_channels. chan_list[i].bandcfg; pscan_chan++; } PRINTM(MCMND, "Set AP scan channel list = %d\n", bss->param.ap_scan_channels.num_of_chan); } else { tlv_chan_list->header.len = wlan_cpu_to_le16((t_u16) (sizeof (ChanScanParamSet_t) * MLAN_MAX_CHANNEL)); cmd->size = wlan_cpu_to_le16(sizeof (HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + sizeof (MrvlIEtypes_ChanListParamSet_t) + sizeof (ChanScanParamSet_t) * MLAN_MAX_CHANNEL); } } else if (bss->sub_command == MLAN_OID_UAP_CHANNEL) { chan_band_tlv = (MrvlIEtypes_channel_band_t *)sys_config-> tlv_buffer; cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + sizeof (MrvlIEtypes_channel_band_t)); chan_band_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_CHAN_BAND_CONFIG); chan_band_tlv->header.len = wlan_cpu_to_le16(sizeof (MrvlIEtypes_channel_band_t) - sizeof(MrvlIEtypesHeader_t)); if (cmd_action == HostCmd_ACT_GEN_SET) { chan_band_tlv->bandcfg = bss->param.ap_channel.bandcfg; chan_band_tlv->channel = bss->param.ap_channel.channel; PRINTM(MCMND, "Set AP channel, band=%d, channel=%d\n", bss->param.ap_channel.bandcfg.chanBand, bss->param.ap_channel.channel); } } else if ((bss->sub_command == MLAN_OID_UAP_BSS_CONFIG) && (cmd_action == HostCmd_ACT_GEN_SET)) { ret = wlan_uap_cmd_ap_config(pmpriv, cmd, cmd_action, pioctl_buf); goto done; } } else if (pioctl_buf->req_id == MLAN_IOCTL_MISC_CFG) { misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf; if ((misc->sub_command == MLAN_OID_MISC_GEN_IE) && (misc->param.gen_ie.type == MLAN_IE_TYPE_GEN_IE) ) { cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + sizeof(MrvlIEtypesHeader_t) + misc->param.gen_ie.len); ie_header->type = wlan_cpu_to_le16(TLV_TYPE_WAPI_IE); ie_header->len = wlan_cpu_to_le16(misc->param.gen_ie.len); if (cmd_action == HostCmd_ACT_GEN_SET) memcpy(pmpriv->adapter, ie, misc->param.gen_ie.ie_data, misc->param.gen_ie.len); } if ((misc->sub_command == MLAN_OID_MISC_CUSTOM_IE) && (misc->param.cust_ie.type == TLV_TYPE_MGMT_IE)) { cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + sizeof(MrvlIEtypesHeader_t) + misc->param.cust_ie.len); ie_header->type = wlan_cpu_to_le16(TLV_TYPE_MGMT_IE); ie_header->len = wlan_cpu_to_le16(misc->param.cust_ie.len); if (ie && misc->param.cust_ie.ie_data_list) { req_len = misc->param.cust_ie.len; travel_len = 0; /* conversion for index, mask, len */ if (req_len == sizeof(t_u16)) misc->param.cust_ie.ie_data_list[0]. ie_index = wlan_cpu_to_le16(misc->param. cust_ie. ie_data_list [0].ie_index); while (req_len > sizeof(t_u16)) { cptr = (custom_ie *)(((t_u8 *)&misc->param. cust_ie.ie_data_list) + travel_len); travel_len += cptr->ie_length + sizeof(custom_ie) - MAX_IE_SIZE; req_len -= cptr->ie_length + sizeof(custom_ie) - MAX_IE_SIZE; cptr->ie_index = wlan_cpu_to_le16(cptr-> ie_index); cptr->mgmt_subtype_mask = wlan_cpu_to_le16(cptr-> mgmt_subtype_mask); cptr->ie_length = wlan_cpu_to_le16(cptr-> ie_length); } if (misc->param.cust_ie.len) memcpy(pmpriv->adapter, ie, misc->param.cust_ie.ie_data_list, misc->param.cust_ie.len); } } } done: LEAVE(); return ret; } /** * @brief This function handles command resp for get uap settings * * @param pmpriv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @param pioctl_buf A pointer to mlan_ioctl_req structure * * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_ret_cmd_ap_config(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf) { HostCmd_DS_SYS_CONFIG *sys_config = (HostCmd_DS_SYS_CONFIG *)&resp->params.sys_config; mlan_ds_bss *bss = MNULL; MrvlIEtypesHeader_t *tlv = MNULL; t_u16 tlv_buf_left = 0; t_u16 tlv_type = 0; t_u16 tlv_len = 0; MrvlIEtypes_MacAddr_t *tlv_mac = MNULL; MrvlIEtypes_SsIdParamSet_t *tlv_ssid = MNULL; MrvlIEtypes_beacon_period_t *tlv_beacon_period = MNULL; MrvlIEtypes_dtim_period_t *tlv_dtim_period = MNULL; MrvlIEtypes_RatesParamSet_t *tlv_rates = MNULL; MrvlIEtypes_tx_rate_t *tlv_txrate = MNULL; MrvlIEtypes_mcbc_rate_t *tlv_mcbc_rate = MNULL; MrvlIEtypes_tx_power_t *tlv_tx_power = MNULL; MrvlIEtypes_bcast_ssid_t *tlv_bcast_ssid = MNULL; MrvlIEtypes_antenna_mode_t *tlv_antenna = MNULL; MrvlIEtypes_pkt_forward_t *tlv_pkt_forward = MNULL; MrvlIEtypes_max_sta_count_t *tlv_sta_count = MNULL; MrvlIEtypes_sta_ageout_t *tlv_sta_ageout = MNULL; MrvlIEtypes_ps_sta_ageout_t *tlv_ps_sta_ageout = MNULL; MrvlIEtypes_rts_threshold_t *tlv_rts_threshold = MNULL; MrvlIEtypes_frag_threshold_t *tlv_frag_threshold = MNULL; MrvlIEtypes_retry_limit_t *tlv_retry_limit = MNULL; MrvlIEtypes_eapol_pwk_hsk_timeout_t *tlv_pairwise_timeout = MNULL; MrvlIEtypes_eapol_pwk_hsk_retries_t *tlv_pairwise_retries = MNULL; MrvlIEtypes_eapol_gwk_hsk_timeout_t *tlv_groupwise_timeout = MNULL; MrvlIEtypes_eapol_gwk_hsk_retries_t *tlv_groupwise_retries = MNULL; MrvlIEtypes_mgmt_ie_passthru_t *tlv_mgmt_ie_passthru = MNULL; MrvlIEtypes_2040_coex_enable_t *tlv_2040_coex_enable = MNULL; MrvlIEtypes_mac_filter_t *tlv_mac_filter = MNULL; MrvlIEtypes_channel_band_t *tlv_chan_band = MNULL; MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL; ChanScanParamSet_t *pscan_chan = MNULL; MrvlIEtypes_auth_type_t *tlv_auth_type = MNULL; MrvlIEtypes_encrypt_protocol_t *tlv_encrypt_protocol = MNULL; MrvlIEtypes_akmp_t *tlv_akmp = MNULL; MrvlIEtypes_pwk_cipher_t *tlv_pwk_cipher = MNULL; MrvlIEtypes_gwk_cipher_t *tlv_gwk_cipher = MNULL; MrvlIEtypes_rsn_replay_prot_t *tlv_rsn_prot = MNULL; MrvlIEtypes_passphrase_t *tlv_passphrase = MNULL; #ifdef WIFI_DIRECT_SUPPORT MrvlIEtypes_psk_t *tlv_psk = MNULL; #endif /* WIFI_DIRECT_SUPPORT */ MrvlIEtypes_group_rekey_time_t *tlv_rekey_time = MNULL; MrvlIEtypes_wep_key_t *tlv_wep_key = MNULL; MrvlIEtypes_preamble_t *tlv_preamble = MNULL; MrvlIEtypes_bss_status_t *tlv_bss_status = MNULL; MrvlIETypes_HTCap_t *tlv_htcap = MNULL; MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = MNULL; wep_key *pkey = MNULL; t_u16 i; t_u16 ac; ENTER(); bss = (mlan_ds_bss *)pioctl_buf->pbuf; tlv = (MrvlIEtypesHeader_t *)sys_config->tlv_buffer; tlv_buf_left = resp->size - (sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN); while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) { tlv_type = wlan_le16_to_cpu(tlv->type); tlv_len = wlan_le16_to_cpu(tlv->len); if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) { PRINTM(MERROR, "Error processing uAP sys config TLVs, bytes left < TLV length\n"); break; } switch (tlv_type) { case TLV_TYPE_UAP_MAC_ADDRESS: tlv_mac = (MrvlIEtypes_MacAddr_t *)tlv; memcpy(pmpriv->adapter, &bss->param.bss_config.mac_addr, tlv_mac->mac, MLAN_MAC_ADDR_LENGTH); break; case TLV_TYPE_SSID: tlv_ssid = (MrvlIEtypes_SsIdParamSet_t *)tlv; bss->param.bss_config.ssid.ssid_len = MIN(MLAN_MAX_SSID_LENGTH, tlv_len); memcpy(pmpriv->adapter, bss->param.bss_config.ssid.ssid, tlv_ssid->ssid, MIN(MLAN_MAX_SSID_LENGTH, tlv_len)); break; case TLV_TYPE_UAP_BEACON_PERIOD: tlv_beacon_period = (MrvlIEtypes_beacon_period_t *)tlv; bss->param.bss_config.beacon_period = wlan_le16_to_cpu(tlv_beacon_period-> beacon_period); pmpriv->uap_state_chan_cb.beacon_period = wlan_le16_to_cpu(tlv_beacon_period-> beacon_period); break; case TLV_TYPE_UAP_DTIM_PERIOD: tlv_dtim_period = (MrvlIEtypes_dtim_period_t *)tlv; bss->param.bss_config.dtim_period = tlv_dtim_period->dtim_period; pmpriv->uap_state_chan_cb.dtim_period = tlv_dtim_period->dtim_period; break; case TLV_TYPE_RATES: tlv_rates = (MrvlIEtypes_RatesParamSet_t *)tlv; memcpy(pmpriv->adapter, bss->param.bss_config.rates, tlv_rates->rates, MIN(MAX_DATA_RATES, tlv_len)); break; case TLV_TYPE_UAP_TX_DATA_RATE: tlv_txrate = (MrvlIEtypes_tx_rate_t *)tlv; bss->param.bss_config.tx_data_rate = wlan_le16_to_cpu(tlv_txrate->tx_data_rate); break; case TLV_TYPE_UAP_TX_BEACON_RATE: tlv_txrate = (MrvlIEtypes_tx_rate_t *)tlv; bss->param.bss_config.tx_beacon_rate = wlan_le16_to_cpu(tlv_txrate->tx_data_rate); break; case TLV_TYPE_UAP_MCBC_DATA_RATE: tlv_mcbc_rate = (MrvlIEtypes_mcbc_rate_t *)tlv; bss->param.bss_config.mcbc_data_rate = wlan_le16_to_cpu(tlv_mcbc_rate->mcbc_data_rate); break; case TLV_TYPE_UAP_TX_POWER: tlv_tx_power = (MrvlIEtypes_tx_power_t *)tlv; bss->param.bss_config.tx_power_level = tlv_tx_power->tx_power; break; case TLV_TYPE_UAP_BCAST_SSID_CTL: tlv_bcast_ssid = (MrvlIEtypes_bcast_ssid_t *)tlv; bss->param.bss_config.bcast_ssid_ctl = tlv_bcast_ssid->bcast_ssid_ctl; break; case TLV_TYPE_UAP_ANTENNA_CTL: tlv_antenna = (MrvlIEtypes_antenna_mode_t *)tlv; if (tlv_antenna->which_antenna == TX_ANTENNA) bss->param.bss_config.tx_antenna = tlv_antenna->antenna_mode; else if (tlv_antenna->which_antenna == RX_ANTENNA) bss->param.bss_config.rx_antenna = tlv_antenna->antenna_mode; break; case TLV_TYPE_UAP_PKT_FWD_CTL: tlv_pkt_forward = (MrvlIEtypes_pkt_forward_t *)tlv; bss->param.bss_config.pkt_forward_ctl = tlv_pkt_forward->pkt_forward_ctl; break; case TLV_TYPE_UAP_MAX_STA_CNT: tlv_sta_count = (MrvlIEtypes_max_sta_count_t *)tlv; bss->param.bss_config.max_sta_count = wlan_le16_to_cpu(tlv_sta_count->max_sta_count); break; case TLV_TYPE_UAP_STA_AGEOUT_TIMER: tlv_sta_ageout = (MrvlIEtypes_sta_ageout_t *)tlv; bss->param.bss_config.sta_ageout_timer = wlan_le32_to_cpu(tlv_sta_ageout-> sta_ageout_timer); break; case TLV_TYPE_UAP_PS_STA_AGEOUT_TIMER: tlv_ps_sta_ageout = (MrvlIEtypes_ps_sta_ageout_t *)tlv; bss->param.bss_config.ps_sta_ageout_timer = wlan_le32_to_cpu(tlv_ps_sta_ageout-> ps_sta_ageout_timer); break; case TLV_TYPE_UAP_RTS_THRESHOLD: tlv_rts_threshold = (MrvlIEtypes_rts_threshold_t *)tlv; bss->param.bss_config.rts_threshold = wlan_le16_to_cpu(tlv_rts_threshold-> rts_threshold); break; case TLV_TYPE_UAP_FRAG_THRESHOLD: tlv_frag_threshold = (MrvlIEtypes_frag_threshold_t *)tlv; bss->param.bss_config.frag_threshold = wlan_le16_to_cpu(tlv_frag_threshold-> frag_threshold); break; case TLV_TYPE_UAP_RETRY_LIMIT: tlv_retry_limit = (MrvlIEtypes_retry_limit_t *)tlv; bss->param.bss_config.retry_limit = tlv_retry_limit->retry_limit; break; case TLV_TYPE_UAP_EAPOL_PWK_HSK_TIMEOUT: tlv_pairwise_timeout = (MrvlIEtypes_eapol_pwk_hsk_timeout_t *)tlv; bss->param.bss_config.pairwise_update_timeout = wlan_le32_to_cpu(tlv_pairwise_timeout-> pairwise_update_timeout); break; case TLV_TYPE_UAP_EAPOL_PWK_HSK_RETRIES: tlv_pairwise_retries = (MrvlIEtypes_eapol_pwk_hsk_retries_t *)tlv; bss->param.bss_config.pwk_retries = wlan_le32_to_cpu(tlv_pairwise_retries-> pwk_retries); break; case TLV_TYPE_UAP_EAPOL_GWK_HSK_TIMEOUT: tlv_groupwise_timeout = (MrvlIEtypes_eapol_gwk_hsk_timeout_t *)tlv; bss->param.bss_config.groupwise_update_timeout = wlan_le32_to_cpu(tlv_groupwise_timeout-> groupwise_update_timeout); break; case TLV_TYPE_UAP_EAPOL_GWK_HSK_RETRIES: tlv_groupwise_retries = (MrvlIEtypes_eapol_gwk_hsk_retries_t *)tlv; bss->param.bss_config.gwk_retries = wlan_le32_to_cpu(tlv_groupwise_retries-> gwk_retries); break; case TLV_TYPE_UAP_MGMT_IE_PASSTHRU_MASK: tlv_mgmt_ie_passthru = (MrvlIEtypes_mgmt_ie_passthru_t *)tlv; bss->param.bss_config.mgmt_ie_passthru_mask = wlan_le32_to_cpu(tlv_mgmt_ie_passthru-> mgmt_ie_mask); break; case TLV_TYPE_2040_BSS_COEX_CONTROL: tlv_2040_coex_enable = (MrvlIEtypes_2040_coex_enable_t *)tlv; bss->param.bss_config.enable_2040coex = tlv_2040_coex_enable->enable_2040coex; break; case TLV_TYPE_UAP_STA_MAC_ADDR_FILTER: tlv_mac_filter = (MrvlIEtypes_mac_filter_t *)tlv; bss->param.bss_config.filter.mac_count = MIN(MAX_MAC_FILTER_NUM, tlv_mac_filter->count); bss->param.bss_config.filter.filter_mode = tlv_mac_filter->filter_mode; memcpy(pmpriv->adapter, (t_u8 *)bss->param.bss_config.filter.mac_list, tlv_mac_filter->mac_address, MLAN_MAC_ADDR_LENGTH * bss->param.bss_config.filter.mac_count); break; case TLV_TYPE_UAP_CHAN_BAND_CONFIG: tlv_chan_band = (MrvlIEtypes_channel_band_t *)tlv; bss->param.bss_config.bandcfg = tlv_chan_band->bandcfg; bss->param.bss_config.channel = tlv_chan_band->channel; pmpriv->uap_state_chan_cb.bandcfg = tlv_chan_band->bandcfg; pmpriv->uap_state_chan_cb.channel = tlv_chan_band->channel; break; case TLV_TYPE_CHANLIST: tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv; bss->param.bss_config.num_of_chan = tlv_len / sizeof(ChanScanParamSet_t); pscan_chan = tlv_chan_list->chan_scan_param; for (i = 0; i < bss->param.bss_config.num_of_chan; i++) { bss->param.bss_config.chan_list[i].chan_number = pscan_chan->chan_number; bss->param.bss_config.chan_list[i].bandcfg = pscan_chan->bandcfg; pscan_chan++; } break; case TLV_TYPE_AUTH_TYPE: tlv_auth_type = (MrvlIEtypes_auth_type_t *)tlv; bss->param.bss_config.auth_mode = tlv_auth_type->auth_type; break; case TLV_TYPE_UAP_ENCRYPT_PROTOCOL: tlv_encrypt_protocol = (MrvlIEtypes_encrypt_protocol_t *)tlv; bss->param.bss_config.protocol = wlan_le16_to_cpu(tlv_encrypt_protocol-> protocol); break; case TLV_TYPE_UAP_AKMP: tlv_akmp = (MrvlIEtypes_akmp_t *)tlv; bss->param.bss_config.key_mgmt = wlan_le16_to_cpu(tlv_akmp->key_mgmt); if (tlv_len > sizeof(t_u16)) bss->param.bss_config.key_mgmt_operation = wlan_le16_to_cpu(tlv_akmp-> key_mgmt_operation); break; case TLV_TYPE_PWK_CIPHER: tlv_pwk_cipher = (MrvlIEtypes_pwk_cipher_t *)tlv; if (wlan_le16_to_cpu(tlv_pwk_cipher->protocol) & PROTOCOL_WPA) bss->param.bss_config.wpa_cfg. pairwise_cipher_wpa = tlv_pwk_cipher->pairwise_cipher; if (wlan_le16_to_cpu(tlv_pwk_cipher->protocol) & PROTOCOL_WPA2) bss->param.bss_config.wpa_cfg. pairwise_cipher_wpa2 = tlv_pwk_cipher->pairwise_cipher; break; case TLV_TYPE_GWK_CIPHER: tlv_gwk_cipher = (MrvlIEtypes_gwk_cipher_t *)tlv; bss->param.bss_config.wpa_cfg.group_cipher = tlv_gwk_cipher->group_cipher; break; case TLV_TYPE_UAP_RSN_REPLAY_PROTECT: tlv_rsn_prot = (MrvlIEtypes_rsn_replay_prot_t *)tlv; bss->param.bss_config.wpa_cfg.rsn_protection = tlv_rsn_prot->rsn_replay_prot; break; case TLV_TYPE_UAP_WPA_PASSPHRASE: tlv_passphrase = (MrvlIEtypes_passphrase_t *)tlv; bss->param.bss_config.wpa_cfg.length = MIN(MLAN_PMK_HEXSTR_LENGTH, tlv_len); memcpy(pmpriv->adapter, bss->param.bss_config.wpa_cfg.passphrase, tlv_passphrase->passphrase, bss->param.bss_config.wpa_cfg.length); break; #ifdef WIFI_DIRECT_SUPPORT case TLV_TYPE_UAP_PSK: tlv_psk = (MrvlIEtypes_psk_t *)tlv; memcpy(pmpriv->adapter, bss->param.bss_config.psk, tlv_psk->psk, MIN(MLAN_MAX_KEY_LENGTH, tlv_len)); break; #endif /* WIFI_DIRECT_SUPPORT */ case TLV_TYPE_UAP_GRP_REKEY_TIME: tlv_rekey_time = (MrvlIEtypes_group_rekey_time_t *)tlv; bss->param.bss_config.wpa_cfg.gk_rekey_time = wlan_le32_to_cpu(tlv_rekey_time->gk_rekey_time); break; case TLV_TYPE_UAP_WEP_KEY: tlv_wep_key = (MrvlIEtypes_wep_key_t *)tlv; pkey = MNULL; if (tlv_wep_key->key_index == 0) pkey = &bss->param.bss_config.wep_cfg.key0; else if (tlv_wep_key->key_index == 1) pkey = &bss->param.bss_config.wep_cfg.key1; else if (tlv_wep_key->key_index == 2) pkey = &bss->param.bss_config.wep_cfg.key2; else if (tlv_wep_key->key_index == 3) pkey = &bss->param.bss_config.wep_cfg.key3; if (pkey) { pkey->key_index = tlv_wep_key->key_index; pkey->is_default = tlv_wep_key->is_default; pkey->length = MIN(MAX_WEP_KEY_SIZE, (tlv_len - 2)); memcpy(pmpriv->adapter, pkey->key, tlv_wep_key->key, pkey->length); } break; case TLV_TYPE_UAP_PREAMBLE_CTL: tlv_preamble = (MrvlIEtypes_preamble_t *)tlv; bss->param.bss_config.preamble_type = tlv_preamble->preamble_type; break; case TLV_TYPE_BSS_STATUS: tlv_bss_status = (MrvlIEtypes_bss_status_t *)tlv; bss->param.bss_config.bss_status = wlan_le16_to_cpu(tlv_bss_status->bss_status); pmpriv->uap_bss_started = (bss->param.bss_config. bss_status) ? MTRUE : MFALSE; break; case TLV_TYPE_HT_CAPABILITY: tlv_htcap = (MrvlIETypes_HTCap_t *)tlv; bss->param.bss_config.ht_cap_info = wlan_le16_to_cpu(tlv_htcap->ht_cap.ht_cap_info); bss->param.bss_config.ampdu_param = tlv_htcap->ht_cap.ampdu_param; memcpy(pmpriv->adapter, bss->param.bss_config.supported_mcs_set, tlv_htcap->ht_cap.supported_mcs_set, 16); bss->param.bss_config.ht_ext_cap = wlan_le16_to_cpu(tlv_htcap->ht_cap.ht_ext_cap); bss->param.bss_config.tx_bf_cap = wlan_le32_to_cpu(tlv_htcap->ht_cap.tx_bf_cap); bss->param.bss_config.asel = tlv_htcap->ht_cap.asel; break; case TLV_TYPE_VENDOR_SPECIFIC_IE: tlv_wmm_parameter = (MrvlIEtypes_wmm_parameter_t *)tlv; bss->param.bss_config.wmm_para.qos_info = tlv_wmm_parameter->wmm_para.qos_info; for (ac = 0; ac < 4; ac++) { bss->param.bss_config.wmm_para.ac_params[ac]. aci_aifsn.aifsn = tlv_wmm_parameter->wmm_para. ac_params[ac].aci_aifsn.aifsn; bss->param.bss_config.wmm_para.ac_params[ac]. aci_aifsn.aci = tlv_wmm_parameter->wmm_para. ac_params[ac].aci_aifsn.aci; bss->param.bss_config.wmm_para.ac_params[ac]. ecw.ecw_max = tlv_wmm_parameter->wmm_para. ac_params[ac].ecw.ecw_max; bss->param.bss_config.wmm_para.ac_params[ac]. ecw.ecw_min = tlv_wmm_parameter->wmm_para. ac_params[ac].ecw.ecw_min; bss->param.bss_config.wmm_para.ac_params[ac]. tx_op_limit = wlan_le16_to_cpu(tlv_wmm_parameter-> wmm_para.ac_params[ac]. tx_op_limit); } break; } tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t); tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len + sizeof(MrvlIEtypesHeader_t)); } #ifdef DRV_EMBEDDED_AUTHENTICATOR if (!IS_FW_SUPPORT_AUTHENTICATOR(pmpriv->adapter)) AuthenticatorBssConfig(pmpriv->psapriv, (t_u8 *)&bss->param.bss_config, 0, 0, 1); #endif LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function handles the command response of sys_reset * Clear various private state variables used by DFS. * * @param pmpriv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @param pioctl_buf A pointer to mlan_ioctl_req structure * * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_ret_sys_reset(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf) { ENTER(); memset(pmpriv->adapter, &(pmpriv->uap_state_chan_cb.bandcfg), 0, sizeof(pmpriv->uap_state_chan_cb.bandcfg)); pmpriv->uap_state_chan_cb.channel = 0; pmpriv->uap_state_chan_cb.beacon_period = 0; pmpriv->uap_state_chan_cb.dtim_period = 0; /* assume default 11d/11h states are off, should check with FW */ /* currently don't clear domain_info... global, could be from STA */ wlan_11d_priv_init(pmpriv); wlan_11h_priv_init(pmpriv); LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function handles the command response of sys_config * * @param pmpriv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @param pioctl_buf A pointer to mlan_ioctl_req structure * * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_ret_sys_config(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf) { int resp_len = 0, travel_len = 0; int i = 0; custom_ie *cptr; HostCmd_DS_SYS_CONFIG *sys_config = (HostCmd_DS_SYS_CONFIG *)&resp->params.sys_config; mlan_ds_bss *bss = MNULL; mlan_ds_misc_cfg *misc = MNULL; MrvlIEtypes_MacAddr_t *tlv = (MrvlIEtypes_MacAddr_t *)sys_config->tlv_buffer; mlan_ds_misc_custom_ie *cust_ie = MNULL; tlvbuf_max_mgmt_ie *max_mgmt_ie = MNULL; MrvlIEtypes_wmm_parameter_t *tlv_wmm_parameter = (MrvlIEtypes_wmm_parameter_t *)sys_config->tlv_buffer; MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)sys_config->tlv_buffer; MrvlIEtypes_channel_band_t *chan_band_tlv = (MrvlIEtypes_channel_band_t *)sys_config->tlv_buffer; ChanScanParamSet_t *pscan_chan = MNULL; t_u8 ac = 0; MrvlIEtypes_channel_band_t *tlv_cb = MNULL; MrvlIEtypes_beacon_period_t *tlv_bcnpd = MNULL; MrvlIEtypes_dtim_period_t *tlv_dtimpd = MNULL; ENTER(); if (pioctl_buf) { if (pioctl_buf->req_id == MLAN_IOCTL_BSS) { bss = (mlan_ds_bss *)pioctl_buf->pbuf; if (bss->sub_command == MLAN_OID_BSS_MAC_ADDR) { if (TLV_TYPE_UAP_MAC_ADDRESS == wlan_le16_to_cpu(tlv->header.type)) { memcpy(pmpriv->adapter, &bss->param.mac_addr, tlv->mac, MLAN_MAC_ADDR_LENGTH); } } else if (bss->sub_command == MLAN_OID_UAP_CFG_WMM_PARAM) { if (TLV_TYPE_AP_WMM_PARAM == wlan_le16_to_cpu(tlv_wmm_parameter->header. type)) { if (wlan_le16_to_cpu (tlv_wmm_parameter->header.len) < sizeof(bss->param.ap_wmm_para)) { PRINTM(MCMND, "FW don't support AP WMM PARAM\n"); } else { bss->param.ap_wmm_para. reserved = MLAN_STATUS_COMPLETE; for (ac = 0; ac < 4; ac++) { bss->param.ap_wmm_para. ac_params[ac]. aci_aifsn. aifsn = tlv_wmm_parameter-> wmm_para. ac_params[ac]. aci_aifsn.aifsn; bss->param.ap_wmm_para. ac_params[ac]. aci_aifsn.aci = tlv_wmm_parameter-> wmm_para. ac_params[ac]. aci_aifsn.aci; bss->param.ap_wmm_para. ac_params[ac]. ecw.ecw_max = tlv_wmm_parameter-> wmm_para. ac_params[ac]. ecw.ecw_max; bss->param.ap_wmm_para. ac_params[ac]. ecw.ecw_min = tlv_wmm_parameter-> wmm_para. ac_params[ac]. ecw.ecw_min; bss->param.ap_wmm_para. ac_params[ac]. tx_op_limit = wlan_le16_to_cpu (tlv_wmm_parameter-> wmm_para. ac_params[ac]. tx_op_limit); PRINTM(MCMND, "ac=%d, aifsn=%d, aci=%d, ecw_max=%d, ecw_min=%d, tx_op=%d\n", ac, bss->param. ap_wmm_para. ac_params[ac]. aci_aifsn.aifsn, bss->param. ap_wmm_para. ac_params[ac]. aci_aifsn.aci, bss->param. ap_wmm_para. ac_params[ac]. ecw.ecw_max, bss->param. ap_wmm_para. ac_params[ac]. ecw.ecw_min, bss->param. ap_wmm_para. ac_params[ac]. tx_op_limit); } } } } else if (bss->sub_command == MLAN_OID_UAP_SCAN_CHANNELS) { if (TLV_TYPE_CHANLIST == wlan_le16_to_cpu(tlv_chan_list->header. type)) { pscan_chan = tlv_chan_list->chan_scan_param; bss->param.ap_scan_channels. num_of_chan = 0; for (i = 0; i < wlan_le16_to_cpu(tlv_chan_list-> header.len) / sizeof(ChanScanParamSet_t); i++) { if (bss->param.ap_scan_channels. remove_nop_channel && wlan_11h_is_channel_under_nop (pmpriv->adapter, pscan_chan->chan_number)) { bss->param. ap_scan_channels. num_remvoed_channel++; PRINTM(MCMND, "Remove nop channel=%d\n", pscan_chan-> chan_number); pscan_chan++; continue; } bss->param.ap_scan_channels. chan_list[bss->param. ap_scan_channels. num_of_chan]. chan_number = pscan_chan->chan_number; bss->param.ap_scan_channels. chan_list[bss->param. ap_scan_channels. num_of_chan]. bandcfg = pscan_chan->bandcfg; bss->param.ap_scan_channels. num_of_chan++; pscan_chan++; } PRINTM(MCMND, "AP scan channel list=%d\n", bss->param.ap_scan_channels. num_of_chan); } } else if (bss->sub_command == MLAN_OID_UAP_CHANNEL) { if (TLV_TYPE_UAP_CHAN_BAND_CONFIG == wlan_le16_to_cpu(chan_band_tlv->header. type)) { bss->param.ap_channel.bandcfg = chan_band_tlv->bandcfg; bss->param.ap_channel.channel = chan_band_tlv->channel; bss->param.ap_channel.is_11n_enabled = pmpriv->is_11n_enabled; bss->param.ap_channel.is_dfs_chan = wlan_11h_radar_detect_required (pmpriv, bss->param.ap_channel.channel); if (chan_band_tlv->bandcfg.chanWidth == CHAN_BW_80MHZ) bss->param.ap_channel. center_chan = wlan_get_center_freq_idx (pmpriv, BAND_AAC, chan_band_tlv->channel, CHANNEL_BW_80MHZ); PRINTM(MCMND, "AP channel, band=0x%x, channel=%d, is_11n_enabled=%d center_chan=%d\n", bss->param.ap_channel.bandcfg. chanBand, bss->param.ap_channel.channel, bss->param.ap_channel. is_11n_enabled, bss->param.ap_channel. center_chan); } } else if ((bss->sub_command == MLAN_OID_UAP_BSS_CONFIG) && (pioctl_buf->action == MLAN_ACT_GET)) { wlan_uap_ret_cmd_ap_config(pmpriv, resp, pioctl_buf); } } if (pioctl_buf->req_id == MLAN_IOCTL_MISC_CFG) { misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf; cust_ie = (mlan_ds_misc_custom_ie *)sys_config-> tlv_buffer; if ((pioctl_buf->action == MLAN_ACT_GET || pioctl_buf->action == MLAN_ACT_SET) && (misc->sub_command == MLAN_OID_MISC_CUSTOM_IE)) { cust_ie->type = wlan_le16_to_cpu(cust_ie->type); resp_len = cust_ie->len = wlan_le16_to_cpu(cust_ie->len); travel_len = 0; /* conversion for index, mask, len */ if (resp_len == sizeof(t_u16)) cust_ie->ie_data_list[0].ie_index = wlan_cpu_to_le16(cust_ie-> ie_data_list [0].ie_index); while (resp_len > sizeof(t_u16)) { cptr = (custom_ie *)(((t_u8 *)cust_ie-> ie_data_list) + travel_len); cptr->ie_index = wlan_le16_to_cpu(cptr-> ie_index); cptr->mgmt_subtype_mask = wlan_le16_to_cpu(cptr-> mgmt_subtype_mask); cptr->ie_length = wlan_le16_to_cpu(cptr-> ie_length); travel_len += cptr->ie_length + sizeof(custom_ie) - MAX_IE_SIZE; resp_len -= cptr->ie_length + sizeof(custom_ie) - MAX_IE_SIZE; } memcpy(pmpriv->adapter, &misc->param.cust_ie, cust_ie, MIN(sizeof(mlan_ds_misc_custom_ie) - sizeof(tlvbuf_max_mgmt_ie), (cust_ie->len + sizeof(MrvlIEtypesHeader_t)))); max_mgmt_ie = (tlvbuf_max_mgmt_ie *)(sys_config-> tlv_buffer + cust_ie->len + sizeof (MrvlIEtypesHeader_t)); if (max_mgmt_ie) { max_mgmt_ie->type = wlan_le16_to_cpu(max_mgmt_ie-> type); if (max_mgmt_ie->type == TLV_TYPE_MAX_MGMT_IE) { max_mgmt_ie->len = wlan_le16_to_cpu (max_mgmt_ie->len); max_mgmt_ie->count = wlan_le16_to_cpu (max_mgmt_ie->count); for (i = 0; i < max_mgmt_ie->count; i++) { max_mgmt_ie->info[i]. buf_size = wlan_le16_to_cpu (max_mgmt_ie-> info[i]. buf_size); max_mgmt_ie->info[i]. buf_count = wlan_le16_to_cpu (max_mgmt_ie-> info[i]. buf_count); } /* Append max_mgmt_ie TLV after custom_ie */ memcpy(pmpriv->adapter, (t_u8 *)&misc->param. cust_ie + (cust_ie->len + sizeof (MrvlIEtypesHeader_t)), max_mgmt_ie, MIN(sizeof (tlvbuf_max_mgmt_ie), max_mgmt_ie->len + sizeof (MrvlIEtypesHeader_t))); } } } } } else { /* no ioctl: driver generated get/set */ switch (wlan_le16_to_cpu(tlv->header.type)) { case TLV_TYPE_UAP_MAC_ADDRESS: memcpy(pmpriv->adapter, pmpriv->curr_addr, tlv->mac, MLAN_MAC_ADDR_LENGTH); break; case TLV_TYPE_UAP_CHAN_BAND_CONFIG: tlv_cb = (MrvlIEtypes_channel_band_t *)tlv; pmpriv->uap_state_chan_cb.bandcfg = tlv_cb->bandcfg; pmpriv->uap_state_chan_cb.channel = tlv_cb->channel; /* call callback waiting for channel info */ if (pmpriv->uap_state_chan_cb.get_chan_callback) pmpriv->uap_state_chan_cb. get_chan_callback(pmpriv); break; case TLV_TYPE_UAP_BEACON_PERIOD: tlv_bcnpd = (MrvlIEtypes_beacon_period_t *)tlv; pmpriv->uap_state_chan_cb.beacon_period = wlan_le16_to_cpu(tlv_bcnpd->beacon_period); /* copy dtim_period as well if it follows */ tlv_dtimpd = (MrvlIEtypes_dtim_period_t *)(((t_u8 *)tlv) + sizeof (MrvlIEtypes_beacon_period_t)); if (TLV_TYPE_UAP_DTIM_PERIOD == wlan_le16_to_cpu(tlv_dtimpd->header.type)) pmpriv->uap_state_chan_cb.dtim_period = tlv_dtimpd->dtim_period; /* call callback waiting for beacon/dtim info */ if (pmpriv->uap_state_chan_cb.get_chan_callback) pmpriv->uap_state_chan_cb. get_chan_callback(pmpriv); break; case TLV_TYPE_MGMT_IE: if ((pmpriv->adapter->state_rdh.stage == RDH_SET_CUSTOM_IE) || (pmpriv->adapter->state_rdh.stage == RDH_REM_CUSTOM_IE)) { if (!pmpriv->adapter->ecsa_enable) wlan_11h_radar_detected_callback((t_void *) pmpriv); } break; } } LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function prepares command of snmp_mib * * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @param cmd_action the action: GET or SET * @param cmd_oid Cmd oid: treated as sub command * @param pioctl_buf A pointer to mlan_ioctl_req structure * @param pdata_buf A pointer to information buffer * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status wlan_uap_cmd_snmp_mib(pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action, IN t_u32 cmd_oid, IN pmlan_ioctl_req pioctl_buf, IN t_void *pdata_buf) { HostCmd_DS_802_11_SNMP_MIB *psnmp_mib = &cmd->params.smib; mlan_status ret = MLAN_STATUS_SUCCESS; t_u8 *psnmp_oid = MNULL; t_u32 ul_temp; t_u8 i; t_u8 snmp_oids[] = { tkip_mic_failures, ccmp_decrypt_errors, wep_undecryptable_count, wep_icv_error_count, decrypt_failure_count, dot11_mcast_tx_count, dot11_failed_count, dot11_retry_count, dot11_multi_retry_count, dot11_frame_dup_count, dot11_rts_success_count, dot11_rts_failure_count, dot11_ack_failure_count, dot11_rx_fragment_count, dot11_mcast_rx_frame_count, dot11_fcs_error_count, dot11_tx_frame_count, dot11_rsna_tkip_cm_invoked, dot11_rsna_4way_hshk_failures, }; ENTER(); if (cmd_action == HostCmd_ACT_GEN_GET) { cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB); psnmp_mib->query_type = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET); if (cmd_oid == StopDeauth_i) { psnmp_mib->oid = wlan_cpu_to_le16((t_u16)StopDeauth_i); psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8)); cmd->size = wlan_cpu_to_le16(sizeof (HostCmd_DS_802_11_SNMP_MIB) + S_DS_GEN); } else { cmd->size = wlan_cpu_to_le16(sizeof(t_u16) + S_DS_GEN + sizeof(snmp_oids) * sizeof (MrvlIEtypes_snmp_oid_t)); psnmp_oid = (t_u8 *)&psnmp_mib->oid; for (i = 0; i < sizeof(snmp_oids); i++) { /* SNMP OID header type */ *(t_u16 *)psnmp_oid = wlan_cpu_to_le16(snmp_oids[i]); psnmp_oid += sizeof(t_u16); /* SNMP OID header length */ *(t_u16 *)psnmp_oid = wlan_cpu_to_le16(sizeof(t_u32)); psnmp_oid += sizeof(t_u16) + sizeof(t_u32); } } } else { /* cmd_action == ACT_SET */ cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB); cmd->size = sizeof(HostCmd_DS_802_11_SNMP_MIB) - 1 + S_DS_GEN; psnmp_mib->query_type = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); switch (cmd_oid) { case Dot11D_i: case Dot11H_i: psnmp_mib->oid = wlan_cpu_to_le16((t_u16)cmd_oid); psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16)); ul_temp = *(t_u32 *)pdata_buf; *((t_u16 *)(psnmp_mib->value)) = wlan_cpu_to_le16((t_u16)ul_temp); cmd->size += sizeof(t_u16); break; case ECSAEnable_i: psnmp_mib->oid = wlan_cpu_to_le16((t_u16)cmd_oid); psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8)); psnmp_mib->value[0] = *((t_u8 *)pdata_buf); cmd->size += sizeof(t_u8); break; case StopDeauth_i: psnmp_mib->oid = wlan_cpu_to_le16((t_u16)cmd_oid); psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8)); psnmp_mib->value[0] = *((t_u8 *)pdata_buf); cmd->size += sizeof(t_u8); break; default: PRINTM(MERROR, "Unsupported OID.\n"); ret = MLAN_STATUS_FAILURE; break; } cmd->size = wlan_cpu_to_le16(cmd->size); } LEAVE(); return ret; } /** * @brief This function prepares command of get_log. * * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_cmd_802_11_get_log(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd) { ENTER(); cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_GET_LOG); cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_GET_LOG) + S_DS_GEN); LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function prepares command of bss_start. * * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_cmd_bss_start(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd) { MrvlIEtypes_HostMlme_t *tlv; ENTER(); cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_BSS_START); cmd->size = S_DS_GEN; if (pmpriv->uap_host_based & UAP_FLAG_HOST_MLME) { tlv = (MrvlIEtypes_HostMlme_t *) ((t_u8 *)cmd + cmd->size); tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_HOST_MLME); tlv->header.len = wlan_cpu_to_le16(sizeof(tlv->host_mlme)); tlv->host_mlme = MTRUE; cmd->size += sizeof(MrvlIEtypes_HostMlme_t); } cmd->size = wlan_cpu_to_le16(cmd->size); LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function handles the command response of snmp_mib * * @param pmpriv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @param pioctl_buf A pointer to mlan_ioctl_req structure * * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_ret_snmp_mib(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf) { pmlan_adapter pmadapter = pmpriv->adapter; HostCmd_DS_802_11_SNMP_MIB *psnmp_mib = (HostCmd_DS_802_11_SNMP_MIB *)&resp->params.smib; mlan_ds_get_info *info; mlan_ds_snmp_mib *mib = MNULL; t_u16 oid = wlan_le16_to_cpu(psnmp_mib->oid); t_u8 *psnmp_oid = MNULL; t_u32 data; t_u16 tlv_buf_left = 0; t_u16 tlv_type = 0; t_u16 query_type = wlan_le16_to_cpu(psnmp_mib->query_type); ENTER(); if (query_type == HostCmd_ACT_GEN_GET) { if (!pioctl_buf) { LEAVE(); return MLAN_STATUS_SUCCESS; } if (oid == StopDeauth_i) { mib = (mlan_ds_snmp_mib *)pioctl_buf->pbuf; if (mib) mib->param.deauthctrl = psnmp_mib->value[0]; LEAVE(); return MLAN_STATUS_SUCCESS; } info = (mlan_ds_get_info *)pioctl_buf->pbuf; tlv_buf_left = resp->size - (sizeof(t_u16) + S_DS_GEN); psnmp_oid = (t_u8 *)&psnmp_mib->oid; while (tlv_buf_left >= sizeof(MrvlIEtypes_snmp_oid_t)) { tlv_type = wlan_le16_to_cpu(*(t_u16 *)psnmp_oid); psnmp_oid += sizeof(t_u16) + sizeof(t_u16); memcpy(pmadapter, &data, psnmp_oid, sizeof(t_u32)); switch (tlv_type) { case tkip_mic_failures: info->param.ustats.tkip_mic_failures = wlan_le32_to_cpu(data); break; case ccmp_decrypt_errors: info->param.ustats.ccmp_decrypt_errors = wlan_le32_to_cpu(data); break; case wep_undecryptable_count: info->param.ustats.wep_undecryptable_count = wlan_le32_to_cpu(data); break; case wep_icv_error_count: info->param.ustats.wep_icv_error_count = wlan_le32_to_cpu(data); break; case decrypt_failure_count: info->param.ustats.decrypt_failure_count = wlan_le32_to_cpu(data); break; case dot11_mcast_tx_count: info->param.ustats.mcast_tx_count = wlan_le32_to_cpu(data); break; case dot11_failed_count: info->param.ustats.failed_count = wlan_le32_to_cpu(data); break; case dot11_retry_count: info->param.ustats.retry_count = wlan_le32_to_cpu(data); break; case dot11_multi_retry_count: info->param.ustats.multi_retry_count = wlan_le32_to_cpu(data); break; case dot11_frame_dup_count: info->param.ustats.frame_dup_count = wlan_le32_to_cpu(data); break; case dot11_rts_success_count: info->param.ustats.rts_success_count = wlan_le32_to_cpu(data); break; case dot11_rts_failure_count: info->param.ustats.rts_failure_count = wlan_le32_to_cpu(data); break; case dot11_ack_failure_count: info->param.ustats.ack_failure_count = wlan_le32_to_cpu(data); break; case dot11_rx_fragment_count: info->param.ustats.rx_fragment_count = wlan_le32_to_cpu(data); break; case dot11_mcast_rx_frame_count: info->param.ustats.mcast_rx_frame_count = wlan_le32_to_cpu(data); break; case dot11_fcs_error_count: info->param.ustats.fcs_error_count = wlan_le32_to_cpu(data); break; case dot11_tx_frame_count: info->param.ustats.tx_frame_count = wlan_le32_to_cpu(data); break; case dot11_rsna_tkip_cm_invoked: info->param.ustats.rsna_tkip_cm_invoked = wlan_le32_to_cpu(data); break; case dot11_rsna_4way_hshk_failures: info->param.ustats.rsna_4way_hshk_failures = wlan_le32_to_cpu(data); break; } tlv_buf_left -= sizeof(MrvlIEtypes_snmp_oid_t); psnmp_oid += sizeof(t_u32); } } else { /* ACT_SET */ switch (wlan_le16_to_cpu(psnmp_mib->oid)) { case Dot11D_i: data = wlan_le16_to_cpu(*((t_u16 *)(psnmp_mib->value))); /* Set 11d state to private */ pmpriv->state_11d.enable_11d = data; /* Set user enable flag if called from ioctl */ if (pioctl_buf) pmpriv->state_11d.user_enable_11d = data; break; case Dot11H_i: data = wlan_le16_to_cpu(*((t_u16 *)(psnmp_mib->value))); /* Set 11h state to priv */ pmpriv->intf_state_11h.is_11h_active = (data & ENABLE_11H_MASK); /* Set radar_det state to adapter */ pmpriv->adapter->state_11h.is_master_radar_det_active = (data & MASTER_RADAR_DET_MASK) ? MTRUE : MFALSE; pmpriv->adapter->state_11h.is_slave_radar_det_active = (data & SLAVE_RADAR_DET_MASK) ? MTRUE : MFALSE; break; } } LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function handles the command response of get_log * * @param pmpriv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @param pioctl_buf A pointer to mlan_ioctl_req structure * * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_ret_get_log(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf) { HostCmd_DS_802_11_GET_LOG *pget_log = (HostCmd_DS_802_11_GET_LOG *)&resp->params.get_log; mlan_ds_get_info *pget_info = MNULL; int i = 0; ENTER(); if (pioctl_buf) { pget_info = (mlan_ds_get_info *)pioctl_buf->pbuf; pget_info->param.stats.mcast_tx_frame = wlan_le32_to_cpu(pget_log->mcast_tx_frame); pget_info->param.stats.failed = wlan_le32_to_cpu(pget_log->failed); pget_info->param.stats.retry = wlan_le32_to_cpu(pget_log->retry); pget_info->param.stats.multi_retry = wlan_le32_to_cpu(pget_log->multiretry); pget_info->param.stats.frame_dup = wlan_le32_to_cpu(pget_log->frame_dup); pget_info->param.stats.rts_success = wlan_le32_to_cpu(pget_log->rts_success); pget_info->param.stats.rts_failure = wlan_le32_to_cpu(pget_log->rts_failure); pget_info->param.stats.ack_failure = wlan_le32_to_cpu(pget_log->ack_failure); pget_info->param.stats.rx_frag = wlan_le32_to_cpu(pget_log->rx_frag); pget_info->param.stats.mcast_rx_frame = wlan_le32_to_cpu(pget_log->mcast_rx_frame); pget_info->param.stats.fcs_error = wlan_le32_to_cpu(pget_log->fcs_error); pget_info->param.stats.tx_frame = wlan_le32_to_cpu(pget_log->tx_frame); pget_info->param.stats.wep_icv_error[0] = wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[0]); pget_info->param.stats.wep_icv_error[1] = wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[1]); pget_info->param.stats.wep_icv_error[2] = wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[2]); pget_info->param.stats.wep_icv_error[3] = wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[3]); pget_info->param.stats.bcn_rcv_cnt = wlan_le32_to_cpu(pget_log->bcn_rcv_cnt); pget_info->param.stats.bcn_miss_cnt = wlan_le32_to_cpu(pget_log->bcn_miss_cnt); pget_info->param.stats.amsdu_rx_cnt = pmpriv->amsdu_rx_cnt; pget_info->param.stats.msdu_in_rx_amsdu_cnt = pmpriv->msdu_in_rx_amsdu_cnt; pget_info->param.stats.amsdu_tx_cnt = pmpriv->amsdu_tx_cnt; pget_info->param.stats.msdu_in_tx_amsdu_cnt = pmpriv->msdu_in_tx_amsdu_cnt; if (pmpriv->adapter->getlog_enable) { pget_info->param.stats.tx_frag_cnt = wlan_le32_to_cpu(pget_log->tx_frag_cnt); for (i = 0; i < 8; i++) { pget_info->param.stats.qos_tx_frag_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_tx_frag_cnt[i]); pget_info->param.stats.qos_failed_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_failed_cnt[i]); pget_info->param.stats.qos_retry_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_retry_cnt[i]); pget_info->param.stats.qos_multi_retry_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_multi_retry_cnt [i]); pget_info->param.stats.qos_frm_dup_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_frm_dup_cnt[i]); pget_info->param.stats.qos_rts_suc_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_rts_suc_cnt[i]); pget_info->param.stats.qos_rts_failure_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_rts_failure_cnt [i]); pget_info->param.stats.qos_ack_failure_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_ack_failure_cnt [i]); pget_info->param.stats.qos_rx_frag_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_rx_frag_cnt[i]); pget_info->param.stats.qos_tx_frm_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_tx_frm_cnt[i]); pget_info->param.stats. qos_discarded_frm_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_discarded_frm_cnt [i]); pget_info->param.stats.qos_mpdus_rx_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_mpdus_rx_cnt[i]); pget_info->param.stats.qos_retries_rx_cnt[i] = wlan_le32_to_cpu(pget_log-> qos_retries_rx_cnt[i]); } pget_info->param.stats.mgmt_ccmp_replays = wlan_le32_to_cpu(pget_log->mgmt_ccmp_replays); pget_info->param.stats.tx_amsdu_cnt = wlan_le32_to_cpu(pget_log->tx_amsdu_cnt); pget_info->param.stats.failed_amsdu_cnt = wlan_le32_to_cpu(pget_log->failed_amsdu_cnt); pget_info->param.stats.retry_amsdu_cnt = wlan_le32_to_cpu(pget_log->retry_amsdu_cnt); pget_info->param.stats.multi_retry_amsdu_cnt = wlan_le32_to_cpu(pget_log-> multi_retry_amsdu_cnt); pget_info->param.stats.tx_octets_in_amsdu_cnt = wlan_le64_to_cpu(pget_log-> tx_octets_in_amsdu_cnt); pget_info->param.stats.amsdu_ack_failure_cnt = wlan_le32_to_cpu(pget_log-> amsdu_ack_failure_cnt); pget_info->param.stats.rx_amsdu_cnt = wlan_le32_to_cpu(pget_log->rx_amsdu_cnt); pget_info->param.stats.rx_octets_in_amsdu_cnt = wlan_le64_to_cpu(pget_log-> rx_octets_in_amsdu_cnt); pget_info->param.stats.tx_ampdu_cnt = wlan_le32_to_cpu(pget_log->tx_ampdu_cnt); pget_info->param.stats.tx_mpdus_in_ampdu_cnt = wlan_le32_to_cpu(pget_log-> tx_mpdus_in_ampdu_cnt); pget_info->param.stats.tx_octets_in_ampdu_cnt = wlan_le64_to_cpu(pget_log-> tx_octets_in_ampdu_cnt); pget_info->param.stats.ampdu_rx_cnt = wlan_le32_to_cpu(pget_log->ampdu_rx_cnt); pget_info->param.stats.mpdu_in_rx_ampdu_cnt = wlan_le32_to_cpu(pget_log-> mpdu_in_rx_ampdu_cnt); pget_info->param.stats.rx_octets_in_ampdu_cnt = wlan_le64_to_cpu(pget_log-> rx_octets_in_ampdu_cnt); pget_info->param.stats.ampdu_delimiter_crc_error_cnt = wlan_le32_to_cpu(pget_log-> ampdu_delimiter_crc_error_cnt); /* Indicate ioctl complete */ pioctl_buf->data_read_written = sizeof(mlan_ds_get_info); } else pioctl_buf->data_read_written = sizeof(mlan_ds_get_stats_org) + sizeof(pget_info->sub_command); } LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function prepares command of deauth station * * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @param pdata_buf A pointer to data buffer * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_cmd_sta_deauth(pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf) { HostCmd_DS_STA_DEAUTH *pcmd_sta_deauth = (HostCmd_DS_STA_DEAUTH *)&cmd->params.sta_deauth; mlan_deauth_param *deauth = (mlan_deauth_param *)pdata_buf; ENTER(); cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_STA_DEAUTH); cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_STA_DEAUTH)); memcpy(pmpriv->adapter, pcmd_sta_deauth->mac, deauth->mac_addr, MLAN_MAC_ADDR_LENGTH); pcmd_sta_deauth->reason = wlan_cpu_to_le16(deauth->reason_code); LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function prepares command of key material * * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @param cmd_action The action: GET or SET * @param cmd_oid OID: ENABLE or DISABLE * @param pdata_buf A pointer to data buffer * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_cmd_key_material(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action, IN t_u16 cmd_oid, IN t_void *pdata_buf) { HostCmd_DS_802_11_KEY_MATERIAL *pkey_material = &cmd->params.key_material; mlan_ds_encrypt_key *pkey = (mlan_ds_encrypt_key *)pdata_buf; mlan_status ret = MLAN_STATUS_SUCCESS; sta_node *sta_ptr = MNULL; ENTER(); if (!pkey) { ret = MLAN_STATUS_FAILURE; goto done; } cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); pkey_material->action = wlan_cpu_to_le16(cmd_action); if (cmd_action == HostCmd_ACT_GEN_GET) { cmd->size = wlan_cpu_to_le16(sizeof(pkey_material->action) + S_DS_GEN); goto done; } memset(pmpriv->adapter, &pkey_material->key_param_set, 0, sizeof(MrvlIEtype_KeyParamSetV2_t)); if (pkey->key_flags & KEY_FLAG_REMOVE_KEY) { pkey_material->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_REMOVE); pkey_material->key_param_set.type = wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); pkey_material->key_param_set.length = wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN); pkey_material->key_param_set.key_idx = pkey->key_index & KEY_INDEX_MASK; pkey_material->key_param_set.key_info = wlan_cpu_to_le16(KEY_INFO_MCAST_KEY | KEY_INFO_UCAST_KEY); memcpy(pmpriv->adapter, pkey_material->key_param_set.mac_addr, pkey->mac_addr, MLAN_MAC_ADDR_LENGTH); cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + KEY_PARAMS_FIXED_LEN + sizeof(pkey_material->action)); PRINTM(MCMND, "Remove Key\n"); goto done; } pkey_material->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); pkey_material->key_param_set.key_idx = pkey->key_index & KEY_INDEX_MASK; pkey_material->key_param_set.type = wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); pkey_material->key_param_set.key_info = KEY_INFO_ENABLE_KEY; memcpy(pmpriv->adapter, pkey_material->key_param_set.mac_addr, pkey->mac_addr, MLAN_MAC_ADDR_LENGTH); if (pkey->key_len <= MAX_WEP_KEY_SIZE) { pkey_material->key_param_set.length = wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(wep_param_t)); pkey_material->key_param_set.key_type = KEY_TYPE_ID_WEP; pkey_material->key_param_set.key_info |= KEY_INFO_MCAST_KEY | KEY_INFO_UCAST_KEY; if (pkey_material->key_param_set.key_idx == (pmpriv->wep_key_curr_index & KEY_INDEX_MASK)) pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY; pkey_material->key_param_set.key_info = wlan_cpu_to_le16(pkey_material->key_param_set.key_info); pkey_material->key_param_set.key_params.wep.key_len = wlan_cpu_to_le16(pkey->key_len); memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.wep.key, pkey->key_material, pkey->key_len); cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + KEY_PARAMS_FIXED_LEN + sizeof(wep_param_t) + sizeof(pkey_material->action)); PRINTM(MCMND, "Set WEP Key\n"); goto done; } if (pkey->key_flags & KEY_FLAG_GROUP_KEY) pkey_material->key_param_set.key_info |= KEY_INFO_MCAST_KEY; else pkey_material->key_param_set.key_info |= KEY_INFO_UCAST_KEY; if (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK) pkey_material->key_param_set.key_info = KEY_INFO_CMAC_AES_KEY; if (pkey->key_flags & KEY_FLAG_SET_TX_KEY) pkey_material->key_param_set.key_info |= KEY_INFO_TX_KEY | KEY_INFO_RX_KEY; else pkey_material->key_param_set.key_info |= KEY_INFO_TX_KEY; if (pkey->is_wapi_key) { pkey_material->key_param_set.key_type = KEY_TYPE_ID_WAPI; memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.wapi.pn, pkey->pn, PN_SIZE); pkey_material->key_param_set.key_params.wapi.key_len = wlan_cpu_to_le16(MIN(WAPI_KEY_SIZE, pkey->key_len)); memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.wapi.key, pkey->key_material, MIN(WAPI_KEY_SIZE, pkey->key_len)); if (!pmpriv->sec_info.wapi_key_on) pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY; if (pkey->key_flags & KEY_FLAG_GROUP_KEY) { pmpriv->sec_info.wapi_key_on = MTRUE; } else { /* WAPI pairwise key: unicast */ sta_ptr = wlan_add_station_entry(pmpriv, pkey->mac_addr); if (sta_ptr) { PRINTM(MCMND, "station: wapi_key_on\n"); sta_ptr->wapi_key_on = MTRUE; } } pkey_material->key_param_set.key_info = wlan_cpu_to_le16(pkey_material->key_param_set.key_info); pkey_material->key_param_set.length = wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(wapi_param)); cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + KEY_PARAMS_FIXED_LEN + sizeof(wapi_param) + sizeof(pkey_material->action)); PRINTM(MCMND, "Set WAPI Key\n"); goto done; } pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY; pkey_material->key_param_set.key_info = wlan_cpu_to_le16(pkey_material->key_param_set.key_info); if (pkey->key_len == WPA_AES_KEY_LEN && !(pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) { if (pkey-> key_flags & (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID)) memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.aes.pn, pkey->pn, SEQ_MAX_SIZE); pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES; pkey_material->key_param_set.key_params.aes.key_len = wlan_cpu_to_le16(pkey->key_len); memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.aes.key, pkey->key_material, pkey->key_len); pkey_material->key_param_set.length = wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(aes_param)); cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + KEY_PARAMS_FIXED_LEN + sizeof(aes_param) + sizeof(pkey_material->action)); PRINTM(MCMND, "Set AES Key\n"); goto done; } if (pkey->key_len == WPA_IGTK_KEY_LEN && (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) { if (pkey-> key_flags & (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID)) memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.cmac_aes. ipn, pkey->pn, SEQ_MAX_SIZE); pkey_material->key_param_set.key_info &= ~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY)); pkey_material->key_param_set.key_info |= wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK); pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC; pkey_material->key_param_set.key_params.cmac_aes.key_len = wlan_cpu_to_le16(pkey->key_len); memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.cmac_aes.key, pkey->key_material, pkey->key_len); pkey_material->key_param_set.length = wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(cmac_aes_param)); cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + KEY_PARAMS_FIXED_LEN + sizeof(cmac_aes_param) + sizeof(pkey_material->action)); PRINTM(MCMND, "Set CMAC AES Key\n"); goto done; } if (pkey->key_len == WPA_TKIP_KEY_LEN) { if (pkey-> key_flags & (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID)) memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.tkip.pn, pkey->pn, SEQ_MAX_SIZE); pkey_material->key_param_set.key_type = KEY_TYPE_ID_TKIP; pkey_material->key_param_set.key_params.tkip.key_len = wlan_cpu_to_le16(pkey->key_len); memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.tkip.key, pkey->key_material, pkey->key_len); pkey_material->key_param_set.length = wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(tkip_param)); cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + KEY_PARAMS_FIXED_LEN + sizeof(tkip_param) + sizeof(pkey_material->action)); PRINTM(MCMND, "Set TKIP Key\n"); } done: LEAVE(); return ret; } /** * @brief This function handles the command response of sta_list * * @param pmpriv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @param pioctl_buf A pointer to mlan_ioctl_req structure * * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_ret_sta_list(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf) { HostCmd_DS_STA_LIST *sta_list = (HostCmd_DS_STA_LIST *)&resp->params.sta_list; mlan_ds_get_info *info; MrvlIEtypes_sta_info_t *tlv = MNULL; t_u8 i = 0; sta_node *sta_ptr; ENTER(); if (pioctl_buf) { info = (mlan_ds_get_info *)pioctl_buf->pbuf; info->param.sta_list.sta_count = wlan_le16_to_cpu(sta_list->sta_count); tlv = (MrvlIEtypes_sta_info_t *)((t_u8 *)sta_list + sizeof(HostCmd_DS_STA_LIST)); info->param.sta_list.sta_count = MIN(info->param.sta_list.sta_count, MAX_NUM_CLIENTS); for (i = 0; i < info->param.sta_list.sta_count; i++) { memcpy(pmpriv->adapter, info->param.sta_list.info[i].mac_address, tlv->mac_address, MLAN_MAC_ADDR_LENGTH); info->param.sta_list.info[i].power_mfg_status = tlv->power_mfg_status; info->param.sta_list.info[i].rssi = tlv->rssi; sta_ptr = wlan_get_station_entry(pmpriv, tlv->mac_address); if (sta_ptr) { info->param.sta_list.info[i].bandmode = sta_ptr->bandmode; memcpy(pmpriv->adapter, &(info->param.sta_list.info[i].stats), &(sta_ptr->stats), sizeof(sta_stats)); } else info->param.sta_list.info[i].bandmode = 0xFF; tlv++; } } LEAVE(); return MLAN_STATUS_SUCCESS; } /** Fixed size of bss start event */ #define BSS_START_EVENT_FIX_SIZE 12 /** * @brief This function will search for the specific ie * * @param priv A pointer to mlan_private * @param pevent A pointer to event buf * * @return N/A */ static void wlan_check_uap_capability(pmlan_private priv, pmlan_buffer pevent) { t_u16 tlv_type, tlv_len; int tlv_buf_left = pevent->data_len - BSS_START_EVENT_FIX_SIZE; MrvlIEtypesHeader_t *tlv = (MrvlIEtypesHeader_t *)(pevent->pbuf + pevent->data_offset + BSS_START_EVENT_FIX_SIZE); const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; IEEEtypes_WmmParameter_t wmm_param_ie; MrvlIEtypes_channel_band_t *pchan_info; t_u8 event_buf[100]; mlan_event *event = (mlan_event *)event_buf; chan_band_info *pchan_band_info = (chan_band_info *) event->event_buf; priv->wmm_enabled = MFALSE; priv->pkt_fwd = MFALSE; priv->is_11n_enabled = MFALSE; ENTER(); while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) { tlv_type = wlan_le16_to_cpu(tlv->type); tlv_len = wlan_le16_to_cpu(tlv->len); if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) > (unsigned int)tlv_buf_left) { PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len, tlv_buf_left); break; } if (tlv_type == HT_CAPABILITY) { DBG_HEXDUMP(MCMD_D, "HT_CAP tlv", tlv, tlv_len + sizeof(MrvlIEtypesHeader_t)); priv->is_11n_enabled = MTRUE; } if (tlv_type == VHT_CAPABILITY) { DBG_HEXDUMP(MCMD_D, "VHT_CAP tlv", tlv, tlv_len + sizeof(MrvlIEtypesHeader_t)); priv->is_11ac_enabled = MTRUE; } if (tlv_type == VENDOR_SPECIFIC_221) { if (!memcmp (priv->adapter, (t_u8 *)tlv + sizeof(MrvlIEtypesHeader_t), wmm_oui, sizeof(wmm_oui))) { DBG_HEXDUMP(MCMD_D, "wmm ie tlv", tlv, tlv_len + sizeof(MrvlIEtypesHeader_t)); priv->wmm_enabled = MFALSE; wlan_wmm_setup_ac_downgrade(priv); priv->wmm_enabled = MTRUE; memcpy(priv->adapter, &wmm_param_ie, ((t_u8 *)tlv + 2), sizeof(IEEEtypes_WmmParameter_t)); wmm_param_ie.vend_hdr.len = (t_u8)tlv_len; wmm_param_ie.vend_hdr.element_id = WMM_IE; wlan_wmm_setup_queue_priorities(priv, &wmm_param_ie); } } if (tlv_type == TLV_TYPE_UAP_PKT_FWD_CTL) { DBG_HEXDUMP(MCMD_D, "pkt_fwd tlv", tlv, tlv_len + sizeof(MrvlIEtypesHeader_t)); priv->pkt_fwd = *((t_u8 *)tlv + sizeof(MrvlIEtypesHeader_t)); PRINTM(MCMND, "pkt_fwd FW: 0x%x\n", priv->pkt_fwd); if (priv->pkt_fwd & PKT_FWD_FW_BIT) priv->pkt_fwd = MFALSE; else priv->pkt_fwd |= PKT_FWD_ENABLE_BIT; PRINTM(MCMND, "pkt_fwd DRV: 0x%x\n", priv->pkt_fwd); } if (tlv_type == TLV_TYPE_UAP_CHAN_BAND_CONFIG) { DBG_HEXDUMP(MCMD_D, "chan_band_config tlv", tlv, tlv_len + sizeof(MrvlIEtypesHeader_t)); pchan_info = (MrvlIEtypes_channel_band_t *)tlv; priv->uap_channel = pchan_info->channel; PRINTM(MCMND, "uap_channel FW: 0x%x\n", priv->uap_channel); event->bss_index = priv->bss_index; event->event_id = MLAN_EVENT_ID_DRV_UAP_CHAN_INFO; event->event_len = sizeof(chan_band_info); memcpy(priv->adapter, (t_u8 *)&pchan_band_info->bandcfg, (t_u8 *)&pchan_info->bandcfg, tlv_len); if (pchan_band_info->bandcfg.chanWidth == CHAN_BW_80MHZ) pchan_band_info->center_chan = wlan_get_center_freq_idx(priv, BAND_AAC, pchan_info-> channel, CHANNEL_BW_80MHZ); if (priv->adapter->ecsa_enable) { int ret; t_u8 bandwidth = BW_20MHZ; MrvlIEtypes_chan_bw_oper_t chan_bw_oper; chan_bw_oper.header.type = REGULATORY_CLASS; chan_bw_oper.header.len = sizeof(MrvlIEtypes_chan_bw_oper_t); chan_bw_oper.ds_chan_bw_oper.channel = pchan_info->channel; if (pchan_band_info->bandcfg.chanWidth == CHAN_BW_40MHZ) bandwidth = BW_40MHZ; else if (pchan_band_info->bandcfg.chanWidth == CHAN_BW_80MHZ) bandwidth = BW_80MHZ; chan_bw_oper.ds_chan_bw_oper.bandwidth = bandwidth; ret = wlan_prepare_cmd(priv, HOST_CMD_APCMD_SYS_CONFIGURE, HostCmd_ACT_GEN_SET, 0, MNULL, &chan_bw_oper); if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) { PRINTM(MERROR, "%s(): Could not set supported operating class IE for priv=%p [priv_bss_idx=%d]!\n", __func__, priv, priv->bss_index); } } } tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len); tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len + sizeof(MrvlIEtypesHeader_t)); } if (priv->wmm_enabled == MFALSE) { /* Since WMM is not enabled, setup the queues with the defaults */ wlan_wmm_setup_queues(priv); } if (event->event_id == MLAN_EVENT_ID_DRV_UAP_CHAN_INFO) { pchan_band_info->is_11n_enabled = priv->is_11n_enabled; wlan_recv_event(priv, MLAN_EVENT_ID_DRV_UAP_CHAN_INFO, event); } LEAVE(); } /** * @brief This function will update WAPI PN in statation assoc event * * @param priv A pointer to mlan_private * @param pevent A pointer to event buf * * @return MFALSE */ static t_u32 wlan_update_wapi_info_tlv(pmlan_private priv, pmlan_buffer pevent) { t_u32 ret = MFALSE; t_u16 tlv_type, tlv_len; t_u32 tx_pn[4]; t_u32 i = 0; int tlv_buf_left = pevent->data_len - ASSOC_EVENT_FIX_SIZE; MrvlIEtypesHeader_t *tlv = (MrvlIEtypesHeader_t *) (pevent->pbuf + pevent->data_offset + ASSOC_EVENT_FIX_SIZE); MrvlIEtypes_wapi_info_t *wapi_tlv = MNULL; ENTER(); while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) { tlv_type = wlan_le16_to_cpu(tlv->type); tlv_len = wlan_le16_to_cpu(tlv->len); if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) > (unsigned int)tlv_buf_left) { PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len, tlv_buf_left); break; } if (tlv_type == TLV_TYPE_AP_WAPI_INFO) { wapi_tlv = (MrvlIEtypes_wapi_info_t *)tlv; DBG_HEXDUMP(MCMD_D, "Fw:multicast_PN", wapi_tlv->multicast_PN, PN_SIZE); memcpy(priv->adapter, (t_u8 *)tx_pn, wapi_tlv->multicast_PN, PN_SIZE); for (i = 0; i < 4; i++) tx_pn[i] = mlan_ntohl(tx_pn[i]); memcpy(priv->adapter, wapi_tlv->multicast_PN, (t_u8 *)tx_pn, PN_SIZE); DBG_HEXDUMP(MCMD_D, "Host:multicast_PN", wapi_tlv->multicast_PN, PN_SIZE); break; } tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len); tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len + sizeof(MrvlIEtypesHeader_t)); } LEAVE(); return ret; } /** * @brief This function send sta_assoc_event to moal * payload with sta mac address and assoc ie. * * @param priv A pointer to mlan_private * @param pevent A pointer to mlan_event buffer * @param pbuf A pointer to mlan_buffer which has event content. * * @return MFALSE */ static t_u32 wlan_process_sta_assoc_event(pmlan_private priv, mlan_event *pevent, pmlan_buffer pmbuf) { t_u32 ret = MFALSE; t_u16 tlv_type, tlv_len; t_u16 frame_control, frame_sub_type = 0; t_u8 *assoc_req_ie = MNULL; t_u8 ie_len = 0, assoc_ie_len = 0; int tlv_buf_left = pmbuf->data_len - ASSOC_EVENT_FIX_SIZE; MrvlIEtypesHeader_t *tlv = (MrvlIEtypesHeader_t *) (pmbuf->pbuf + pmbuf->data_offset + ASSOC_EVENT_FIX_SIZE); MrvlIETypes_MgmtFrameSet_t *mgmt_tlv = MNULL; ENTER(); pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_CONNECT; pevent->bss_index = priv->bss_index; pevent->event_len = MLAN_MAC_ADDR_LENGTH; memcpy(priv->adapter, pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset + 6, pevent->event_len); while (tlv_buf_left >= (int)sizeof(MrvlIEtypesHeader_t)) { tlv_type = wlan_le16_to_cpu(tlv->type); tlv_len = wlan_le16_to_cpu(tlv->len); if ((sizeof(MrvlIEtypesHeader_t) + tlv_len) > (unsigned int)tlv_buf_left) { PRINTM(MERROR, "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", tlv_len, tlv_buf_left); break; } if (tlv_type == TLV_TYPE_MGMT_FRAME) { mgmt_tlv = (MrvlIETypes_MgmtFrameSet_t *)tlv; memcpy(priv->adapter, &frame_control, (t_u8 *)&(mgmt_tlv->frame_control), sizeof(frame_control)); frame_sub_type = IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE (frame_control); if ((mgmt_tlv->frame_control.type == 0) && ((frame_sub_type == SUBTYPE_ASSOC_REQUEST) || (frame_sub_type == SUBTYPE_REASSOC_REQUEST))) { if (frame_sub_type == SUBTYPE_ASSOC_REQUEST) assoc_ie_len = sizeof(IEEEtypes_AssocRqst_t); else if (frame_sub_type == SUBTYPE_REASSOC_REQUEST) assoc_ie_len = sizeof(IEEEtypes_ReAssocRqst_t); ie_len = tlv_len - sizeof(IEEEtypes_FrameCtl_t) - assoc_ie_len; assoc_req_ie = (t_u8 *)tlv + sizeof(MrvlIETypes_MgmtFrameSet_t) + assoc_ie_len; memcpy(priv->adapter, pevent->event_buf + pevent->event_len, assoc_req_ie, ie_len); pevent->event_len += ie_len; break; } } tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len); tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len + sizeof(MrvlIEtypesHeader_t)); } PRINTM(MEVENT, "STA assoc event len=%d\n", pevent->event_len); DBG_HEXDUMP(MCMD_D, "STA assoc event", pevent->event_buf, pevent->event_len); wlan_recv_event(priv, pevent->event_id, pevent); LEAVE(); return ret; } /** * @brief This function prepares command of uap operation control * * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @param cmd_action the action: GET or SET * @param pdata_buf A pointer to data buffer * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_cmd_oper_ctrl(pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action, IN t_void *pdata_buf) { HostCmd_DS_UAP_OPER_CTRL *poper_ctl = (HostCmd_DS_UAP_OPER_CTRL *) & cmd->params.uap_oper_ctrl; mlan_ds_bss *bss = (mlan_ds_bss *)pdata_buf; mlan_uap_oper_ctrl *uap_oper_ctrl = &bss->param.ap_oper_ctrl; Band_Config_t *bandcfg = MNULL; ENTER(); cmd->command = wlan_cpu_to_le16(HOST_CMD_APCMD_OPER_CTRL); cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_UAP_OPER_CTRL) + S_DS_GEN); poper_ctl->action = wlan_cpu_to_le16(cmd_action); if (cmd_action == HostCmd_ACT_GEN_SET) { poper_ctl->ctrl = wlan_cpu_to_le16(uap_oper_ctrl->ctrl_value); if (uap_oper_ctrl->ctrl_value == 2) { poper_ctl->chan_opt = wlan_cpu_to_le16(uap_oper_ctrl->chan_opt); if (uap_oper_ctrl->chan_opt == 3) { poper_ctl->channel_band.header.type = wlan_cpu_to_le16 (TLV_TYPE_UAP_CHAN_BAND_CONFIG); poper_ctl->channel_band.header.len = wlan_cpu_to_le16(sizeof (MrvlIEtypes_channel_band_t) - sizeof (MrvlIEtypesHeader_t)); bandcfg = &poper_ctl->channel_band.bandcfg; if (uap_oper_ctrl->channel > 14) bandcfg->chanBand = BAND_5GHZ; bandcfg->chanWidth = uap_oper_ctrl->band_cfg; if (bandcfg->chanWidth) bandcfg->chan2Offset = wlan_get_second_channel_offset (uap_oper_ctrl->channel); bandcfg->scanMode = SCAN_MODE_MANUAL; poper_ctl->channel_band.channel = uap_oper_ctrl->channel; } } } LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief This function handles the command response of uap operation control * * @param pmpriv A pointer to mlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @param pioctl_buf A pointer to mlan_ioctl_req structure * * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_uap_ret_oper_ctrl(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *resp, IN mlan_ioctl_req *pioctl_buf) { HostCmd_DS_UAP_OPER_CTRL *poper_ctl = (HostCmd_DS_UAP_OPER_CTRL *) & resp->params.uap_oper_ctrl; mlan_ds_bss *bss = MNULL; mlan_uap_oper_ctrl *uap_oper_ctrl = MNULL; Band_Config_t *bandcfg = MNULL; ENTER(); if (pioctl_buf && pioctl_buf->action == MLAN_ACT_GET) { bss = (mlan_ds_bss *)pioctl_buf->pbuf; uap_oper_ctrl = (mlan_uap_oper_ctrl *) & bss->param.ap_oper_ctrl; uap_oper_ctrl->ctrl_value = wlan_le16_to_cpu(poper_ctl->ctrl); uap_oper_ctrl->chan_opt = wlan_le16_to_cpu(poper_ctl->chan_opt); uap_oper_ctrl->channel = poper_ctl->channel_band.channel; bandcfg = &poper_ctl->channel_band.bandcfg; uap_oper_ctrl->band_cfg = bandcfg->chanWidth; } LEAVE(); return MLAN_STATUS_SUCCESS; } /** * @brief Check 11B support Rates * * * @param pmadapter Private mlan adapter structure * * @return MTRUE/MFALSE * */ t_u8 wlan_check_11B_support_rates(MrvlIEtypes_RatesParamSet_t *prates_tlv) { int i; t_u8 rate; t_u8 ret = MTRUE; for (i = 0; i < prates_tlv->header.len; i++) { rate = prates_tlv->rates[i] & 0x7f; if ((rate != 0x02) && (rate != 0x04) && (rate != 0x0b) && (rate != 0x16)) { ret = MFALSE; break; } } return ret; } /** * @brief This function prepares command of sys_config * * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @param cmd_action cmd action * @param pioctl_buf A pointer to mlan_ioctl_req structure * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status wlan_uap_cmd_add_station(pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action, IN pmlan_ioctl_req pioctl_buf) { mlan_ds_bss *bss = MNULL; HostCmd_DS_ADD_STATION *new_sta = (HostCmd_DS_ADD_STATION *) & cmd->params.sta_info; sta_node *sta_ptr = MNULL; t_u16 tlv_buf_left; t_u8 *pos = MNULL; t_u8 *tlv_buf = MNULL; t_u16 travel_len = 0; MrvlIEtypesHeader_t *tlv; t_u16 tlv_len = 0; t_u8 b_only = MFALSE; mlan_adapter *pmadapter = pmpriv->adapter; MrvlIETypes_HTCap_t *phtcap; MrvlIETypes_VHTCap_t *pvhtcap; MrvlIEtypes_StaFlag_t *pstaflag; ENTER(); if (!pioctl_buf) { LEAVE(); return MLAN_STATUS_FAILURE; } bss = (mlan_ds_bss *)pioctl_buf->pbuf; cmd->command = wlan_cpu_to_le16(HostCmd_CMD_ADD_NEW_STATION); new_sta->action = wlan_cpu_to_le16(cmd_action); cmd->size = sizeof(HostCmd_DS_ADD_STATION) + S_DS_GEN; if (cmd_action == HostCmd_ACT_ADD_STA) { sta_ptr = wlan_get_station_entry(pmpriv, bss->param.sta_info.peer_mac); if (!sta_ptr) sta_ptr = wlan_add_station_entry(pmpriv, bss->param.sta_info. peer_mac); } else { sta_ptr = wlan_add_station_entry(pmpriv, bss->param.sta_info.peer_mac); } if (!sta_ptr) { LEAVE(); return MLAN_STATUS_FAILURE; } memcpy(pmadapter, new_sta->peer_mac, bss->param.sta_info.peer_mac, MLAN_MAC_ADDR_LENGTH); if (cmd_action != HostCmd_ACT_ADD_STA) goto done; new_sta->aid = wlan_cpu_to_le16(bss->param.sta_info.aid); new_sta->listen_interval = wlan_cpu_to_le32(bss->param.sta_info.listen_interval); if (bss->param.sta_info.cap_info) new_sta->cap_info = wlan_cpu_to_le16(bss->param.sta_info.cap_info); else new_sta->cap_info = wlan_cpu_to_le16(sta_ptr->capability); tlv_buf_left = bss->param.sta_info.tlv_len; pos = new_sta->tlv; tlv_buf = bss->param.sta_info.tlv; tlv = (MrvlIEtypesHeader_t *)tlv_buf; if (bss->param.sta_info.sta_flags & STA_FLAG_WME) { PRINTM(MCMND, "STA flags supports wmm \n"); sta_ptr->is_wmm_enabled = MTRUE; } //append sta_flag_flags. pstaflag = (MrvlIEtypes_StaFlag_t *) pos; pstaflag->header.type = wlan_cpu_to_le16(TLV_TYPE_UAP_STA_FLAGS); pstaflag->header.len = wlan_cpu_to_le16(sizeof(t_u32)); pstaflag->sta_flags = wlan_cpu_to_le32(bss->param.sta_info.sta_flags); pos += sizeof(MrvlIEtypes_StaFlag_t); cmd->size += sizeof(MrvlIEtypes_StaFlag_t); while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) { if (tlv_buf_left < (sizeof(MrvlIEtypesHeader_t) + tlv->len)) break; switch (tlv->type) { case EXT_CAPABILITY: break; case TLV_TYPE_RATES: b_only = wlan_check_11B_support_rates((MrvlIEtypes_RatesParamSet_t *)tlv); break; case QOS_INFO: PRINTM(MCMND, "STA supports wmm\n"); sta_ptr->is_wmm_enabled = MTRUE; break; case HT_CAPABILITY: PRINTM(MCMND, "STA supports 11n\n"); sta_ptr->is_11n_enabled = MTRUE; phtcap = (MrvlIETypes_HTCap_t *)tlv; if (GETHT_MAXAMSDU(phtcap->ht_cap.ht_cap_info)) sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K; else sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K; break; case VHT_CAPABILITY: PRINTM(MCMND, "STA supports 11ac\n"); sta_ptr->is_11ac_enabled = MTRUE; pvhtcap = (MrvlIETypes_VHTCap_t *)tlv; if (GET_VHTCAP_MAXMPDULEN(pvhtcap->vht_cap.vht_cap_info) == 2) sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_12K; else if (GET_VHTCAP_MAXMPDULEN (pvhtcap->vht_cap.vht_cap_info) == 1) sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_8K; else sta_ptr->max_amsdu = MLAN_TX_DATA_BUF_SIZE_4K; break; case OPER_MODE_NTF: break; default: break; } tlv_len = tlv->len; tlv->type = wlan_cpu_to_le16(tlv->type); tlv->len = wlan_cpu_to_le16(tlv->len); memcpy(pmadapter, pos, (t_u8 *)tlv, sizeof(MrvlIEtypesHeader_t) + tlv_len); pos += sizeof(MrvlIEtypesHeader_t) + tlv_len; tlv_buf += sizeof(MrvlIEtypesHeader_t) + tlv_len; tlv = (MrvlIEtypesHeader_t *)tlv_buf; travel_len += sizeof(MrvlIEtypesHeader_t) + tlv_len; tlv_buf_left -= sizeof(MrvlIEtypesHeader_t) + tlv_len; } if (sta_ptr->is_11ac_enabled) { if (pmpriv->uap_channel <= 14) sta_ptr->bandmode = BAND_GAC; else sta_ptr->bandmode = BAND_AAC; } else if (sta_ptr->is_11n_enabled) { if (pmpriv->uap_channel <= 14) sta_ptr->bandmode = BAND_GN; else sta_ptr->bandmode = BAND_AN; } else if (!b_only) { if (pmpriv->uap_channel <= 14) sta_ptr->bandmode = BAND_G; else sta_ptr->bandmode = BAND_A; } else sta_ptr->bandmode = BAND_B; done: cmd->size += travel_len; cmd->size = wlan_cpu_to_le16(cmd->size); LEAVE(); return MLAN_STATUS_SUCCESS; } /******************************************************** Global Functions ********************************************************/ /** * @brief This function prepare the command before sending to firmware. * * @param priv A pointer to mlan_private structure * @param cmd_no Command number * @param cmd_action Command action: GET or SET * @param cmd_oid Cmd oid: treated as sub command * @param pioctl_buf A pointer to MLAN IOCTL Request buffer * @param pdata_buf A pointer to information buffer * @param pcmd_buf A pointer to cmd buf * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_uap_prepare_cmd(IN t_void *priv, IN t_u16 cmd_no, IN t_u16 cmd_action, IN t_u32 cmd_oid, IN t_void *pioctl_buf, IN t_void *pdata_buf, IN t_void *pcmd_buf) { HostCmd_DS_COMMAND *cmd_ptr = (HostCmd_DS_COMMAND *)pcmd_buf; mlan_private *pmpriv = (mlan_private *)priv; mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf; ENTER(); /* Prepare command */ switch (cmd_no) { case HostCmd_CMD_SOFT_RESET: case HOST_CMD_APCMD_BSS_STOP: case HOST_CMD_APCMD_SYS_INFO: case HOST_CMD_APCMD_SYS_RESET: case HOST_CMD_APCMD_STA_LIST: cmd_ptr->command = wlan_cpu_to_le16(cmd_no); cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN); break; case HOST_CMD_APCMD_BSS_START: ret = wlan_uap_cmd_bss_start(pmpriv, cmd_ptr); #ifdef DRV_EMBEDDED_AUTHENTICATOR if (IsAuthenticatorEnabled(pmpriv->psapriv)) AuthenticatorBssConfig(pmpriv->psapriv, MNULL, 1, 0, 0); #endif break; case HOST_CMD_APCMD_SYS_CONFIGURE: ret = wlan_uap_cmd_sys_configure(pmpriv, cmd_ptr, cmd_action, (pmlan_ioctl_req)pioctl_buf, pdata_buf); break; case HostCmd_CMD_802_11_PS_MODE_ENH: ret = wlan_cmd_enh_power_mode(pmpriv, cmd_ptr, cmd_action, (t_u16)cmd_oid, pdata_buf); break; case HostCmd_CMD_FUNC_INIT: if (pmpriv->adapter->hw_status == WlanHardwareStatusReset) pmpriv->adapter->hw_status = WlanHardwareStatusInitializing; cmd_ptr->command = wlan_cpu_to_le16(cmd_no); cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN); break; case HostCmd_CMD_FUNC_SHUTDOWN: pmpriv->adapter->hw_status = WlanHardwareStatusReset; cmd_ptr->command = wlan_cpu_to_le16(cmd_no); cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN); break; case HostCmd_CMD_CFG_DATA: ret = wlan_cmd_cfg_data(pmpriv, cmd_ptr, cmd_action, cmd_oid, pdata_buf); break; case HostCmd_CMD_MAC_CONTROL: ret = wlan_cmd_mac_control(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_802_11_SNMP_MIB: ret = wlan_uap_cmd_snmp_mib(pmpriv, cmd_ptr, cmd_action, cmd_oid, (pmlan_ioctl_req)pioctl_buf, pdata_buf); break; case HostCmd_CMD_802_11_GET_LOG: ret = wlan_uap_cmd_802_11_get_log(pmpriv, cmd_ptr); break; case HostCmd_CMD_802_11D_DOMAIN_INFO: ret = wlan_cmd_802_11d_domain_info(pmpriv, cmd_ptr, cmd_action); break; case HostCmd_CMD_CHAN_REPORT_REQUEST: ret = wlan_11h_cmd_process(pmpriv, cmd_ptr, pdata_buf); break; case HOST_CMD_APCMD_STA_DEAUTH: ret = wlan_uap_cmd_sta_deauth(pmpriv, cmd_ptr, pdata_buf); break; case HostCmd_CMD_802_11_KEY_MATERIAL: ret = wlan_uap_cmd_key_material(pmpriv, cmd_ptr, cmd_action, cmd_oid, pdata_buf); break; case HostCmd_CMD_GET_HW_SPEC: ret = wlan_cmd_get_hw_spec(pmpriv, cmd_ptr); break; case HostCmd_CMD_802_11_HS_CFG_ENH: ret = wlan_uap_cmd_802_11_hs_cfg(pmpriv, cmd_ptr, cmd_action, (hs_config_param *)pdata_buf); break; case HostCmd_CMD_HS_WAKEUP_REASON: ret = wlan_cmd_hs_wakeup_reason(pmpriv, cmd_ptr, pdata_buf); break; case HostCmd_CMD_802_11_FW_WAKE_METHOD: ret = wlan_cmd_802_11_fw_wakeup_method(pmpriv, cmd_ptr, cmd_action, (t_u16 *)pdata_buf); break; case HostCmd_CMD_802_11_ROBUSTCOEX: ret = wlan_cmd_robustcoex(pmpriv, cmd_ptr, cmd_action, (t_u16 *)pdata_buf); break; case HostCmd_CMD_RECONFIGURE_TX_BUFF: ret = wlan_cmd_recfg_tx_buf(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_AMSDU_AGGR_CTRL: ret = wlan_cmd_amsdu_aggr_ctrl(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_11N_CFG: ret = wlan_cmd_11n_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_11N_ADDBA_REQ: ret = wlan_cmd_11n_addba_req(pmpriv, cmd_ptr, pdata_buf); break; case HostCmd_CMD_11N_DELBA: ret = wlan_cmd_11n_delba(pmpriv, cmd_ptr, pdata_buf); break; case HostCmd_CMD_11N_ADDBA_RSP: ret = wlan_cmd_11n_addba_rspgen(pmpriv, cmd_ptr, pdata_buf); break; case HostCmd_CMD_REJECT_ADDBA_REQ: ret = wlan_cmd_reject_addba_req(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_TX_BF_CFG: ret = wlan_cmd_tx_bf_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; #if defined(WIFI_DIRECT_SUPPORT) case HostCmd_CMD_SET_BSS_MODE: cmd_ptr->command = wlan_cpu_to_le16(cmd_no); if (pdata_buf) cmd_ptr->params.bss_mode.con_type = *(t_u8 *)pdata_buf; else cmd_ptr->params.bss_mode.con_type = BSS_MODE_WIFIDIRECT_GO; cmd_ptr->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_SET_BSS_MODE) + S_DS_GEN); ret = MLAN_STATUS_SUCCESS; break; #endif case HostCmd_CMD_VERSION_EXT: cmd_ptr->command = wlan_cpu_to_le16(cmd_no); cmd_ptr->params.verext.version_str_sel = (t_u8)(*((t_u32 *)pdata_buf)); cmd_ptr->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_VERSION_EXT) + S_DS_GEN); ret = MLAN_STATUS_SUCCESS; break; case HostCmd_CMD_RX_MGMT_IND: cmd_ptr->command = wlan_cpu_to_le16(cmd_no); cmd_ptr->params.rx_mgmt_ind.action = wlan_cpu_to_le16(cmd_action); cmd_ptr->params.rx_mgmt_ind.mgmt_subtype_mask = (t_u32)(*((t_u32 *)pdata_buf)); cmd_ptr->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_RX_MGMT_IND) + S_DS_GEN); break; case HostCmd_CMD_CFG_TX_DATA_PAUSE: ret = wlan_uap_cmd_txdatapause(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_802_11_RADIO_CONTROL: ret = wlan_cmd_802_11_radio_control(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_TX_RATE_CFG: ret = wlan_cmd_tx_rate_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_802_11_TX_RATE_QUERY: cmd_ptr->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY); cmd_ptr->size = wlan_cpu_to_le16(sizeof(HostCmd_TX_RATE_QUERY) + S_DS_GEN); pmpriv->tx_rate = 0; ret = MLAN_STATUS_SUCCESS; break; case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL: ret = wlan_cmd_remain_on_channel(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; #ifdef WIFI_DIRECT_SUPPORT case HOST_CMD_WIFI_DIRECT_MODE_CONFIG: ret = wlan_cmd_wifi_direct_mode(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HOST_CMD_P2P_PARAMS_CONFIG: ret = wlan_cmd_p2p_params_config(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; #endif case HostCmd_CMD_802_11_RF_ANTENNA: ret = wlan_cmd_802_11_rf_antenna(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_802_11_MIMO_SWITCH: ret = wlan_cmd_802_11_mimo_switch(pmpriv, cmd_ptr, pdata_buf); break; case HostCmd_CMD_11AC_CFG: ret = wlan_cmd_11ac_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_MAC_REG_ACCESS: case HostCmd_CMD_BBP_REG_ACCESS: case HostCmd_CMD_RF_REG_ACCESS: case HostCmd_CMD_CAU_REG_ACCESS: case HostCmd_CMD_802_11_EEPROM_ACCESS: ret = wlan_cmd_reg_access(cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_MEM_ACCESS: ret = wlan_cmd_mem_access(cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_WMM_QUEUE_CONFIG: ret = wlan_cmd_wmm_queue_config(pmpriv, cmd_ptr, pdata_buf); break; case HostCmd_CMD_MULTI_CHAN_CONFIG: ret = wlan_cmd_multi_chan_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_MULTI_CHAN_POLICY: ret = wlan_cmd_multi_chan_policy(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_DRCS_CONFIG: ret = wlan_cmd_drcs_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; #ifdef RX_PACKET_COALESCE case HostCmd_CMD_RX_PKT_COALESCE_CFG: ret = wlan_cmd_rx_pkt_coalesce_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; #endif case HOST_CMD_APCMD_OPER_CTRL: ret = wlan_uap_cmd_oper_ctrl(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_INDEPENDENT_RESET_CFG: ret = wlan_cmd_ind_rst_cfg(cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_GET_TSF: ret = wlan_cmd_get_tsf(pmpriv, cmd_ptr, cmd_action); break; case HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT: ret = wlan_cmd_ps_inactivity_timeout(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_HOST_CLOCK_CFG: ret = wlan_cmd_host_clock_cfg(cmd_ptr, cmd_action, pdata_buf); break; #ifdef STA_SUPPORT case HostCmd_CMD_ACS: ret = wlan_cmd_acs(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; #endif case HostCmd_CMD_CHAN_REGION_CFG: cmd_ptr->command = wlan_cpu_to_le16(cmd_no); cmd_ptr->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_CHAN_REGION_CFG) + S_DS_GEN); cmd_ptr->params.reg_cfg.action = wlan_cpu_to_le16(cmd_action); break; case HostCmd_CMD_802_11_NET_MONITOR: ret = wlan_cmd_net_monitor(cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_PCIE_HOST_BUF_DETAILS: ret = wlan_cmd_pcie_host_buf_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HOST_CMD_TX_RX_PKT_STATS: ret = wlan_cmd_tx_rx_pkt_stats(pmpriv, cmd_ptr, (pmlan_ioctl_req)pioctl_buf, pdata_buf); break; case HostCmd_CMD_FW_DUMP_EVENT: ret = wlan_cmd_fw_dump_event(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; case HostCmd_CMD_ADD_NEW_STATION: ret = wlan_uap_cmd_add_station(pmpriv, cmd_ptr, cmd_action, (pmlan_ioctl_req)pioctl_buf); break; case HostCmd_CMD_BOOT_SLEEP: ret = wlan_cmd_boot_sleep(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; #if defined(DRV_EMBEDDED_AUTHENTICATOR) case HostCmd_CMD_CRYPTO: ret = wlan_cmd_crypto(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; #endif case HostCmd_CMD_TX_AMPDU_PROT_MODE: ret = wlan_cmd_tx_ampdu_prot_mode(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; default: PRINTM(MERROR, "PREP_CMD: unknown command- %#x\n", cmd_no); if (pioctl_req) pioctl_req->status_code = MLAN_ERROR_CMD_INVALID; ret = MLAN_STATUS_FAILURE; break; } LEAVE(); return ret; } /** * @brief This function handles the AP mode command response * * @param priv A pointer to mlan_private structure * @param cmdresp_no cmd no * @param pcmd_buf cmdresp buf * @param pioctl A pointer to ioctl buf * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_uap_process_cmdresp(IN t_void *priv, IN t_u16 cmdresp_no, IN t_void *pcmd_buf, IN t_void *pioctl) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = (mlan_private *)priv; HostCmd_DS_COMMAND *resp = (HostCmd_DS_COMMAND *)pcmd_buf; mlan_ioctl_req *pioctl_buf = (mlan_ioctl_req *)pioctl; mlan_adapter *pmadapter = pmpriv->adapter; wlan_dfs_device_state_t *pstate_dfs = (wlan_dfs_device_state_t *) &pmpriv->adapter->state_dfs; t_u32 sec, usec; ENTER(); /* If the command is not successful, cleanup and return failure */ if (resp->result != HostCmd_RESULT_OK) { ret = uap_process_cmdresp_error(pmpriv, resp, pioctl_buf); LEAVE(); return ret; } /* Command successful, handle response */ switch (cmdresp_no) { case HOST_CMD_APCMD_BSS_STOP: pmpriv->uap_bss_started = MFALSE; /* Timestamp update is required because bss_start after skip_cac * enabled should not select non-current channel just because * timestamp got expired */ if (!pmpriv->intf_state_11h.is_11h_host && !pstate_dfs->dfs_check_pending && pstate_dfs->dfs_check_channel) { pmpriv->adapter->callbacks.moal_get_system_time(pmpriv-> adapter-> pmoal_handle, &sec, &usec); pstate_dfs->dfs_report_time_sec = sec; } if (pmpriv->intf_state_11h.is_11h_host) pmpriv->intf_state_11h.tx_disabled = MFALSE; else { if (pmpriv->adapter->ecsa_enable) wlan_11h_remove_custom_ie(pmpriv->adapter, pmpriv); wlan_11h_check_update_radar_det_state(pmpriv); } if (pmpriv->adapter->state_rdh.stage == RDH_STOP_INTFS) wlan_11h_radar_detected_callback((t_void *)pmpriv); wlan_coex_ampdu_rxwinsize(pmadapter); #ifdef DRV_EMBEDDED_AUTHENTICATOR if (IsAuthenticatorEnabled(pmpriv->psapriv)) { AuthenticatorBssConfig(pmpriv->psapriv, MNULL, 0, 1, 0); AuthenticatorkeyClear(pmpriv->psapriv); } #endif pmpriv->uap_host_based = 0; break; case HOST_CMD_APCMD_BSS_START: if (!pmpriv->intf_state_11h.is_11h_host && pmpriv->adapter->state_rdh.stage == RDH_RESTART_INTFS) wlan_11h_radar_detected_callback((t_void *)pmpriv); /* Stop pps_uapsd_mode once bss_start */ pmpriv->adapter->tx_lock_flag = MFALSE; pmpriv->adapter->pps_uapsd_mode = MFALSE; pmpriv->adapter->delay_null_pkt = MFALSE; /* Clear AMSDU statistics */ pmpriv->amsdu_rx_cnt = 0; pmpriv->amsdu_tx_cnt = 0; pmpriv->msdu_in_rx_amsdu_cnt = 0; pmpriv->msdu_in_tx_amsdu_cnt = 0; break; case HOST_CMD_APCMD_SYS_RESET: pmpriv->uap_bss_started = MFALSE; pmpriv->uap_host_based = 0; #ifdef DRV_EMBEDDED_AUTHENTICATOR AuthenitcatorInitBssConfig(pmpriv->psapriv); #endif ret = wlan_uap_ret_sys_reset(pmpriv, resp, pioctl_buf); wlan_11h_check_update_radar_det_state(pmpriv); wlan_coex_ampdu_rxwinsize(pmadapter); break; case HOST_CMD_APCMD_SYS_INFO: break; case HOST_CMD_APCMD_SYS_CONFIGURE: ret = wlan_uap_ret_sys_config(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_802_11_PS_MODE_ENH: ret = wlan_ret_enh_power_mode(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_FUNC_INIT: case HostCmd_CMD_FUNC_SHUTDOWN: break; case HostCmd_CMD_802_11_SNMP_MIB: ret = wlan_uap_ret_snmp_mib(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_802_11_GET_LOG: ret = wlan_uap_ret_get_log(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_802_11D_DOMAIN_INFO: ret = wlan_ret_802_11d_domain_info(pmpriv, resp); break; case HostCmd_CMD_CHAN_REPORT_REQUEST: ret = wlan_11h_cmdresp_process(pmpriv, resp); break; case HOST_CMD_APCMD_STA_DEAUTH: break; case HostCmd_CMD_802_11_KEY_MATERIAL: break; case HOST_CMD_APCMD_STA_LIST: ret = wlan_uap_ret_sta_list(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_GET_HW_SPEC: ret = wlan_ret_get_hw_spec(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_CFG_DATA: ret = wlan_ret_cfg_data(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_MAC_CONTROL: ret = wlan_ret_mac_control(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_802_11_HS_CFG_ENH: ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_HS_WAKEUP_REASON: ret = wlan_ret_hs_wakeup_reason(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_802_11_FW_WAKE_METHOD: ret = wlan_ret_fw_wakeup_method(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_802_11_ROBUSTCOEX: break; case HostCmd_CMD_11N_ADDBA_REQ: ret = wlan_ret_11n_addba_req(pmpriv, resp); break; case HostCmd_CMD_11N_DELBA: ret = wlan_ret_11n_delba(pmpriv, resp); break; case HostCmd_CMD_11N_ADDBA_RSP: ret = wlan_ret_11n_addba_resp(pmpriv, resp); break; case HostCmd_CMD_SET_BSS_MODE: break; case HostCmd_CMD_802_11_NET_MONITOR: ret = wlan_ret_net_monitor(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_RECONFIGURE_TX_BUFF: wlan_set_tx_pause_flag(pmpriv, MFALSE); pmadapter->tx_buf_size = (t_u16)wlan_le16_to_cpu(resp->params.tx_buf.buff_size); pmadapter->curr_tx_buf_size = pmadapter->tx_buf_size; PRINTM(MCMND, "max_tx_buf_size=%d, tx_buf_size=%d\n", pmadapter->max_tx_buf_size, pmadapter->tx_buf_size); break; case HostCmd_CMD_AMSDU_AGGR_CTRL: ret = wlan_ret_amsdu_aggr_ctrl(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_11N_CFG: ret = wlan_ret_11n_cfg(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_REJECT_ADDBA_REQ: ret = wlan_ret_reject_addba_req(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_TX_BF_CFG: ret = wlan_ret_tx_bf_cfg(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_VERSION_EXT: ret = wlan_ret_ver_ext(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_RX_MGMT_IND: ret = wlan_ret_rx_mgmt_ind(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_CFG_TX_DATA_PAUSE: ret = wlan_uap_ret_txdatapause(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_802_11_RADIO_CONTROL: ret = wlan_ret_802_11_radio_control(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_TX_RATE_CFG: ret = wlan_ret_tx_rate_cfg(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_802_11_TX_RATE_QUERY: ret = wlan_ret_802_11_tx_rate_query(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL: ret = wlan_ret_remain_on_channel(pmpriv, resp, pioctl_buf); break; #ifdef WIFI_DIRECT_SUPPORT case HOST_CMD_WIFI_DIRECT_MODE_CONFIG: ret = wlan_ret_wifi_direct_mode(pmpriv, resp, pioctl_buf); break; case HOST_CMD_P2P_PARAMS_CONFIG: ret = wlan_ret_p2p_params_config(pmpriv, resp, pioctl_buf); break; #endif case HostCmd_CMD_802_11_RF_ANTENNA: ret = wlan_ret_802_11_rf_antenna(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_802_11_MIMO_SWITCH: break; case HostCmd_CMD_11AC_CFG: ret = wlan_ret_11ac_cfg(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_MAC_REG_ACCESS: case HostCmd_CMD_BBP_REG_ACCESS: case HostCmd_CMD_RF_REG_ACCESS: case HostCmd_CMD_CAU_REG_ACCESS: case HostCmd_CMD_802_11_EEPROM_ACCESS: ret = wlan_ret_reg_access(pmpriv->adapter, cmdresp_no, resp, pioctl_buf); break; case HostCmd_CMD_MEM_ACCESS: ret = wlan_ret_mem_access(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_WMM_QUEUE_CONFIG: ret = wlan_ret_wmm_queue_config(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_MULTI_CHAN_CONFIG: ret = wlan_ret_multi_chan_cfg(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_MULTI_CHAN_POLICY: ret = wlan_ret_multi_chan_policy(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_DRCS_CONFIG: ret = wlan_ret_drcs_cfg(pmpriv, resp, pioctl_buf); break; #ifdef RX_PACKET_COALESCE case HostCmd_CMD_RX_PKT_COALESCE_CFG: ret = wlan_ret_rx_pkt_coalesce_cfg(pmpriv, resp, pioctl_buf); break; #endif case HOST_CMD_APCMD_OPER_CTRL: ret = wlan_uap_ret_oper_ctrl(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_INDEPENDENT_RESET_CFG: ret = wlan_ret_ind_rst_cfg(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_802_11_PS_INACTIVITY_TIMEOUT: break; case HostCmd_CMD_GET_TSF: ret = wlan_ret_get_tsf(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_HOST_CLOCK_CFG: ret = wlan_ret_host_clock_cfg(pmpriv, resp, pioctl_buf); break; #ifdef STA_SUPPORT case HostCmd_CMD_ACS: ret = wlan_ret_acs(pmpriv, resp, pioctl_buf); break; #endif case HostCmd_CMD_CHAN_REGION_CFG: ret = wlan_ret_chan_region_cfg(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_PCIE_HOST_BUF_DETAILS: PRINTM(MINFO, "PCIE host buffer configuration successful.\n"); break; case HOST_CMD_TX_RX_PKT_STATS: ret = wlan_ret_tx_rx_pkt_stats(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_BOOT_SLEEP: ret = wlan_ret_boot_sleep(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_ADD_NEW_STATION: break; #if defined(DRV_EMBEDDED_AUTHENTICATOR) case HostCmd_CMD_CRYPTO: ret = wlan_ret_crypto(pmpriv, resp, pioctl_buf); break; #endif case HostCmd_CMD_TX_AMPDU_PROT_MODE: ret = wlan_ret_tx_ampdu_prot_mode(pmpriv, resp, pioctl_buf); break; default: PRINTM(MERROR, "CMD_RESP: Unknown command response %#x\n", resp->command); if (pioctl_buf) pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL; break; } LEAVE(); return ret; } /** * @brief This function handles events generated by firmware * * @param priv A pointer to mlan_private structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_uap_process_event(IN t_void *priv) { pmlan_private pmpriv = (pmlan_private)priv; pmlan_adapter pmadapter = pmpriv->adapter; pmlan_callbacks pcb = &pmadapter->callbacks; mlan_status ret = MLAN_STATUS_SUCCESS; t_u32 eventcause = pmadapter->event_cause; pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event; t_u8 *event_buf = MNULL; mlan_event *pevent = MNULL; t_u8 sta_addr[MLAN_MAC_ADDR_LENGTH]; sta_node *sta_ptr = MNULL; t_u8 i = 0; t_u8 channel = 0; MrvlIEtypes_channel_band_t *pchan_info = MNULL; chan_band_info *pchan_band_info = MNULL; event_exceed_max_p2p_conn *event_excd_p2p = MNULL; ENTER(); if (!pmbuf) { LEAVE(); return MLAN_STATUS_FAILURE; } /* Event length check */ if (pmbuf && (pmbuf->data_len - sizeof(eventcause)) > MAX_EVENT_SIZE) { pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; LEAVE(); return MLAN_STATUS_FAILURE; } /* Allocate memory for event buffer */ ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE + sizeof(mlan_event), MLAN_MEM_DEF, &event_buf); if ((ret != MLAN_STATUS_SUCCESS) || !event_buf) { PRINTM(MERROR, "Could not allocate buffer for event buf\n"); if (pmbuf) pmbuf->status_code = MLAN_ERROR_NO_MEM; goto done; } pevent = (pmlan_event)event_buf; memset(pmadapter, &pevent->event_id, 0, sizeof(pevent->event_id)); if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE && pmbuf->data_len > sizeof(eventcause)) DBG_HEXDUMP(MEVT_D, "EVENT", pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len); switch (eventcause) { case EVENT_MICRO_AP_BSS_START: PRINTM(MEVENT, "EVENT: MICRO_AP_BSS_START\n"); pmpriv->uap_bss_started = MTRUE; pmpriv->is_data_rate_auto = MTRUE; memcpy(pmadapter, pmpriv->curr_addr, pmadapter->event_body + 2, MLAN_MAC_ADDR_LENGTH); pevent->event_id = MLAN_EVENT_ID_UAP_FW_BSS_START; wlan_check_uap_capability(pmpriv, pmbuf); wlan_coex_ampdu_rxwinsize(pmadapter); #ifdef DRV_EMBEDDED_AUTHENTICATOR if (IsAuthenticatorEnabled(pmpriv->psapriv)) { pmadapter->authenticator_priv = pmpriv; wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_RX_WORK, MNULL); } #endif break; case EVENT_MICRO_AP_BSS_ACTIVE: PRINTM(MEVENT, "EVENT: MICRO_AP_BSS_ACTIVE\n"); pmpriv->media_connected = MTRUE; pmpriv->port_open = MTRUE; pevent->event_id = MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE; break; case EVENT_MICRO_AP_BSS_IDLE: PRINTM(MEVENT, "EVENT: MICRO_AP_BSS_IDLE\n"); pevent->event_id = MLAN_EVENT_ID_UAP_FW_BSS_IDLE; pmpriv->media_connected = MFALSE; wlan_clean_txrx(pmpriv); wlan_notify_station_deauth(pmpriv); wlan_delete_station_list(pmpriv); pmpriv->port_open = MFALSE; pmpriv->tx_pause = MFALSE; break; case EVENT_PS_AWAKE: PRINTM(MINFO, "EVENT: AWAKE\n"); PRINTM(MEVENT, "||"); /* Handle unexpected PS AWAKE event */ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) break; pmadapter->pm_wakeup_card_req = MFALSE; pmadapter->pm_wakeup_fw_try = MFALSE; pmadapter->ps_state = PS_STATE_AWAKE; break; case EVENT_PS_SLEEP: PRINTM(MINFO, "EVENT: SLEEP\n"); PRINTM(MEVENT, "__"); /* Handle unexpected PS SLEEP event */ if (pmadapter->ps_state == PS_STATE_SLEEP_CFM) break; pmadapter->ps_state = PS_STATE_PRE_SLEEP; wlan_check_ps_cond(pmadapter); break; case EVENT_MICRO_AP_STA_ASSOC: wlan_process_sta_assoc_event(pmpriv, pevent, pmbuf); memcpy(pmadapter, sta_addr, pmadapter->event_body + 2, MLAN_MAC_ADDR_LENGTH); sta_ptr = wlan_add_station_entry(pmpriv, sta_addr); PRINTM(MMSG, "wlan: EVENT: MICRO_AP_STA_ASSOC " MACSTR "\n", MAC2STR(sta_addr)); if (!sta_ptr) break; if (pmpriv->is_11n_enabled #ifdef DRV_EMBEDDED_AUTHENTICATOR || IsAuthenticatorEnabled(pmpriv->psapriv) #endif ) { wlan_check_sta_capability(pmpriv, pmbuf, sta_ptr); for (i = 0; i < MAX_NUM_TID; i++) { if (sta_ptr->is_11n_enabled) sta_ptr->ampdu_sta[i] = pmpriv->aggr_prio_tbl[i]. ampdu_user; else sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED; } memset(pmadapter, sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq)); } if (pmpriv->sec_info.wapi_enabled) wlan_update_wapi_info_tlv(pmpriv, pmbuf); #ifdef DRV_EMBEDDED_AUTHENTICATOR /**enter authenticator*/ if (IsAuthenticatorEnabled(pmpriv->psapriv)) AuthenticatorSendEapolPacket(pmpriv->psapriv, sta_ptr-> cm_connectioninfo); #endif pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; break; case EVENT_MICRO_AP_STA_DEAUTH: pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT; pevent->bss_index = pmpriv->bss_index; pevent->event_len = pmbuf->data_len - 4; /* skip event length field */ memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset + 4, pevent->event_len); wlan_recv_event(pmpriv, pevent->event_id, pevent); memcpy(pmadapter, sta_addr, pmadapter->event_body + 2, MLAN_MAC_ADDR_LENGTH); PRINTM(MMSG, "wlan: EVENT: MICRO_AP_STA_DEAUTH " MACSTR "\n", MAC2STR(sta_addr)); if (pmpriv->is_11n_enabled) { wlan_cleanup_reorder_tbl(pmpriv, sta_addr); wlan_11n_cleanup_txbastream_tbl(pmpriv, sta_addr); } wlan_wmm_delete_peer_ralist(pmpriv, sta_addr); wlan_delete_station_entry(pmpriv, sta_addr); pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; break; case EVENT_HS_ACT_REQ: PRINTM(MEVENT, "EVENT: HS_ACT_REQ\n"); ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_HS_CFG_ENH, 0, 0, MNULL, MNULL); break; case EVENT_ADDBA: PRINTM(MEVENT, "EVENT: ADDBA Request\n"); if (pmpriv->media_connected == MTRUE) ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_11N_ADDBA_RSP, HostCmd_ACT_GEN_SET, 0, MNULL, pmadapter->event_body); else PRINTM(MERROR, "Ignore ADDBA Request event in BSS idle state\n"); break; case EVENT_DELBA: PRINTM(MEVENT, "EVENT: DELBA Request\n"); if (pmpriv->media_connected == MTRUE) wlan_11n_delete_bastream(pmpriv, pmadapter->event_body); else PRINTM(MERROR, "Ignore DELBA Request event in BSS idle state\n"); break; case EVENT_BA_STREAM_TIMEOUT: PRINTM(MEVENT, "EVENT: BA Stream timeout\n"); if (pmpriv->media_connected == MTRUE) wlan_11n_ba_stream_timeout(pmpriv, (HostCmd_DS_11N_BATIMEOUT *) pmadapter->event_body); else PRINTM(MERROR, "Ignore BA Stream timeout event in BSS idle state\n"); break; case EVENT_RXBA_SYNC: PRINTM(MEVENT, "EVENT: RXBA_SYNC\n"); wlan_11n_rxba_sync_event(pmpriv, pmadapter->event_body, pmbuf->data_len - sizeof(eventcause)); break; case EVENT_AMSDU_AGGR_CTRL: PRINTM(MEVENT, "EVENT: AMSDU_AGGR_CTRL %d\n", *(t_u16 *)pmadapter->event_body); pmadapter->tx_buf_size = MIN(pmadapter->curr_tx_buf_size, wlan_le16_to_cpu(*(t_u16 *)pmadapter->event_body)); PRINTM(MEVENT, "tx_buf_size %d\n", pmadapter->tx_buf_size); break; case EVENT_TX_DATA_PAUSE: PRINTM(MEVENT, "EVENT: TX_DATA_PAUSE\n"); wlan_process_tx_pause_event(priv, pmbuf); break; case EVENT_RADAR_DETECTED: PRINTM(MEVENT, "EVENT: Radar Detected\n"); /* Send as passthru first, this event can cause other events */ memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE); pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; pevent->event_len = pmbuf->data_len; memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset, pevent->event_len); wlan_recv_event(pmpriv, pevent->event_id, pevent); pevent->event_id = 0; /* clear to avoid resending at end of fcn */ if (!pmpriv->intf_state_11h.is_11h_host) { if (pmadapter->state_rdh.stage == RDH_OFF) { pmadapter->state_rdh.stage = RDH_CHK_INTFS; wlan_11h_radar_detected_handling(pmadapter, pmpriv); if (pmpriv->uap_host_based) wlan_recv_event(priv, MLAN_EVENT_ID_FW_RADAR_DETECTED, MNULL); } else { PRINTM(MEVENT, "Ignore Event Radar Detected - handling" " already in progress.\n"); } } else { #ifdef DFS_TESTING_SUPPORT if (pmpriv->adapter->dfs_test_params. no_channel_change_on_radar || pmpriv->adapter->dfs_test_params. fixed_new_channel_on_radar) { if (pmadapter->state_rdh.stage == RDH_OFF || pmadapter->state_rdh.stage == RDH_SET_CUSTOM_IE) { pmadapter->state_rdh.stage = RDH_CHK_INTFS; wlan_11h_radar_detected_handling (pmadapter, pmpriv); } else PRINTM(MEVENT, "Ignore Event Radar Detected - handling already in progress.\n"); } else { #endif pmpriv->intf_state_11h.tx_disabled = MTRUE; wlan_recv_event(priv, MLAN_EVENT_ID_FW_RADAR_DETECTED, MNULL); #ifdef DFS_TESTING_SUPPORT } #endif } break; case EVENT_CHANNEL_REPORT_RDY: PRINTM(MEVENT, "EVENT: Channel Report Ready\n"); memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE); /* Setup event buffer */ pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY; pevent->event_len = pmbuf->data_len - sizeof(eventcause); /* Copy event data */ memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause), pevent->event_len); /* Handle / pass event data, and free buffer */ ret = wlan_11h_handle_event_chanrpt_ready(pmpriv, pevent); if (pmpriv->intf_state_11h.is_11h_host) { *((t_u8 *)pevent->event_buf) = pmpriv->adapter->state_dfs.dfs_radar_found; wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY, pevent); } else { /* Send up this Event to unblock MOAL waitqueue */ wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_MEAS_REPORT, MNULL); } pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; break; case EVENT_CHANNEL_SWITCH: pchan_info = (MrvlIEtypes_channel_band_t *)(pmadapter->event_body); channel = pchan_info->channel; PRINTM(MEVENT, "EVENT: CHANNEL_SWITCH new channel %d\n", channel); pmpriv->uap_channel = channel; if ((pmpriv->adapter->state_rdh.stage != RDH_OFF && !pmpriv->intf_state_11h.is_11h_host) #ifdef DFS_TESTING_SUPPORT || pmpriv->adapter->dfs_test_params. no_channel_change_on_radar || pmpriv->adapter->dfs_test_params.fixed_new_channel_on_radar #endif ) { /* Handle embedded DFS */ if (pmpriv->adapter->state_rdh.stage == RDH_SET_CUSTOM_IE) { pmadapter->state_rdh.stage = RDH_RESTART_TRAFFIC; wlan_11h_radar_detected_handling(pmadapter, pmpriv); } } else { /* Handle Host-based DFS and non-DFS(normal uap) case */ pmpriv->intf_state_11h.tx_disabled = MFALSE; memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE); /* Setup event buffer */ pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE; pevent->event_len = sizeof(chan_band_info); pchan_band_info = (chan_band_info *) pevent->event_buf; /* Copy event data */ memcpy(pmadapter, (t_u8 *)&pchan_band_info->bandcfg, (t_u8 *)&pchan_info->bandcfg, sizeof(pchan_info->bandcfg)); pchan_band_info->channel = pchan_info->channel; if (pchan_band_info->bandcfg.chanWidth == CHAN_BW_80MHZ) pchan_band_info->center_chan = wlan_get_center_freq_idx(priv, BAND_AAC, pchan_info-> channel, CHANNEL_BW_80MHZ); pchan_band_info->is_11n_enabled = pmpriv->is_11n_enabled; wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_CHAN_SWITCH_COMPLETE, pevent); pevent->event_id = 0; } break; #ifdef WIFI_DIRECT_SUPPORT case EVENT_REMAIN_ON_CHANNEL_EXPIRED: PRINTM(MEVENT, "EVENT: REMAIN_ON_CHANNEL_EXPIRED reason=%d\n", *(t_u16 *)pmadapter->event_body); wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_FLUSH_RX_WORK, MNULL); pevent->event_id = MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED; break; #endif case EVENT_MULTI_CHAN_INFO: PRINTM(MEVENT, "EVENT: MULTI_CHAN_INFO\n"); wlan_handle_event_multi_chan_info(pmpriv, pmbuf); break; case EVENT_FW_DEBUG_INFO: memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE); pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_FW_DEBUG_INFO; pevent->event_len = pmbuf->data_len - sizeof(eventcause); memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause), pevent->event_len); PRINTM(MEVENT, "EVENT: FW Debug Info %s\n", (t_u8 *)pevent->event_buf); wlan_recv_event(pmpriv, pevent->event_id, pevent); pevent->event_id = 0; /* clear to avoid resending at end of fcn */ break; case EVENT_TX_STATUS_REPORT: PRINTM(MINFO, "EVENT: TX_STATUS\n"); pevent->event_id = MLAN_EVENT_ID_FW_TX_STATUS; break; case EVENT_BT_COEX_WLAN_PARA_CHANGE: PRINTM(MEVENT, "EVENT: BT coex wlan param update\n"); wlan_bt_coex_wlan_param_update_event(pmpriv, pmbuf); break; case EVENT_EXCEED_MAX_P2P_CONN: event_excd_p2p = (event_exceed_max_p2p_conn *) (pmbuf->pbuf + pmbuf->data_offset); PRINTM(MEVENT, "EVENT: EXCEED MAX P2P CONNECTION\n"); PRINTM(MEVENT, "REQUEST P2P MAC: " MACSTR "\n", MAC2STR(event_excd_p2p->peer_mac_addr)); pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; break; case EVENT_FW_HANG_REPORT: if (pmbuf->data_len < (sizeof(eventcause) + sizeof(t_u16))) { PRINTM(MEVENT, "EVENT: EVENT_FW_HANG_REPORT skip for len too short: %d\n", pmbuf->data_len); break; } PRINTM(MEVENT, "EVENT: EVENT_FW_HANG_REPORT reasoncode=%d\n", wlan_le16_to_cpu(*(t_u16 *) (pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause)))); pmadapter->fw_hang_report = MTRUE; wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL); break; default: pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; break; } if (pevent->event_id) { pevent->bss_index = pmpriv->bss_index; pevent->event_len = pmbuf->data_len; memcpy(pmadapter, (t_u8 *)pevent->event_buf, pmbuf->pbuf + pmbuf->data_offset, pevent->event_len); wlan_recv_event(pmpriv, pevent->event_id, pevent); } done: if (event_buf) pcb->moal_mfree(pmadapter->pmoal_handle, event_buf); LEAVE(); return ret; } /** * @brief This function issues commands to initialize firmware * * @param priv A pointer to mlan_private structure * @param first_bss flag for first BSS * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE */ mlan_status wlan_ops_uap_init_cmd(IN t_void *priv, IN t_u8 first_bss) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private pmpriv = (pmlan_private)priv; t_u16 last_cmd = 0; ENTER(); if (!pmpriv) { LEAVE(); return MLAN_STATUS_FAILURE; } if (first_bss) { if (wlan_adapter_init_cmd(pmpriv->adapter) == MLAN_STATUS_FAILURE) { ret = MLAN_STATUS_FAILURE; goto done; } } ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, HostCmd_ACT_GEN_GET, 0, MNULL, MNULL); if (ret) { ret = MLAN_STATUS_FAILURE; goto done; } last_cmd = HOST_CMD_APCMD_SYS_CONFIGURE; /** set last_init_cmd */ if (last_cmd) { pmpriv->adapter->last_init_cmd = last_cmd; ret = MLAN_STATUS_PENDING; } done: LEAVE(); return ret; }