blob: fb506cb161c01f0c6e1f393a7c2e37c2aefb2169 [file] [log] [blame]
/** @file mlan_sta_cmd.c
*
* @brief This file contains the handling of command.
* it prepares command and sends it to firmware when
* it is ready.
*
* Copyright (C) 2008-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:
10/21/2008: initial version
******************************************************/
#include "mlan.h"
#include "mlan_join.h"
#include "mlan_util.h"
#include "mlan_fw.h"
#include "mlan_main.h"
#include "mlan_wmm.h"
#include "mlan_11n.h"
#include "mlan_11ac.h"
#include "mlan_11h.h"
#include "mlan_sdio.h"
#include "mlan_meas.h"
/********************************************************
Local Variables
********************************************************/
/********************************************************
Global Variables
********************************************************/
/********************************************************
Local Functions
********************************************************/
/**
* @brief This function prepares command of RSSI info.
*
* @param pmpriv A pointer to mlan_private structure
* @param pcmd A pointer to HostCmd_DS_COMMAND structure
* @param cmd_action Command action
*
* @return MLAN_STATUS_SUCCESS
*/
static mlan_status
wlan_cmd_802_11_rssi_info(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *pcmd, IN t_u16 cmd_action)
{
ENTER();
pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_RSSI_INFO);
pcmd->size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RSSI_INFO) +
S_DS_GEN);
pcmd->params.rssi_info.action = wlan_cpu_to_le16(cmd_action);
pcmd->params.rssi_info.ndata =
wlan_cpu_to_le16(pmpriv->data_avg_factor);
pcmd->params.rssi_info.nbcn = wlan_cpu_to_le16(pmpriv->bcn_avg_factor);
/* Reset SNR/NF/RSSI values in private structure */
pmpriv->data_rssi_last = 0;
pmpriv->data_nf_last = 0;
pmpriv->data_rssi_avg = 0;
pmpriv->data_nf_avg = 0;
pmpriv->bcn_rssi_last = 0;
pmpriv->bcn_nf_last = 0;
pmpriv->bcn_rssi_avg = 0;
pmpriv->bcn_nf_avg = 0;
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 OID: ENABLE or DISABLE
* @param pdata_buf A pointer to command information buffer
*
* @return MLAN_STATUS_SUCCESS
*/
static mlan_status
wlan_cmd_802_11_snmp_mib(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action,
IN t_u32 cmd_oid, IN t_void *pdata_buf)
{
HostCmd_DS_802_11_SNMP_MIB *psnmp_mib = &cmd->params.smib;
t_u32 ul_temp;
ENTER();
PRINTM(MINFO, "SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
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;
if (cmd_action == HostCmd_ACT_GEN_GET) {
psnmp_mib->query_type = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
psnmp_mib->buf_size = wlan_cpu_to_le16(MAX_SNMP_BUF_SIZE);
cmd->size += MAX_SNMP_BUF_SIZE;
}
switch (cmd_oid) {
case DtimPeriod_i:
psnmp_mib->oid = wlan_cpu_to_le16((t_u16)DtimPeriod_i);
if (cmd_action == HostCmd_ACT_GEN_SET) {
psnmp_mib->query_type =
wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8));
ul_temp = *((t_u32 *)pdata_buf);
psnmp_mib->value[0] = (t_u8)ul_temp;
cmd->size += sizeof(t_u8);
}
break;
case FragThresh_i:
psnmp_mib->oid = wlan_cpu_to_le16((t_u16)FragThresh_i);
if (cmd_action == HostCmd_ACT_GEN_SET) {
psnmp_mib->query_type =
wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
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 RtsThresh_i:
psnmp_mib->oid = wlan_cpu_to_le16((t_u16)RtsThresh_i);
if (cmd_action == HostCmd_ACT_GEN_SET) {
psnmp_mib->query_type =
wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
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 ShortRetryLim_i:
psnmp_mib->oid = wlan_cpu_to_le16((t_u16)ShortRetryLim_i);
if (cmd_action == HostCmd_ACT_GEN_SET) {
psnmp_mib->query_type =
wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
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 Dot11D_i:
psnmp_mib->oid = wlan_cpu_to_le16((t_u16)Dot11D_i);
if (cmd_action == HostCmd_ACT_GEN_SET) {
psnmp_mib->query_type =
wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
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 Dot11H_i:
psnmp_mib->oid = wlan_cpu_to_le16((t_u16)Dot11H_i);
if (cmd_action == HostCmd_ACT_GEN_SET) {
psnmp_mib->query_type =
wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
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 WwsMode_i:
psnmp_mib->oid = wlan_cpu_to_le16((t_u16)WwsMode_i);
if (cmd_action == HostCmd_ACT_GEN_SET) {
psnmp_mib->query_type =
wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
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 Thermal_i:
psnmp_mib->oid = wlan_cpu_to_le16((t_u16)Thermal_i);
break;
case NullPktPeriod_i:
/** keep alive null data pkt interval in full power mode */
psnmp_mib->oid = wlan_cpu_to_le16((t_u16)NullPktPeriod_i);
if (cmd_action == HostCmd_ACT_GEN_SET) {
psnmp_mib->query_type =
wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u32));
ul_temp = *((t_u32 *)pdata_buf);
*((t_u32 *)(psnmp_mib->value)) =
wlan_cpu_to_le32((t_u32)ul_temp);
cmd->size += sizeof(t_u32);
}
break;
default:
break;
}
cmd->size = wlan_cpu_to_le16(cmd->size);
PRINTM(MINFO,
"SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x, Value=0x%x\n",
cmd_action, cmd_oid, wlan_le16_to_cpu(psnmp_mib->buf_size),
wlan_le16_to_cpu(*(t_u16 *)psnmp_mib->value));
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @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_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 tx_power_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_cmd_tx_power_cfg(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
MrvlTypes_Power_Group_t *ppg_tlv = MNULL;
HostCmd_DS_TXPWR_CFG *ptxp = MNULL;
HostCmd_DS_TXPWR_CFG *ptxp_cfg = &cmd->params.txp_cfg;
ENTER();
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TXPWR_CFG);
cmd->size = wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_TXPWR_CFG));
switch (cmd_action) {
case HostCmd_ACT_GEN_SET:
ptxp = (HostCmd_DS_TXPWR_CFG *)pdata_buf;
if (ptxp->mode) {
ppg_tlv =
(MrvlTypes_Power_Group_t *)((t_u8 *)pdata_buf +
sizeof
(HostCmd_DS_TXPWR_CFG));
memmove(pmpriv->adapter, ptxp_cfg, pdata_buf,
sizeof(HostCmd_DS_TXPWR_CFG) +
sizeof(MrvlTypes_Power_Group_t) +
ppg_tlv->length);
ppg_tlv = (MrvlTypes_Power_Group_t *)((t_u8 *)ptxp_cfg +
sizeof
(HostCmd_DS_TXPWR_CFG));
cmd->size +=
wlan_cpu_to_le16(sizeof(MrvlTypes_Power_Group_t)
+ ppg_tlv->length);
ppg_tlv->type = wlan_cpu_to_le16(ppg_tlv->type);
ppg_tlv->length = wlan_cpu_to_le16(ppg_tlv->length);
} else {
memmove(pmpriv->adapter, ptxp_cfg, pdata_buf,
sizeof(HostCmd_DS_TXPWR_CFG));
}
ptxp_cfg->action = wlan_cpu_to_le16(cmd_action);
ptxp_cfg->cfg_index = wlan_cpu_to_le16(ptxp_cfg->cfg_index);
ptxp_cfg->mode = wlan_cpu_to_le32(ptxp_cfg->mode);
break;
case HostCmd_ACT_GEN_GET:
ptxp_cfg->action = wlan_cpu_to_le16(cmd_action);
break;
}
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of rf_tx_power.
*
* @param pmpriv A pointer to wlan_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_cmd_802_11_rf_tx_power(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
HostCmd_DS_802_11_RF_TX_POWER *prtp = &cmd->params.txp;
ENTER();
cmd->size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_RF_TX_POWER))
+ S_DS_GEN);
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_TX_POWER);
prtp->action = cmd_action;
PRINTM(MINFO, "RF_TX_POWER_CMD: Size:%d Cmd:0x%x Act:%d\n",
cmd->size, cmd->command, prtp->action);
switch (cmd_action) {
case HostCmd_ACT_GEN_GET:
prtp->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
prtp->current_level = 0;
break;
case HostCmd_ACT_GEN_SET:
prtp->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
prtp->current_level = wlan_cpu_to_le16(*((t_s16 *)pdata_buf));
break;
}
LEAVE();
return MLAN_STATUS_SUCCESS;
}
#ifdef WIFI_DIRECT_SUPPORT
/**
* @brief Check if any p2p interface is conencted
*
* @param pmadapter A pointer to mlan_adapter structure
*
* @return MTRUE/MFALSE;
*/
static t_u8
wlan_is_p2p_connected(IN pmlan_adapter pmadapter)
{
int j;
pmlan_private priv;
ENTER();
for (j = 0; j < pmadapter->priv_num; ++j) {
priv = pmadapter->priv[j];
if (priv) {
if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
if ((priv->bss_role == MLAN_BSS_ROLE_STA) &&
(priv->media_connected == MTRUE)) {
LEAVE();
return MTRUE;
}
if ((priv->bss_role == MLAN_BSS_ROLE_UAP) &&
(priv->uap_bss_started == MTRUE)) {
LEAVE();
return MTRUE;
}
}
}
}
LEAVE();
return MFALSE;
}
#endif
/**
* @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_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 = &cmd->params.opt_hs_cfg;
t_u16 hs_activate = MFALSE;
t_u8 *tlv = (t_u8 *)phs_cfg + sizeof(HostCmd_DS_802_11_HS_CFG_ENH);
MrvlIEtypes_HsWakeHoldoff_t *holdoff_tlv = MNULL;
ENTER();
if (pdata_buf == MNULL) {
/* New Activate command */
hs_activate = MTRUE;
}
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
if (!hs_activate && (pdata_buf->conditions != HOST_SLEEP_CFG_CANCEL)
&& ((pmadapter->arp_filter_size > 0)
&& (pmadapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
PRINTM(MINFO, "Attach %d bytes ArpFilter to HSCfg cmd\n",
pmadapter->arp_filter_size);
memcpy(pmpriv->adapter,
((t_u8 *)phs_cfg) + sizeof(HostCmd_DS_802_11_HS_CFG_ENH),
pmadapter->arp_filter, pmadapter->arp_filter_size);
cmd->size =
pmadapter->arp_filter_size +
sizeof(HostCmd_DS_802_11_HS_CFG_ENH) + S_DS_GEN;
tlv = (t_u8 *)phs_cfg + sizeof(HostCmd_DS_802_11_HS_CFG_ENH) +
pmadapter->arp_filter_size;
} else
cmd->size = S_DS_GEN + sizeof(HostCmd_DS_802_11_HS_CFG_ENH);
if (hs_activate) {
cmd->size = wlan_cpu_to_le16(cmd->size);
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);
#ifdef WIFI_DIRECT_SUPPORT
if (wlan_is_p2p_connected(pmadapter))
phs_cfg->params.hs_config.conditions =
wlan_cpu_to_le32(pdata_buf->
conditions |
HOST_SLEEP_COND_MULTICAST_DATA);
else
#endif
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 (pmadapter->min_wake_holdoff) {
cmd->size += 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(pmadapter->min_wake_holdoff);
PRINTM(MCMND, "min_wake_holdoff=%d\n",
pmadapter->min_wake_holdoff);
}
cmd->size = wlan_cpu_to_le16(cmd->size);
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,
pmadapter->min_wake_holdoff);
}
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of mac_address.
*
* @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
*
* @return MLAN_STATUS_SUCCESS
*/
static mlan_status
wlan_cmd_802_11_mac_address(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd, IN t_u16 cmd_action)
{
ENTER();
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS);
cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_MAC_ADDRESS) +
S_DS_GEN);
cmd->result = 0;
cmd->params.mac_addr.action = wlan_cpu_to_le16(cmd_action);
if (cmd_action == HostCmd_ACT_GEN_SET) {
memcpy(pmpriv->adapter, cmd->params.mac_addr.mac_addr,
pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH);
/* HEXDUMP("SET_CMD: MAC ADDRESS-", priv->CurrentAddr, 6); */
}
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of sleep_period.
*
* @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_cmd_802_11_sleep_period(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_u16 *pdata_buf)
{
HostCmd_DS_802_11_SLEEP_PERIOD *pcmd_sleep_pd = &cmd->params.sleep_pd;
ENTER();
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SLEEP_PERIOD);
cmd->size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_SLEEP_PERIOD) +
S_DS_GEN);
if (cmd_action == HostCmd_ACT_GEN_SET) {
pcmd_sleep_pd->sleep_pd = wlan_cpu_to_le16(*(t_u16 *)pdata_buf);
}
pcmd_sleep_pd->action = wlan_cpu_to_le16(cmd_action);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of sleep_params.
*
* @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_cmd_802_11_sleep_params(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_u16 *pdata_buf)
{
HostCmd_DS_802_11_SLEEP_PARAMS *pcmd_sp = &cmd->params.sleep_param;
mlan_ds_sleep_params *psp = (mlan_ds_sleep_params *)pdata_buf;
ENTER();
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SLEEP_PARAMS);
cmd->size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_SLEEP_PARAMS) +
S_DS_GEN);
if (cmd_action == HostCmd_ACT_GEN_SET) {
pcmd_sp->reserved = (t_u16)psp->reserved;
pcmd_sp->error = (t_u16)psp->error;
pcmd_sp->offset = (t_u16)psp->offset;
pcmd_sp->stable_time = (t_u16)psp->stable_time;
pcmd_sp->cal_control = (t_u8)psp->cal_control;
pcmd_sp->external_sleep_clk = (t_u8)psp->ext_sleep_clk;
pcmd_sp->reserved = wlan_cpu_to_le16(pcmd_sp->reserved);
pcmd_sp->error = wlan_cpu_to_le16(pcmd_sp->error);
pcmd_sp->offset = wlan_cpu_to_le16(pcmd_sp->offset);
pcmd_sp->stable_time = wlan_cpu_to_le16(pcmd_sp->stable_time);
}
pcmd_sp->action = wlan_cpu_to_le16(cmd_action);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of mac_multicast_adr.
*
* @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_cmd_mac_multicast_adr(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
mlan_multicast_list *pmcast_list = (mlan_multicast_list *)pdata_buf;
HostCmd_DS_MAC_MULTICAST_ADR *pmc_addr = &cmd->params.mc_addr;
ENTER();
cmd->size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_MULTICAST_ADR) +
S_DS_GEN);
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR);
pmc_addr->action = wlan_cpu_to_le16(cmd_action);
pmc_addr->num_of_adrs =
wlan_cpu_to_le16((t_u16)pmcast_list->num_multicast_addr);
memcpy(pmpriv->adapter, pmc_addr->mac_list, pmcast_list->mac_list,
pmcast_list->num_multicast_addr * MLAN_MAC_ADDR_LENGTH);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of deauthenticate/disassociate.
*
* @param pmpriv A pointer to mlan_private structure
* @param cmd_no Command number
* @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_cmd_802_11_deauthenticate(IN pmlan_private pmpriv,
IN t_u16 cmd_no,
IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
{
HostCmd_DS_802_11_DEAUTHENTICATE *pdeauth = &cmd->params.deauth;
ENTER();
cmd->command = wlan_cpu_to_le16(cmd_no);
cmd->size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_DEAUTHENTICATE) +
S_DS_GEN);
/* Set AP MAC address */
memcpy(pmpriv->adapter, pdeauth->mac_addr, (t_u8 *)pdata_buf,
MLAN_MAC_ADDR_LENGTH);
if (cmd_no == HostCmd_CMD_802_11_DEAUTHENTICATE)
PRINTM(MCMND, "Deauth: " MACSTR "\n",
MAC2STR(pdeauth->mac_addr));
else
PRINTM(MCMND, "Disassociate: " MACSTR "\n",
MAC2STR(pdeauth->mac_addr));
if (pmpriv->adapter->state_11h.recvd_chanswann_event) {
/** Reason code 36 = Requested from peer station as it is leaving the BSS */
#define REASON_CODE_PEER_STA_LEAVING 36
pdeauth->reason_code =
wlan_cpu_to_le16(REASON_CODE_PEER_STA_LEAVING);
} else {
/** Reason code 3 = Station is leaving */
#define REASON_CODE_STA_LEAVING 3
pdeauth->reason_code =
wlan_cpu_to_le16(REASON_CODE_STA_LEAVING);
}
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of ad_hoc_stop.
*
* @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_cmd_802_11_ad_hoc_stop(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND *cmd)
{
ENTER();
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP);
cmd->size = wlan_cpu_to_le16(S_DS_GEN);
if (wlan_11h_is_active(pmpriv))
wlan_11h_activate(pmpriv, MNULL, MFALSE);
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 or MLAN_STATUS_FAILURE
*/
static mlan_status
wlan_cmd_802_11_key_material(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action,
IN t_u32 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;
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) {
PRINTM(MCMND, "GET Key\n");
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.length =
wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN);
memcpy(pmpriv->adapter, pkey_material->key_param_set.mac_addr,
pkey->mac_addr, MLAN_MAC_ADDR_LENGTH);
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;
pkey_material->key_param_set.key_info =
wlan_cpu_to_le16(pkey_material->key_param_set.key_info);
cmd->size =
wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) +
S_DS_GEN + KEY_PARAMS_FIXED_LEN +
sizeof(pkey_material->action));
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;
if (pkey->is_current_wep_key) {
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;
} else {
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_SET_TX_KEY)
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_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_RX_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(pkey->key_len);
memcpy(pmpriv->adapter,
pkey_material->key_param_set.key_params.wapi.key,
pkey->key_material, 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;
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;
}
if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) {
/* Enable default key for WPA/WPA2 */
if (!pmpriv->wpa_is_gtk_set)
pkey_material->key_param_set.key_info |=
KEY_INFO_DEFAULT_KEY;
} else {
pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY;
/* Enable unicast bit for WPA-NONE/ADHOC_AES */
if ((!pmpriv->sec_info.wpa2_enabled) &&
(pkey->key_flags & KEY_FLAG_SET_TX_KEY))
pkey_material->key_param_set.key_info |=
KEY_INFO_UCAST_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 send eapol pkt to FW
*
* @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_cmd_eapol_pkt(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
HostCmd_DS_EAPOL_PKT *eapol_pkt = &cmd->params.eapol_pkt;
mlan_buffer *pmbuf = (mlan_buffer *)pdata_buf;
ENTER();
eapol_pkt->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
cmd->size = sizeof(HostCmd_DS_EAPOL_PKT) + S_DS_GEN;
cmd->command = wlan_cpu_to_le16(cmd->command);
eapol_pkt->tlv_eapol.header.type = wlan_cpu_to_le16(TLV_TYPE_EAPOL_PKT);
eapol_pkt->tlv_eapol.header.len = wlan_cpu_to_le16(pmbuf->data_len);
memcpy(pmpriv->adapter, eapol_pkt->tlv_eapol.pkt_buf,
pmbuf->pbuf + pmbuf->data_offset, pmbuf->data_len);
cmd->size += pmbuf->data_len;
cmd->size = wlan_cpu_to_le16(cmd->size);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of supplicant pmk
*
* @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 or MLAN_STATUS_FAILURE
*/
static mlan_status
wlan_cmd_802_11_supplicant_pmk(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
MrvlIEtypes_PMK_t *ppmk_tlv = MNULL;
MrvlIEtypes_Passphrase_t *ppassphrase_tlv = MNULL;
MrvlIEtypes_SsIdParamSet_t *pssid_tlv = MNULL;
MrvlIEtypes_Bssid_t *pbssid_tlv = MNULL;
HostCmd_DS_802_11_SUPPLICANT_PMK *pesupplicant_psk =
&cmd->params.esupplicant_psk;
t_u8 *ptlv_buffer = (t_u8 *)pesupplicant_psk->tlv_buffer;
mlan_ds_passphrase *psk = (mlan_ds_passphrase *)pdata_buf;
t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
ENTER();
/*
* Parse the rest of the buf here
* 1) <ssid="valid ssid"> - This will get the passphrase, AKMP
* for specified ssid, if none specified then it will get all.
* Eg: iwpriv <mlanX> passphrase 0:ssid=marvell
* 2) <psk="psk">:<passphrase="passphare">:<bssid="00:50:43:ef:23:f3">
* <ssid="valid ssid"> - passphrase and psk cannot be provided to
* the same SSID, Takes one SSID at a time, If ssid= is present
* the it should contain a passphrase or psk. If no arguments are
* provided then AKMP=802.1x, and passphrase should be provided
* after association.
* End of each parameter should be followed by a ':'(except for the
* last parameter) as the delimiter. If ':' has to be used in
* an SSID then a '/' should be preceded to ':' as a escape.
* Eg:iwpriv <mlanX> passphrase
* "1:ssid=mrvl AP:psk=abcdefgh:bssid=00:50:43:ef:23:f3"
* iwpriv <mlanX> passphrase
* "1:ssid=mrvl/: AP:psk=abcdefgd:bssid=00:50:43:ef:23:f3"
* iwpriv <mlanX> passphrase "1:ssid=mrvlAP:psk=abcdefgd"
* 3) <ssid="valid ssid"> - This will clear the passphrase
* for specified ssid, if none specified then it will clear all.
* Eg: iwpriv <mlanX> passphrase 2:ssid=marvell
*/
/* -1 is for t_u8 TlvBuffer[1] as this should not be included */
cmd->size = sizeof(HostCmd_DS_802_11_SUPPLICANT_PMK) + S_DS_GEN - 1;
if (psk->ssid.ssid_len) {
pssid_tlv = (MrvlIEtypes_SsIdParamSet_t *)ptlv_buffer;
pssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SSID);
pssid_tlv->header.len =
(t_u16)MIN(MLAN_MAX_SSID_LENGTH, psk->ssid.ssid_len);
memcpy(pmpriv->adapter, (char *)pssid_tlv->ssid, psk->ssid.ssid,
MIN(MLAN_MAX_SSID_LENGTH, psk->ssid.ssid_len));
ptlv_buffer +=
(pssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
cmd->size +=
(pssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
pssid_tlv->header.len = wlan_cpu_to_le16(pssid_tlv->header.len);
}
if (memcmp
(pmpriv->adapter, (t_u8 *)&psk->bssid, zero_mac,
sizeof(zero_mac))) {
pbssid_tlv = (MrvlIEtypes_Bssid_t *)ptlv_buffer;
pbssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_BSSID);
pbssid_tlv->header.len = MLAN_MAC_ADDR_LENGTH;
memcpy(pmpriv->adapter, pbssid_tlv->bssid, (t_u8 *)&psk->bssid,
MLAN_MAC_ADDR_LENGTH);
ptlv_buffer +=
(pbssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
cmd->size +=
(pbssid_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
pbssid_tlv->header.len =
wlan_cpu_to_le16(pbssid_tlv->header.len);
}
if (psk->psk_type == MLAN_PSK_PASSPHRASE) {
ppassphrase_tlv = (MrvlIEtypes_Passphrase_t *)ptlv_buffer;
ppassphrase_tlv->header.type =
wlan_cpu_to_le16(TLV_TYPE_PASSPHRASE);
ppassphrase_tlv->header.len =
(t_u16)MIN(MLAN_MAX_PASSPHRASE_LENGTH,
psk->psk.passphrase.passphrase_len);
memcpy(pmpriv->adapter, ppassphrase_tlv->passphrase,
psk->psk.passphrase.passphrase,
MIN(MLAN_MAX_PASSPHRASE_LENGTH,
psk->psk.passphrase.passphrase_len));
ptlv_buffer +=
(ppassphrase_tlv->header.len +
sizeof(MrvlIEtypesHeader_t));
cmd->size +=
(ppassphrase_tlv->header.len +
sizeof(MrvlIEtypesHeader_t));
ppassphrase_tlv->header.len =
wlan_cpu_to_le16(ppassphrase_tlv->header.len);
}
if (psk->psk_type == MLAN_PSK_PMK) {
ppmk_tlv = (MrvlIEtypes_PMK_t *)ptlv_buffer;
ppmk_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_PMK);
ppmk_tlv->header.len = MLAN_MAX_KEY_LENGTH;
memcpy(pmpriv->adapter, ppmk_tlv->pmk, psk->psk.pmk.pmk,
MLAN_MAX_KEY_LENGTH);
ptlv_buffer +=
(ppmk_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
cmd->size +=
(ppmk_tlv->header.len + sizeof(MrvlIEtypesHeader_t));
ppmk_tlv->header.len = wlan_cpu_to_le16(ppmk_tlv->header.len);
}
if ((cmd_action == HostCmd_ACT_GEN_SET) &&
((pssid_tlv || pbssid_tlv) && (!ppmk_tlv && !ppassphrase_tlv))) {
PRINTM(MERROR,
"Invalid case,ssid/bssid present without pmk or passphrase\n");
LEAVE();
return MLAN_STATUS_FAILURE;
}
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SUPPLICANT_PMK);
pesupplicant_psk->action = wlan_cpu_to_le16(cmd_action);
pesupplicant_psk->cache_result = 0;
cmd->size = wlan_cpu_to_le16(cmd->size);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief Handle the supplicant profile command
*
* @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
*
* @return MLAN_STATUS_SUCCESS
*/
static mlan_status
wlan_cmd_802_11_supplicant_profile(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
HostCmd_DS_802_11_SUPPLICANT_PROFILE *sup_profile =
(HostCmd_DS_802_11_SUPPLICANT_PROFILE *)&(cmd->params.
esupplicant_profile);
MrvlIEtypes_EncrProto_t *encr_proto_tlv = MNULL;
MrvlIEtypes_Cipher_t *pcipher_tlv = MNULL;
t_u8 *ptlv_buffer = (t_u8 *)sup_profile->tlv_buf;
mlan_ds_esupp_mode *esupp = MNULL;
ENTER();
cmd->size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_SUPPLICANT_PROFILE) +
S_DS_GEN - 1);
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SUPPLICANT_PROFILE);
sup_profile->action = wlan_cpu_to_le16(cmd_action);
if ((cmd_action == HostCmd_ACT_GEN_SET) && pdata_buf) {
esupp = (mlan_ds_esupp_mode *)pdata_buf;
if (esupp->rsn_mode) {
encr_proto_tlv = (MrvlIEtypes_EncrProto_t *)ptlv_buffer;
encr_proto_tlv->header.type =
wlan_cpu_to_le16(TLV_TYPE_ENCRYPTION_PROTO);
encr_proto_tlv->header.len =
(t_u16)sizeof(encr_proto_tlv->rsn_mode);
encr_proto_tlv->rsn_mode =
wlan_cpu_to_le16(esupp->rsn_mode);
ptlv_buffer +=
(encr_proto_tlv->header.len +
sizeof(MrvlIEtypesHeader_t));
cmd->size +=
(encr_proto_tlv->header.len +
sizeof(MrvlIEtypesHeader_t));
encr_proto_tlv->header.len =
wlan_cpu_to_le16(encr_proto_tlv->header.len);
}
if (esupp->act_paircipher || esupp->act_groupcipher) {
pcipher_tlv = (MrvlIEtypes_Cipher_t *)ptlv_buffer;
pcipher_tlv->header.type =
wlan_cpu_to_le16(TLV_TYPE_CIPHER);
pcipher_tlv->header.len =
(t_u16)(sizeof(pcipher_tlv->pair_cipher) +
sizeof(pcipher_tlv->group_cipher));
if (esupp->act_paircipher) {
pcipher_tlv->pair_cipher =
wlan_cpu_to_le16(esupp->act_paircipher);
}
if (esupp->act_groupcipher) {
pcipher_tlv->group_cipher =
wlan_cpu_to_le16(esupp->
act_groupcipher);
}
ptlv_buffer +=
(pcipher_tlv->header.len +
sizeof(MrvlIEtypesHeader_t));
cmd->size +=
(pcipher_tlv->header.len +
sizeof(MrvlIEtypesHeader_t));
pcipher_tlv->header.len =
wlan_cpu_to_le16(pcipher_tlv->header.len);
}
}
cmd->size = wlan_cpu_to_le16(cmd->size);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of rf_channel.
*
* @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_cmd_802_11_rf_channel(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
HostCmd_DS_802_11_RF_CHANNEL *prf_chan = &cmd->params.rf_channel;
ENTER();
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_CHANNEL);
cmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RF_CHANNEL)
+ S_DS_GEN);
if (cmd_action == HostCmd_ACT_GEN_SET) {
if ((pmpriv->adapter->adhoc_start_band & BAND_A)
|| (pmpriv->adapter->adhoc_start_band & BAND_AN)
)
prf_chan->rf_type = HostCmd_SCAN_RADIO_TYPE_A;
SET_SECONDARYCHAN(prf_chan->rf_type,
pmpriv->adapter->chan_bandwidth);
prf_chan->rf_type = wlan_cpu_to_le16(prf_chan->rf_type);
prf_chan->current_channel =
wlan_cpu_to_le16(*((t_u16 *)pdata_buf));
}
prf_chan->action = wlan_cpu_to_le16(cmd_action);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of ibss_coalescing_status.
*
* @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 or MNULL
*
* @return MLAN_STATUS_SUCCESS
*/
static mlan_status
wlan_cmd_ibss_coalescing_status(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
HostCmd_DS_802_11_IBSS_STATUS *pibss_coal =
&(cmd->params.ibss_coalescing);
t_u16 enable = 0;
ENTER();
cmd->command =
wlan_cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS);
cmd->size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_IBSS_STATUS) +
S_DS_GEN);
cmd->result = 0;
pibss_coal->action = wlan_cpu_to_le16(cmd_action);
switch (cmd_action) {
case HostCmd_ACT_GEN_SET:
if (pdata_buf != MNULL)
enable = *(t_u16 *)pdata_buf;
pibss_coal->enable = wlan_cpu_to_le16(enable);
break;
/* In other case.. Nothing to do */
case HostCmd_ACT_GEN_GET:
default:
break;
}
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of mgmt IE list.
*
* @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_cmd_mgmt_ie_list(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
t_u16 req_len = 0, travel_len = 0;
custom_ie *cptr = MNULL;
mlan_ds_misc_custom_ie *cust_ie = MNULL;
HostCmd_DS_MGMT_IE_LIST_CFG *pmgmt_ie_list =
&(cmd->params.mgmt_ie_list);
ENTER();
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_MGMT_IE_LIST);
cmd->size = sizeof(HostCmd_DS_MGMT_IE_LIST_CFG) + S_DS_GEN;
cmd->result = 0;
pmgmt_ie_list->action = wlan_cpu_to_le16(cmd_action);
cust_ie = (mlan_ds_misc_custom_ie *)pdata_buf;
pmgmt_ie_list->ds_mgmt_ie.type = wlan_cpu_to_le16(cust_ie->type);
pmgmt_ie_list->ds_mgmt_ie.len = wlan_cpu_to_le16(cust_ie->len);
if (pmgmt_ie_list->ds_mgmt_ie.ie_data_list && 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);
}
if (cust_ie->len)
memcpy(pmpriv->adapter,
pmgmt_ie_list->ds_mgmt_ie.ie_data_list,
cust_ie->ie_data_list, cust_ie->len);
}
cmd->size -=
(MAX_MGMT_IE_INDEX_TO_FW * sizeof(custom_ie)) +
sizeof(tlvbuf_max_mgmt_ie);
cmd->size += cust_ie->len;
cmd->size = wlan_cpu_to_le16(cmd->size);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of TDLS configuration.
*
* @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 or MLAN_STATUS_FAILURE
*/
static mlan_status
wlan_cmd_tdls_config(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
t_u16 travel_len = 0;
mlan_ds_misc_tdls_config *tdls_config = MNULL;
tdls_all_config *tdls_all_cfg = MNULL;
HostCmd_DS_TDLS_CONFIG *ptdls_config_data =
&(cmd->params.tdls_config_data);
t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 };
ENTER();
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TDLS_CONFIG);
cmd->size = sizeof(HostCmd_DS_TDLS_CONFIG) + S_DS_GEN;
cmd->result = 0;
tdls_config = (mlan_ds_misc_tdls_config *)pdata_buf;
ptdls_config_data->tdls_info.tdls_action =
wlan_cpu_to_le16(tdls_config->tdls_action);
tdls_all_cfg = (tdls_all_config *)tdls_config->tdls_data;
switch (tdls_config->tdls_action) {
case WLAN_TDLS_CONFIG:
travel_len = sizeof(tdls_all_cfg->u.tdls_config);
tdls_all_cfg->u.tdls_config.enable =
wlan_cpu_to_le16(tdls_all_cfg->u.tdls_config.enable);
memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
&tdls_all_cfg->u.tdls_setup, travel_len);
break;
case WLAN_TDLS_SET_INFO:
travel_len = tdls_all_cfg->u.tdls_set.tlv_length;
if ((travel_len + sizeof(t_u16)) > MAX_TDLS_DATA_LEN) {
PRINTM(MERROR, "TDLS configuration overflow\n");
LEAVE();
return MLAN_STATUS_FAILURE;
}
memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
(t_u8 *)&tdls_all_cfg->u.tdls_set.cap_info,
sizeof(t_u16));
memcpy(pmpriv->adapter,
(t_u8 *)ptdls_config_data->tdls_info.tdls_data +
sizeof(t_u16), &tdls_all_cfg->u.tdls_set.tlv_buffer,
travel_len);
travel_len += sizeof(t_u16);
break;
case WLAN_TDLS_DISCOVERY_REQ:
travel_len = MLAN_MAC_ADDR_LENGTH;
memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
tdls_all_cfg->u.tdls_discovery.peer_mac_addr,
travel_len);
break;
case WLAN_TDLS_SETUP_REQ:
travel_len = sizeof(tdls_all_cfg->u.tdls_setup);
tdls_all_cfg->u.tdls_setup.setup_timeout =
wlan_cpu_to_le32(tdls_all_cfg->u.tdls_setup.
setup_timeout);
tdls_all_cfg->u.tdls_setup.key_lifetime =
wlan_cpu_to_le32(tdls_all_cfg->u.tdls_setup.
key_lifetime);
memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
&tdls_all_cfg->u.tdls_setup, travel_len);
break;
case WLAN_TDLS_TEAR_DOWN_REQ:
travel_len = sizeof(tdls_all_cfg->u.tdls_tear_down);
tdls_all_cfg->u.tdls_tear_down.reason_code =
wlan_cpu_to_le16(tdls_all_cfg->u.tdls_tear_down.
reason_code);
memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
&tdls_all_cfg->u.tdls_tear_down, travel_len);
break;
case WLAN_TDLS_STOP_CHAN_SWITCH:
travel_len = MLAN_MAC_ADDR_LENGTH;
memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
tdls_all_cfg->u.tdls_stop_chan_switch.peer_mac_addr,
travel_len);
break;
case WLAN_TDLS_INIT_CHAN_SWITCH:
travel_len = sizeof(tdls_all_cfg->u.tdls_chan_switch);
tdls_all_cfg->u.tdls_chan_switch.switch_time =
wlan_cpu_to_le16(tdls_all_cfg->u.tdls_chan_switch.
switch_time);
tdls_all_cfg->u.tdls_chan_switch.switch_timeout =
wlan_cpu_to_le16(tdls_all_cfg->u.tdls_chan_switch.
switch_timeout);
memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
&tdls_all_cfg->u.tdls_chan_switch, travel_len);
break;
case WLAN_TDLS_CS_PARAMS:
travel_len = sizeof(tdls_all_cfg->u.tdls_cs_params);
memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
&tdls_all_cfg->u.tdls_cs_params, travel_len);
break;
case WLAN_TDLS_CS_DISABLE:
travel_len = sizeof(tdls_all_cfg->u.tdls_disable_cs);
tdls_all_cfg->u.tdls_disable_cs.data =
wlan_cpu_to_le16(tdls_all_cfg->u.tdls_disable_cs.data);
memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
&tdls_all_cfg->u.tdls_disable_cs, travel_len);
break;
case WLAN_TDLS_POWER_MODE:
travel_len = sizeof(tdls_all_cfg->u.tdls_power_mode);
tdls_all_cfg->u.tdls_power_mode.power_mode =
wlan_cpu_to_le16(tdls_all_cfg->u.tdls_power_mode.
power_mode);
memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
&tdls_all_cfg->u.tdls_power_mode, travel_len);
break;
case WLAN_TDLS_LINK_STATUS:
travel_len = 0;
if (memcmp
(pmpriv->adapter,
tdls_all_cfg->u.tdls_link_status_req.peer_mac_addr,
zero_mac, sizeof(zero_mac))) {
travel_len =
sizeof(tdls_all_cfg->u.tdls_link_status_req);
memcpy(pmpriv->adapter,
ptdls_config_data->tdls_info.tdls_data,
tdls_all_cfg->u.tdls_link_status_req.
peer_mac_addr, travel_len);
}
break;
case WLAN_TDLS_DEBUG_ALLOW_WEAK_SECURITY:
case WLAN_TDLS_DEBUG_SETUP_SAME_LINK:
case WLAN_TDLS_DEBUG_FAIL_SETUP_CONFIRM:
case WLAN_TDLS_DEBUG_WRONG_BSS:
case WLAN_TDLS_DEBUG_SETUP_PROHIBITED:
case WLAN_TDLS_DEBUG_HIGHER_LOWER_MAC:
case WLAN_TDLS_DEBUG_IGNORE_KEY_EXPIRY:
case WLAN_TDLS_DEBUG_STOP_RX:
case WLAN_TDLS_DEBUG_CS_RET_IM:
travel_len = sizeof(tdls_all_cfg->u.tdls_debug_data);
tdls_all_cfg->u.tdls_debug_data.debug_data =
wlan_cpu_to_le16(tdls_all_cfg->u.tdls_debug_data.
debug_data);
memcpy(pmpriv->adapter, ptdls_config_data->tdls_info.tdls_data,
&tdls_all_cfg->u.tdls_debug_data, travel_len);
break;
default:
LEAVE();
return MLAN_STATUS_FAILURE;
}
cmd->size += travel_len;
cmd->size -= MAX_TDLS_DATA_LEN;
cmd->size = wlan_cpu_to_le16(cmd->size);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of TDLS create/config/delete
*
* @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 or MLAN_STATUS_FAILURE
*/
static mlan_status
wlan_cmd_tdls_oper(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
t_u16 travel_len = 0;
mlan_ds_misc_tdls_oper *tdls_oper = MNULL;
HostCmd_DS_TDLS_OPER *ptdls_oper = &(cmd->params.tdls_oper_data);
sta_node *sta_ptr;
t_u8 *pos;
MrvlIEtypes_RatesParamSet_t *Rate_tlv = MNULL;
MrvlIETypes_HTCap_t *HTcap_tlv = MNULL;
MrvlIETypes_HTInfo_t *HTInfo_tlv = MNULL;
MrvlIETypes_2040BSSCo_t *BSSCo = MNULL;
MrvlIETypes_ExtCap_t *ExCap = MNULL;
MrvlIEtypes_RsnParamSet_t *Rsn_ie = MNULL;
MrvlIETypes_LinkIDElement_t *LinkID = MNULL;
BSSDescriptor_t *pbss_desc = &pmpriv->curr_bss_params.bss_descriptor;
MrvlIETypes_VHTCap_t *VHTcap_tlv = MNULL;
MrvlIETypes_VHTOprat_t *VHTOper_tlv = MNULL;
MrvlIETypes_AID_t *AidInfo = MNULL;
MrvlIEtypes_TDLS_Idle_Timeout_t *TdlsIdleTimeout = MNULL;
ENTER();
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_TDLS_OPERATION);
cmd->size = sizeof(HostCmd_DS_TDLS_OPER) + S_DS_GEN;
cmd->result = 0;
tdls_oper = (mlan_ds_misc_tdls_oper *)pdata_buf;
ptdls_oper->reason = 0;
memcpy(pmpriv->adapter, ptdls_oper->peer_mac, tdls_oper->peer_mac,
MLAN_MAC_ADDR_LENGTH);
sta_ptr = wlan_get_station_entry(pmpriv, tdls_oper->peer_mac);
pos = (t_u8 *)ptdls_oper + sizeof(HostCmd_DS_TDLS_OPER);
switch (tdls_oper->tdls_action) {
case WLAN_TDLS_CREATE_LINK:
if (sta_ptr)
sta_ptr->status = TDLS_SETUP_INPROGRESS;
ptdls_oper->tdls_action = wlan_cpu_to_le16(TDLS_CREATE);
break;
case WLAN_TDLS_CONFIG_LINK:
if (sta_ptr) {
ptdls_oper->tdls_action = wlan_cpu_to_le16(TDLS_CONFIG);
/* capability */
if (tdls_oper->capability)
*(t_u16 *)pos =
wlan_cpu_to_le16(tdls_oper->capability);
else
*(t_u16 *)pos =
wlan_cpu_to_le16(sta_ptr->capability);
travel_len += sizeof(sta_ptr->capability);
/* supported rate */
Rate_tlv =
(MrvlIEtypes_RatesParamSet_t *)(pos +
travel_len);
Rate_tlv->header.type =
wlan_cpu_to_le16(TLV_TYPE_RATES);
if (tdls_oper->supported_rates &&
tdls_oper->supported_rates_len) {
Rate_tlv->header.len =
wlan_cpu_to_le16(tdls_oper->
supported_rates_len);
memcpy(pmpriv->adapter,
pos + travel_len +
sizeof(MrvlIEtypesHeader_t),
tdls_oper->supported_rates,
tdls_oper->supported_rates_len);
travel_len +=
sizeof(MrvlIEtypesHeader_t) +
tdls_oper->supported_rates_len;
} else {
Rate_tlv->header.len =
wlan_cpu_to_le16(sta_ptr->rate_len);
memcpy(pmpriv->adapter,
pos + travel_len +
sizeof(MrvlIEtypesHeader_t),
sta_ptr->support_rate,
Rate_tlv->header.len);
travel_len +=
sizeof(MrvlIEtypesHeader_t) +
sta_ptr->rate_len;
}
/* Extended capability */
if (tdls_oper->ext_capab && tdls_oper->ext_capab_len) {
ExCap = (MrvlIETypes_ExtCap_t *)(pos +
travel_len);
ExCap->header.type =
wlan_cpu_to_le16(TLV_TYPE_EXTCAP);
ExCap->header.len =
wlan_cpu_to_le16(tdls_oper->
ext_capab_len);
memcpy(pmpriv->adapter,
pos + travel_len +
sizeof(MrvlIEtypesHeader_t),
tdls_oper->ext_capab,
tdls_oper->ext_capab_len);
travel_len +=
sizeof(MrvlIEtypesHeader_t) +
tdls_oper->ext_capab_len;
} else if (sta_ptr->ExtCap.ieee_hdr.element_id ==
EXT_CAPABILITY) {
ExCap = (MrvlIETypes_ExtCap_t *)(pos +
travel_len);
ExCap->header.type =
wlan_cpu_to_le16(TLV_TYPE_EXTCAP);
ExCap->header.len =
wlan_cpu_to_le16(sta_ptr->ExtCap.
ieee_hdr.len);
memcpy(pmpriv->adapter, &ExCap->ext_cap,
&sta_ptr->ExtCap.ext_cap,
sta_ptr->ExtCap.ieee_hdr.len);
travel_len +=
sta_ptr->ExtCap.ieee_hdr.len +
sizeof(MrvlIEtypesHeader_t);
}
/* RSN ie */
if (sta_ptr->rsn_ie.ieee_hdr.element_id == RSN_IE) {
Rsn_ie = (MrvlIEtypes_RsnParamSet_t *)(pos +
travel_len);
Rsn_ie->header.type =
wlan_cpu_to_le16(sta_ptr->rsn_ie.
ieee_hdr.element_id);
Rsn_ie->header.len =
wlan_cpu_to_le16(sta_ptr->rsn_ie.
ieee_hdr.len);
memcpy(pmpriv->adapter, Rsn_ie->rsn_ie,
sta_ptr->rsn_ie.data,
sta_ptr->rsn_ie.ieee_hdr.len);
travel_len +=
sta_ptr->rsn_ie.ieee_hdr.len +
sizeof(MrvlIEtypesHeader_t);
}
/* Link ID */
if (sta_ptr->link_ie.element_id == LINK_ID) {
LinkID = (MrvlIETypes_LinkIDElement_t *)(pos +
travel_len);
LinkID->header.type = wlan_cpu_to_le16(LINK_ID);
LinkID->header.len =
wlan_cpu_to_le16(sta_ptr->link_ie.len);
memcpy(pmpriv->adapter, &LinkID->bssid,
&sta_ptr->link_ie.bssid,
sta_ptr->link_ie.len);
travel_len +=
sta_ptr->link_ie.len +
sizeof(MrvlIEtypesHeader_t);
}
/* HT capability */
if (tdls_oper->ht_capa) {
HTcap_tlv =
(MrvlIETypes_HTCap_t *)(pos +
travel_len);
HTcap_tlv->header.type =
wlan_cpu_to_le16(TLV_TYPE_HT_CAP);
HTcap_tlv->header.len =
wlan_cpu_to_le16(sizeof(HTCap_t));
memcpy(pmpriv->adapter, &HTcap_tlv->ht_cap,
tdls_oper->ht_capa, sizeof(HTCap_t));
travel_len +=
sizeof(HTCap_t) +
sizeof(MrvlIEtypesHeader_t);
} else if (sta_ptr->HTcap.ieee_hdr.element_id ==
HT_CAPABILITY) {
HTcap_tlv =
(MrvlIETypes_HTCap_t *)(pos +
travel_len);
HTcap_tlv->header.type =
wlan_cpu_to_le16(TLV_TYPE_HT_CAP);
HTcap_tlv->header.len =
wlan_cpu_to_le16(sta_ptr->HTcap.
ieee_hdr.len);
memcpy(pmpriv->adapter, &HTcap_tlv->ht_cap,
&sta_ptr->HTcap.ht_cap,
sta_ptr->HTcap.ieee_hdr.len);
travel_len +=
sta_ptr->HTcap.ieee_hdr.len +
sizeof(MrvlIEtypesHeader_t);
}
if (HTcap_tlv) {
wlan_fill_ht_cap_tlv(pmpriv, HTcap_tlv,
pbss_desc->bss_band);
DBG_HEXDUMP(MCMD_D, "FW htcap",
(t_u8 *)HTcap_tlv,
sizeof(MrvlIETypes_HTCap_t));
}
/* HT info */
if (sta_ptr->HTInfo.ieee_hdr.element_id == HT_OPERATION) {
HTInfo_tlv =
(MrvlIETypes_HTInfo_t *)(pos +
travel_len);
HTInfo_tlv->header.type =
wlan_cpu_to_le16(TLV_TYPE_HT_INFO);
HTInfo_tlv->header.len =
wlan_cpu_to_le16(sta_ptr->HTInfo.
ieee_hdr.len);
memcpy(pmpriv->adapter, &HTInfo_tlv->ht_info,
&sta_ptr->HTInfo.ht_info,
sta_ptr->HTInfo.ieee_hdr.len);
travel_len +=
sta_ptr->HTInfo.ieee_hdr.len +
sizeof(MrvlIEtypesHeader_t);
DBG_HEXDUMP(MCMD_D, "HT Info",
(t_u8 *)HTInfo_tlv,
sizeof(MrvlIETypes_HTInfo_t));
}
/* 20/40 BSS co-exist */
if (sta_ptr->BSSCO_20_40.ieee_hdr.element_id ==
BSSCO_2040) {
BSSCo = (MrvlIETypes_2040BSSCo_t *)(pos +
travel_len);
BSSCo->header.type =
wlan_cpu_to_le16
(TLV_TYPE_2040BSS_COEXISTENCE);
BSSCo->header.len =
wlan_cpu_to_le16(sta_ptr->BSSCO_20_40.
ieee_hdr.len);
memcpy(pmpriv->adapter, &BSSCo->bss_co_2040,
&sta_ptr->BSSCO_20_40.bss_co_2040,
sta_ptr->BSSCO_20_40.ieee_hdr.len);
travel_len +=
sta_ptr->BSSCO_20_40.ieee_hdr.len +
sizeof(MrvlIEtypesHeader_t);
}
/* Check if we need enable the 11AC */
if (sta_ptr &&
sta_ptr->vht_oprat.ieee_hdr.element_id ==
VHT_OPERATION) {
/** AID */
if (sta_ptr->aid_info.ieee_hdr.element_id ==
AID_INFO) {
AidInfo =
(MrvlIETypes_AID_t *)(pos +
travel_len);
AidInfo->header.type =
wlan_cpu_to_le16(AID_INFO);
AidInfo->header.len =
wlan_cpu_to_le16(sta_ptr->
aid_info.
ieee_hdr.len);
AidInfo->AID =
wlan_cpu_to_le16(sta_ptr->
aid_info.AID);
}
/* Vht capability */
if (tdls_oper->vht_cap) {
VHTcap_tlv =
(MrvlIETypes_VHTCap_t *)(pos +
travel_len);
VHTcap_tlv->header.type =
wlan_cpu_to_le16
(VHT_CAPABILITY);
VHTcap_tlv->header.len =
wlan_cpu_to_le16(sizeof
(VHT_capa_t));
memcpy(pmpriv->adapter,
&VHTcap_tlv->vht_cap,
tdls_oper->vht_cap,
sizeof(VHT_capa_t));
travel_len +=
sizeof(MrvlIETypes_VHTCap_t);
} else if (sta_ptr->vht_cap.ieee_hdr.
element_id == VHT_CAPABILITY) {
VHTcap_tlv =
(MrvlIETypes_VHTCap_t *)(pos +
travel_len);
VHTcap_tlv->header.type =
wlan_cpu_to_le16
(VHT_CAPABILITY);
VHTcap_tlv->header.len =
wlan_cpu_to_le16(sta_ptr->
vht_cap.
ieee_hdr.len);
memcpy(pmpriv->adapter,
&VHTcap_tlv->vht_cap,
&sta_ptr->vht_cap.vht_cap,
sta_ptr->vht_cap.ieee_hdr.len);
travel_len +=
sta_ptr->vht_cap.ieee_hdr.len +
sizeof(MrvlIEtypesHeader_t);
}
if (VHTcap_tlv) {
wlan_fill_vht_cap_tlv(pmpriv,
VHTcap_tlv,
pbss_desc->
bss_band);
DBG_HEXDUMP(MCMD_D, "FW Vhtcap",
(t_u8 *)VHTcap_tlv,
sizeof
(MrvlIETypes_VHTCap_t));
}
/* Vht operation */
VHTOper_tlv =
(MrvlIETypes_VHTOprat_t *)(pos +
travel_len);
VHTOper_tlv->header.type =
wlan_cpu_to_le16(VHT_OPERATION);
VHTOper_tlv->header.len =
wlan_cpu_to_le16(sta_ptr->vht_oprat.
ieee_hdr.len);
memcpy(pmpriv->adapter,
&VHTOper_tlv->chan_width,
&sta_ptr->vht_oprat.chan_width,
sta_ptr->vht_oprat.ieee_hdr.len);
VHTOper_tlv->basic_MCS_map =
wlan_cpu_to_le16(VHTOper_tlv->
basic_MCS_map);
travel_len +=
sta_ptr->vht_oprat.ieee_hdr.len +
sizeof(MrvlIEtypesHeader_t);
DBG_HEXDUMP(MCMD_D, "VHT operation",
(t_u8 *)VHTOper_tlv,
sizeof(MrvlIETypes_VHTOprat_t));
}
TdlsIdleTimeout =
(MrvlIEtypes_TDLS_Idle_Timeout_t *)(pos +
travel_len);
TdlsIdleTimeout->header.type =
wlan_cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT);
TdlsIdleTimeout->header.len =
sizeof(TdlsIdleTimeout->value);
TdlsIdleTimeout->header.len =
wlan_cpu_to_le16(TdlsIdleTimeout->header.len);
if (pmpriv->tdls_idle_time == 0)
TdlsIdleTimeout->value =
wlan_cpu_to_le16(TDLS_IDLE_TIMEOUT);
else
TdlsIdleTimeout->value =
wlan_cpu_to_le16(pmpriv->
tdls_idle_time);
travel_len += sizeof(MrvlIEtypes_TDLS_Idle_Timeout_t);
}
break;
case WLAN_TDLS_DISABLE_LINK:
if (sta_ptr)
sta_ptr->status = TDLS_TEAR_DOWN;
ptdls_oper->tdls_action = wlan_cpu_to_le16(TDLS_DELETE);
break;
default:
break;
}
cmd->size += travel_len;
cmd->size = wlan_cpu_to_le16(cmd->size);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares system clock cfg command
*
* @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_cmd_sysclock_cfg(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG *cfg = &cmd->params.sys_clock_cfg;
mlan_ds_misc_sys_clock *clk_cfg = (mlan_ds_misc_sys_clock *)pdata_buf;
int i = 0;
ENTER();
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG);
cmd->size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_ECL_SYSTEM_CLOCK_CONFIG) +
S_DS_GEN);
cfg->action = wlan_cpu_to_le16(cmd_action);
cfg->cur_sys_clk = wlan_cpu_to_le16(clk_cfg->cur_sys_clk);
cfg->sys_clk_type = wlan_cpu_to_le16(clk_cfg->sys_clk_type);
cfg->sys_clk_len =
wlan_cpu_to_le16(clk_cfg->sys_clk_num) * sizeof(t_u16);
for (i = 0; i < clk_cfg->sys_clk_num; i++)
cfg->sys_clk[i] = wlan_cpu_to_le16(clk_cfg->sys_clk[i]);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of subscribe event.
*
* @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_cmd_subscribe_event(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
mlan_ds_subscribe_evt *sub_evt = (mlan_ds_subscribe_evt *)pdata_buf;
HostCmd_DS_SUBSCRIBE_EVENT *evt =
(HostCmd_DS_SUBSCRIBE_EVENT *)&cmd->params.subscribe_event;
t_u16 cmd_size = 0;
t_u8 *tlv = MNULL;
MrvlIEtypes_BeaconLowRssiThreshold_t *rssi_low = MNULL;
MrvlIEtypes_BeaconLowSnrThreshold_t *snr_low = MNULL;
MrvlIEtypes_FailureCount_t *fail_count = MNULL;
MrvlIEtypes_BeaconsMissed_t *beacon_missed = MNULL;
MrvlIEtypes_BeaconHighRssiThreshold_t *rssi_high = MNULL;
MrvlIEtypes_BeaconHighSnrThreshold_t *snr_high = MNULL;
MrvlIEtypes_DataLowRssiThreshold_t *data_rssi_low = MNULL;
MrvlIEtypes_DataLowSnrThreshold_t *data_snr_low = MNULL;
MrvlIEtypes_DataHighRssiThreshold_t *data_rssi_high = MNULL;
MrvlIEtypes_DataHighSnrThreshold_t *data_snr_high = MNULL;
MrvlIEtypes_LinkQualityThreshold_t *link_quality = MNULL;
MrvlIETypes_PreBeaconMissed_t *pre_bcn_missed = MNULL;
ENTER();
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SUBSCRIBE_EVENT);
evt->action = wlan_cpu_to_le16(cmd_action);
cmd_size = sizeof(HostCmd_DS_SUBSCRIBE_EVENT) + S_DS_GEN;
if (cmd_action == HostCmd_ACT_GEN_GET)
goto done;
evt->action = wlan_cpu_to_le16(sub_evt->evt_action);
evt->event_bitmap = wlan_cpu_to_le16(sub_evt->evt_bitmap);
tlv = (t_u8 *)cmd + cmd_size;
if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_RSSI_LOW) {
rssi_low = (MrvlIEtypes_BeaconLowRssiThreshold_t *)tlv;
rssi_low->header.type = wlan_cpu_to_le16(TLV_TYPE_RSSI_LOW);
rssi_low->header.len =
wlan_cpu_to_le16(sizeof
(MrvlIEtypes_BeaconLowRssiThreshold_t)
- sizeof(MrvlIEtypesHeader_t));
rssi_low->value = sub_evt->low_rssi;
rssi_low->frequency = sub_evt->low_rssi_freq;
tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
}
if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_SNR_LOW) {
snr_low = (MrvlIEtypes_BeaconLowSnrThreshold_t *)tlv;
snr_low->header.type = wlan_cpu_to_le16(TLV_TYPE_SNR_LOW);
snr_low->header.len =
wlan_cpu_to_le16(sizeof
(MrvlIEtypes_BeaconLowSnrThreshold_t) -
sizeof(MrvlIEtypesHeader_t));
snr_low->value = sub_evt->low_snr;
snr_low->frequency = sub_evt->low_snr_freq;
tlv += sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t);
cmd_size += sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t);
}
if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_MAX_FAIL) {
fail_count = (MrvlIEtypes_FailureCount_t *)tlv;
fail_count->header.type = wlan_cpu_to_le16(TLV_TYPE_FAILCOUNT);
fail_count->header.len =
wlan_cpu_to_le16(sizeof(MrvlIEtypes_FailureCount_t) -
sizeof(MrvlIEtypesHeader_t));
fail_count->value = sub_evt->failure_count;
fail_count->frequency = sub_evt->failure_count_freq;
tlv += sizeof(MrvlIEtypes_FailureCount_t);
cmd_size += sizeof(MrvlIEtypes_FailureCount_t);
}
if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_BEACON_MISSED) {
beacon_missed = (MrvlIEtypes_BeaconsMissed_t *)tlv;
beacon_missed->header.type = wlan_cpu_to_le16(TLV_TYPE_BCNMISS);
beacon_missed->header.len =
wlan_cpu_to_le16(sizeof(MrvlIEtypes_BeaconsMissed_t) -
sizeof(MrvlIEtypesHeader_t));
beacon_missed->value = sub_evt->beacon_miss;
beacon_missed->frequency = sub_evt->beacon_miss_freq;
tlv += sizeof(MrvlIEtypes_BeaconsMissed_t);
cmd_size += sizeof(MrvlIEtypes_BeaconsMissed_t);
}
if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_RSSI_HIGH) {
rssi_high = (MrvlIEtypes_BeaconHighRssiThreshold_t *)tlv;
rssi_high->header.type = wlan_cpu_to_le16(TLV_TYPE_RSSI_HIGH);
rssi_high->header.len =
wlan_cpu_to_le16(sizeof
(MrvlIEtypes_BeaconHighRssiThreshold_t)
- sizeof(MrvlIEtypesHeader_t));
rssi_high->value = sub_evt->high_rssi;
rssi_high->frequency = sub_evt->high_rssi_freq;
tlv += sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t);
cmd_size += sizeof(MrvlIEtypes_BeaconHighRssiThreshold_t);
}
if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_SNR_HIGH) {
snr_high = (MrvlIEtypes_BeaconHighSnrThreshold_t *)tlv;
snr_high->header.type = wlan_cpu_to_le16(TLV_TYPE_SNR_HIGH);
snr_high->header.len =
wlan_cpu_to_le16(sizeof
(MrvlIEtypes_BeaconHighSnrThreshold_t)
- sizeof(MrvlIEtypesHeader_t));
snr_high->value = sub_evt->high_snr;
snr_high->frequency = sub_evt->high_snr_freq;
tlv += sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t);
cmd_size += sizeof(MrvlIEtypes_BeaconHighSnrThreshold_t);
}
if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_DATA_RSSI_LOW) {
data_rssi_low = (MrvlIEtypes_DataLowRssiThreshold_t *)tlv;
data_rssi_low->header.type =
wlan_cpu_to_le16(TLV_TYPE_RSSI_LOW_DATA);
data_rssi_low->header.len =
wlan_cpu_to_le16(sizeof
(MrvlIEtypes_DataLowRssiThreshold_t) -
sizeof(MrvlIEtypesHeader_t));
data_rssi_low->value = sub_evt->data_low_rssi;
data_rssi_low->frequency = sub_evt->data_low_rssi_freq;
tlv += sizeof(MrvlIEtypes_DataLowRssiThreshold_t);
cmd_size += sizeof(MrvlIEtypes_DataLowRssiThreshold_t);
}
if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_DATA_SNR_LOW) {
data_snr_low = (MrvlIEtypes_DataLowSnrThreshold_t *)tlv;
data_snr_low->header.type =
wlan_cpu_to_le16(TLV_TYPE_SNR_LOW_DATA);
data_snr_low->header.len =
wlan_cpu_to_le16(sizeof
(MrvlIEtypes_DataLowSnrThreshold_t) -
sizeof(MrvlIEtypesHeader_t));
data_snr_low->value = sub_evt->data_low_snr;
data_snr_low->frequency = sub_evt->data_low_snr_freq;
tlv += sizeof(MrvlIEtypes_DataLowSnrThreshold_t);
cmd_size += sizeof(MrvlIEtypes_DataLowSnrThreshold_t);
}
if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_DATA_RSSI_HIGH) {
data_rssi_high = (MrvlIEtypes_DataHighRssiThreshold_t *)tlv;
data_rssi_high->header.type =
wlan_cpu_to_le16(TLV_TYPE_RSSI_HIGH_DATA);
data_rssi_high->header.len =
wlan_cpu_to_le16(sizeof
(MrvlIEtypes_DataHighRssiThreshold_t) -
sizeof(MrvlIEtypesHeader_t));
data_rssi_high->value = sub_evt->data_high_rssi;
data_rssi_high->frequency = sub_evt->data_high_rssi_freq;
tlv += sizeof(MrvlIEtypes_DataHighRssiThreshold_t);
cmd_size += sizeof(MrvlIEtypes_DataHighRssiThreshold_t);
}
if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_DATA_SNR_HIGH) {
data_snr_high = (MrvlIEtypes_DataHighSnrThreshold_t *)tlv;
data_snr_high->header.type =
wlan_cpu_to_le16(TLV_TYPE_SNR_HIGH_DATA);
data_snr_high->header.len =
wlan_cpu_to_le16(sizeof
(MrvlIEtypes_DataHighSnrThreshold_t) -
sizeof(MrvlIEtypesHeader_t));
data_snr_high->value = sub_evt->data_high_snr;
data_snr_high->frequency = sub_evt->data_high_snr_freq;
tlv += sizeof(MrvlIEtypes_DataHighSnrThreshold_t);
cmd_size += sizeof(MrvlIEtypes_DataHighSnrThreshold_t);
}
if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_LINK_QUALITY) {
link_quality = (MrvlIEtypes_LinkQualityThreshold_t *)tlv;
link_quality->header.type =
wlan_cpu_to_le16(TLV_TYPE_LINK_QUALITY);
link_quality->header.len =
wlan_cpu_to_le16(sizeof
(MrvlIEtypes_LinkQualityThreshold_t) -
sizeof(MrvlIEtypesHeader_t));
link_quality->link_snr = wlan_cpu_to_le16(sub_evt->link_snr);
link_quality->link_snr_freq =
wlan_cpu_to_le16(sub_evt->link_snr_freq);
link_quality->link_rate = wlan_cpu_to_le16(sub_evt->link_rate);
link_quality->link_rate_freq =
wlan_cpu_to_le16(sub_evt->link_rate_freq);
link_quality->link_tx_latency =
wlan_cpu_to_le16(sub_evt->link_tx_latency);
link_quality->link_tx_lantency_freq =
wlan_cpu_to_le16(sub_evt->link_tx_lantency_freq);
tlv += sizeof(MrvlIEtypes_LinkQualityThreshold_t);
cmd_size += sizeof(MrvlIEtypes_LinkQualityThreshold_t);
}
if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_PRE_BEACON_LOST) {
pre_bcn_missed = (MrvlIETypes_PreBeaconMissed_t *)tlv;
pre_bcn_missed->header.type =
wlan_cpu_to_le16(TLV_TYPE_PRE_BCNMISS);
pre_bcn_missed->header.len =
wlan_cpu_to_le16(sizeof(MrvlIETypes_PreBeaconMissed_t) -
sizeof(MrvlIEtypesHeader_t));
pre_bcn_missed->value = sub_evt->pre_beacon_miss;
pre_bcn_missed->frequency = 0;
tlv += sizeof(MrvlIETypes_PreBeaconMissed_t);
cmd_size += sizeof(MrvlIETypes_PreBeaconMissed_t);
}
done:
cmd->size = wlan_cpu_to_le16(cmd_size);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of OTP user data.
*
* @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_cmd_otp_user_data(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
mlan_ds_misc_otp_user_data *user_data =
(mlan_ds_misc_otp_user_data *)pdata_buf;
HostCmd_DS_OTP_USER_DATA *cmd_user_data =
(HostCmd_DS_OTP_USER_DATA *)&cmd->params.otp_user_data;
t_u16 cmd_size = 0;
ENTER();
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_OTP_READ_USER_DATA);
cmd_size = sizeof(HostCmd_DS_OTP_USER_DATA) + S_DS_GEN - 1;
cmd_user_data->action = wlan_cpu_to_le16(cmd_action);
cmd_user_data->reserved = 0;
cmd_user_data->user_data_length =
wlan_cpu_to_le16(user_data->user_data_length);
cmd_size += user_data->user_data_length;
cmd->size = wlan_cpu_to_le16(cmd_size);
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares inactivity timeout command
*
* @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_cmd_inactivity_timeout(IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
pmlan_ds_inactivity_to inac_to;
HostCmd_DS_INACTIVITY_TIMEOUT_EXT *cmd_inac_to =
&cmd->params.inactivity_to;
ENTER();
inac_to = (mlan_ds_inactivity_to *)pdata_buf;
cmd->size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_INACTIVITY_TIMEOUT_EXT) +
S_DS_GEN);
cmd->command = wlan_cpu_to_le16(cmd->command);
cmd_inac_to->action = wlan_cpu_to_le16(cmd_action);
if (cmd_action == HostCmd_ACT_GEN_SET) {
cmd_inac_to->timeout_unit =
wlan_cpu_to_le16((t_u16)inac_to->timeout_unit);
cmd_inac_to->unicast_timeout =
wlan_cpu_to_le16((t_u16)inac_to->unicast_timeout);
cmd_inac_to->mcast_timeout =
wlan_cpu_to_le16((t_u16)inac_to->mcast_timeout);
cmd_inac_to->ps_entry_timeout =
wlan_cpu_to_le16((t_u16)inac_to->ps_entry_timeout);
}
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares Low Power 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
*/
static mlan_status
wlan_cmd_low_pwr_mode(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd, IN t_void *pdata_buf)
{
HostCmd_CONFIG_LOW_PWR_MODE *cmd_lpm_cfg =
&cmd->params.low_pwr_mode_cfg;
t_u8 *enable;
ENTER();
cmd->size = S_DS_GEN + sizeof(HostCmd_CONFIG_LOW_PWR_MODE);
enable = (t_u8 *)pdata_buf;
cmd->size = wlan_cpu_to_le16(cmd->size);
cmd->command = wlan_cpu_to_le16(cmd->command);
cmd_lpm_cfg->enable = *enable;
LEAVE();
return MLAN_STATUS_SUCCESS;
}
/**
* @brief This function prepares command of coalesce_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 pdata_buf A pointer to data buffer
*
* @return MLAN_STATUS_SUCCESS
*/
mlan_status
wlan_cmd_coalesce_config(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND *cmd,
IN t_u16 cmd_action, IN t_void *pdata_buf)
{
HostCmd_DS_COALESCE_CONFIG *coalesce_config =
&cmd->params.coalesce_config;
mlan_ds_coalesce_cfg *cfg = (mlan_ds_coalesce_cfg *) pdata_buf;
t_u16 cnt, idx, length;
struct coalesce_filt_field_param *param;
struct coalesce_receive_filt_rule *rule;
ENTER();
cmd->size = sizeof(HostCmd_DS_COALESCE_CONFIG) + S_DS_GEN;
cmd->command = wlan_cpu_to_le16(HostCmd_CMD_COALESCE_CFG);
coalesce_config->action = wlan_cpu_to_le16(cmd_action);
coalesce_config->num_of_rules = wlan_cpu_to_le16(cfg->num_of_rules);
if (cmd_action == HostCmd_ACT_GEN_SET) {
rule = coalesce_config->rule;
for (cnt = 0; cnt < cfg->num_of_rules; cnt++) {
rule->header.type =
wlan_cpu_to_le16(TLV_TYPE_COALESCE_RULE);
rule->max_coalescing_delay =
wlan_cpu_to_le16(cfg->rule[cnt].
max_coalescing_delay);
rule->pkt_type = cfg->rule[cnt].pkt_type;
rule->num_of_fields = cfg->rule[cnt].num_of_fields;
length = 0;
param = rule->params;
for (idx = 0; idx < cfg->rule[cnt].num_of_fields; idx++) {
param->operation =
cfg->rule[cnt].params[idx].operation;
param->operand_len =
cfg->rule[cnt].params[idx].operand_len;
param->offset =
wlan_cpu_to_le16(cfg->rule[cnt].
params[idx].offset);
memcpy(pmpriv->adapter,
param->operand_byte_stream,
cfg->rule[cnt].params[idx].
operand_byte_stream, param->operand_len);
length +=
sizeof(struct
coalesce_filt_field_param);
param++;
}
/* Total rule length is sizeof
max_coalescing_delay(t_u16), * num_of_fields(t_u8),
pkt_type(t_u8) and total length of the all * params */
rule->header.len =
wlan_cpu_to_le16(length + sizeof(t_u16) +
sizeof(t_u8) + sizeof(t_u8));
/* Add the rule length to the command size */
cmd->size +=
wlan_le16_to_cpu(rule->header.len) +
sizeof(MrvlIEtypesHeader_t);
rule = (void *)((t_u8 *)rule->params + length);
}
}
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_sta_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;
ENTER();
/* Prepare command */
switch (cmd_no) {
case HostCmd_CMD_GET_HW_SPEC:
ret = wlan_cmd_get_hw_spec(pmpriv, cmd_ptr);
break;
case HostCmd_CMD_CFG_DATA:
ret = wlan_cmd_cfg_data(pmpriv, cmd_ptr, cmd_action, 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_MAC_ADDRESS:
ret = wlan_cmd_802_11_mac_address(pmpriv, cmd_ptr, cmd_action);
break;
case HostCmd_CMD_MAC_MULTICAST_ADR:
ret = wlan_cmd_mac_multicast_adr(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_RF_ANTENNA:
ret = wlan_cmd_802_11_rf_antenna(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
case HostCmd_CMD_TXPWR_CFG:
ret = wlan_cmd_tx_power_cfg(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
case HostCmd_CMD_802_11_RF_TX_POWER:
ret = wlan_cmd_802_11_rf_tx_power(pmpriv, cmd_ptr,
cmd_action, 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_802_11_HS_CFG_ENH:
ret = wlan_cmd_802_11_hs_cfg(pmpriv, cmd_ptr, cmd_action,
(hs_config_param *)pdata_buf);
break;
case HostCmd_CMD_802_11_SLEEP_PERIOD:
ret = wlan_cmd_802_11_sleep_period(pmpriv, cmd_ptr,
cmd_action,
(t_u16 *)pdata_buf);
break;
case HostCmd_CMD_802_11_SLEEP_PARAMS:
ret = wlan_cmd_802_11_sleep_params(pmpriv, cmd_ptr,
cmd_action,
(t_u16 *)pdata_buf);
break;
case HostCmd_CMD_802_11_SCAN:
ret = wlan_cmd_802_11_scan(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_802_11_BG_SCAN_CONFIG:
ret = wlan_cmd_bgscan_config(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_802_11_BG_SCAN_QUERY:
ret = wlan_cmd_802_11_bg_scan_query(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_802_11_ASSOCIATE:
ret = wlan_cmd_802_11_associate(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_802_11_DEAUTHENTICATE:
case HostCmd_CMD_802_11_DISASSOCIATE:
ret = wlan_cmd_802_11_deauthenticate(pmpriv, cmd_no, cmd_ptr,
pdata_buf);
break;
case HostCmd_CMD_802_11_AD_HOC_START:
ret = wlan_cmd_802_11_ad_hoc_start(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_802_11_AD_HOC_JOIN:
ret = wlan_cmd_802_11_ad_hoc_join(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_802_11_AD_HOC_STOP:
ret = wlan_cmd_802_11_ad_hoc_stop(pmpriv, cmd_ptr);
break;
case HostCmd_CMD_802_11_GET_LOG:
ret = wlan_cmd_802_11_get_log(pmpriv, cmd_ptr);
break;
case HostCmd_CMD_RSSI_INFO:
ret = wlan_cmd_802_11_rssi_info(pmpriv, cmd_ptr, cmd_action);
break;
case HostCmd_CMD_802_11_SNMP_MIB:
ret = wlan_cmd_802_11_snmp_mib(pmpriv, cmd_ptr, cmd_action,
cmd_oid, 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_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_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 =
wlan_cpu_to_le32((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_802_11_RF_CHANNEL:
ret = wlan_cmd_802_11_rf_channel(pmpriv, cmd_ptr, cmd_action,
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_SOFT_RESET:
cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
cmd_ptr->size = wlan_cpu_to_le16(S_DS_GEN);
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_802_11_KEY_MATERIAL:
ret = wlan_cmd_802_11_key_material(pmpriv, cmd_ptr, cmd_action,
cmd_oid, pdata_buf);
break;
case HostCmd_CMD_SUPPLICANT_PMK:
ret = wlan_cmd_802_11_supplicant_pmk(pmpriv, cmd_ptr,
cmd_action, pdata_buf);
break;
case HostCmd_CMD_802_11_EAPOL_PKT:
ret = wlan_cmd_eapol_pkt(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
case HostCmd_CMD_SUPPLICANT_PROFILE:
ret = wlan_cmd_802_11_supplicant_profile(pmpriv, cmd_ptr,
cmd_action, pdata_buf);
break;
case HostCmd_CMD_802_11D_DOMAIN_INFO:
ret = wlan_cmd_802_11d_domain_info(pmpriv, cmd_ptr, cmd_action);
break;
case HostCmd_CMD_802_11_TPC_ADAPT_REQ:
case HostCmd_CMD_802_11_TPC_INFO:
case HostCmd_CMD_802_11_CHAN_SW_ANN:
case HostCmd_CMD_CHAN_REPORT_REQUEST:
ret = wlan_11h_cmd_process(pmpriv, cmd_ptr, 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_11AC_CFG:
ret = wlan_cmd_11ac_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf);
break;
#if 0
case HostCmd_CMD_RECONFIGURE_TX_BUFF:
ret = wlan_cmd_recfg_tx_buf(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
#endif
case HostCmd_CMD_TX_BF_CFG:
ret = wlan_cmd_tx_bf_cfg(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
case HostCmd_CMD_WMM_GET_STATUS:
PRINTM(MINFO, "WMM: WMM_GET_STATUS cmd sent\n");
cmd_ptr->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS);
cmd_ptr->size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_GET_STATUS) +
S_DS_GEN);
ret = MLAN_STATUS_SUCCESS;
break;
case HostCmd_CMD_WMM_ADDTS_REQ:
ret = wlan_cmd_wmm_addts_req(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_WMM_DELTS_REQ:
ret = wlan_cmd_wmm_delts_req(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_WMM_QUEUE_CONFIG:
ret = wlan_cmd_wmm_queue_config(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_WMM_QUEUE_STATS:
ret = wlan_cmd_wmm_queue_stats(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_WMM_TS_STATUS:
ret = wlan_cmd_wmm_ts_status(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
ret = wlan_cmd_ibss_coalescing_status(pmpriv, cmd_ptr,
cmd_action, pdata_buf);
break;
case HostCmd_CMD_MGMT_IE_LIST:
ret = wlan_cmd_mgmt_ie_list(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
case HostCmd_CMD_TDLS_CONFIG:
ret = wlan_cmd_tdls_config(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
case HostCmd_CMD_TDLS_OPERATION:
ret = wlan_cmd_tdls_oper(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
case HostCmd_CMD_802_11_SCAN_EXT:
ret = wlan_cmd_802_11_scan_ext(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_ECL_SYSTEM_CLOCK_CONFIG:
ret = wlan_cmd_sysclock_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_TARGET_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_INACTIVITY_TIMEOUT_EXT:
ret = wlan_cmd_inactivity_timeout(cmd_ptr, cmd_action,
pdata_buf);
break;
case HostCmd_CMD_SDIO_GPIO_INT_CONFIG:
ret = wlan_cmd_sdio_gpio_int(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
case HostCmd_CMD_SET_BSS_MODE:
cmd_ptr->command = wlan_cpu_to_le16(cmd_no);
#ifdef WIFI_DIRECT_SUPPORT
if (pdata_buf) {
cmd_ptr->params.bss_mode.con_type = *(t_u8 *)pdata_buf;
} else
#endif
if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
cmd_ptr->params.bss_mode.con_type =
CONNECTION_TYPE_ADHOC;
else if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA)
cmd_ptr->params.bss_mode.con_type =
CONNECTION_TYPE_INFRA;
cmd_ptr->size =
wlan_cpu_to_le16(sizeof(HostCmd_DS_SET_BSS_MODE) +
S_DS_GEN);
ret = MLAN_STATUS_SUCCESS;
break;
case HostCmd_CMD_MEASUREMENT_REQUEST:
case HostCmd_CMD_MEASUREMENT_REPORT:
ret = wlan_meas_cmd_process(pmpriv, cmd_ptr, pdata_buf);
break;
#ifdef WIFI_DIRECT_SUPPORT
case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL:
ret = wlan_cmd_remain_on_channel(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
case HOST_CMD_WIFI_DIRECT_MODE_CONFIG:
ret = wlan_cmd_wifi_direct_mode(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
#endif
case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
ret = wlan_cmd_subscribe_event(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
case HostCmd_CMD_OTP_READ_USER_DATA:
ret = wlan_cmd_otp_user_data(pmpriv, cmd_ptr, cmd_action,
pdata_buf);
break;
case HostCmd_CMD_HS_WAKEUP_REASON:
ret = wlan_cmd_hs_wakeup_reason(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;
#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 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_CONFIG_LOW_POWER_MODE:
ret = wlan_cmd_low_pwr_mode(pmpriv, cmd_ptr, pdata_buf);
break;
case HostCmd_CMD_COALESCE_CFG:
ret = wlan_cmd_coalesce_config(pmpriv, cmd_ptr,
cmd_action, pdata_buf);
break;
default:
PRINTM(MERROR, "PREP_CMD: unknown command- %#x\n", cmd_no);
ret = MLAN_STATUS_FAILURE;
break;
}
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_PENDING or MLAN_STATUS_FAILURE
*/
mlan_status
wlan_ops_sta_init_cmd(IN t_void *priv, IN t_u8 first_bss)
{
pmlan_private pmpriv = (pmlan_private)priv;
mlan_status ret = MLAN_STATUS_SUCCESS;
t_u16 enable = MTRUE;
mlan_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
ENTER();
if (first_bss == MTRUE) {
ret = wlan_adapter_init_cmd(pmpriv->adapter);
if (ret == MLAN_STATUS_FAILURE)
goto done;
}
/* get tx rate */
ret = wlan_prepare_cmd(pmpriv,
HostCmd_CMD_TX_RATE_CFG,
HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
if (ret) {
ret = MLAN_STATUS_FAILURE;
goto done;
}
pmpriv->data_rate = 0;
/* get tx power */
ret = wlan_prepare_cmd(pmpriv,
HostCmd_CMD_802_11_RF_TX_POWER,
HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
if (ret) {
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* set ibss coalescing_status */
ret = wlan_prepare_cmd(pmpriv,
HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
HostCmd_ACT_GEN_SET, 0, MNULL, &enable);
if (ret) {
ret = MLAN_STATUS_FAILURE;
goto done;
}
memset(pmpriv->adapter, &amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl));
amsdu_aggr_ctrl.enable = MLAN_ACT_ENABLE;
/* Send request to firmware */
ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_AMSDU_AGGR_CTRL,
HostCmd_ACT_GEN_SET, 0, MNULL,
(t_void *)&amsdu_aggr_ctrl);
if (ret) {
ret = MLAN_STATUS_FAILURE;
goto done;
}
/* MAC Control must be the last command in init_fw */
/* set MAC Control */
ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_MAC_CONTROL,
HostCmd_ACT_GEN_SET, 0, MNULL,
&pmpriv->curr_pkt_filter);
if (ret) {
ret = MLAN_STATUS_FAILURE;
goto done;
}
/** set last_init_cmd */
pmpriv->adapter->last_init_cmd = HostCmd_CMD_MAC_CONTROL;
if (first_bss == MFALSE) {
/* Get MAC address */
ret = wlan_prepare_cmd(pmpriv,
HostCmd_CMD_802_11_MAC_ADDRESS,
HostCmd_ACT_GEN_GET, 0, MNULL, MNULL);
if (ret) {
ret = MLAN_STATUS_FAILURE;
goto done;
}
pmpriv->adapter->last_init_cmd = HostCmd_CMD_802_11_MAC_ADDRESS;
}
ret = MLAN_STATUS_PENDING;
done:
LEAVE();
return ret;
}