blob: b17c583e66c0c29b0ff680bcc3811ced0b3dcbb3 [file] [log] [blame]
/*
* Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file parser_api.cc contains the code for parsing
* 802.11 messages.
* Author: Pierre Vandwalle
* Date: 03/18/02
* History:-
* Date Modified by Modification Information
* --------------------------------------------------------------------
*
*/
#include "sir_api.h"
#include "ani_global.h"
#include "parser_api.h"
#include "lim_utils.h"
#include "utils_parser.h"
#include "lim_ser_des_utils.h"
#include "sch_api.h"
#include "wmm_apsd.h"
#include "rrm_api.h"
#include "cds_regdomain.h"
#include "qdf_crypto.h"
#include "lim_process_fils.h"
#include "wlan_utility.h"
#include "wifi_pos_api.h"
#include "wlan_mlme_public_struct.h"
#include "wlan_mlme_ucfg_api.h"
#include "wlan_mlme_api.h"
#include "wlan_crypto_global_api.h"
#define RSN_OUI_SIZE 4
/* ////////////////////////////////////////////////////////////////////// */
void swap_bit_field16(uint16_t in, uint16_t *out)
{
#ifdef ANI_LITTLE_BIT_ENDIAN
*out = in;
#else /* Big-Endian... */
*out = ((in & 0x8000) >> 15) |
((in & 0x4000) >> 13) |
((in & 0x2000) >> 11) |
((in & 0x1000) >> 9) |
((in & 0x0800) >> 7) |
((in & 0x0400) >> 5) |
((in & 0x0200) >> 3) |
((in & 0x0100) >> 1) |
((in & 0x0080) << 1) |
((in & 0x0040) << 3) |
((in & 0x0020) << 5) |
((in & 0x0010) << 7) |
((in & 0x0008) << 9) |
((in & 0x0004) << 11) |
((in & 0x0002) << 13) | ((in & 0x0001) << 15);
#endif /* ANI_LITTLE_BIT_ENDIAN */
}
static inline void __print_wmm_params(struct mac_context *mac,
tDot11fIEWMMParams *pWmm)
{
pe_debug("WMM Parameters Received:");
pe_debug("BE: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d",
pWmm->acbe_aifsn, pWmm->acbe_acm, pWmm->acbe_aci,
pWmm->acbe_acwmin, pWmm->acbe_acwmax, pWmm->acbe_txoplimit);
pe_debug("BK: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d",
pWmm->acbk_aifsn, pWmm->acbk_acm, pWmm->acbk_aci,
pWmm->acbk_acwmin, pWmm->acbk_acwmax, pWmm->acbk_txoplimit);
pe_debug("VI: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d",
pWmm->acvi_aifsn, pWmm->acvi_acm, pWmm->acvi_aci,
pWmm->acvi_acwmin, pWmm->acvi_acwmax, pWmm->acvi_txoplimit);
pe_debug("VO: aifsn %d, acm %d, aci %d, cwmin %d, cwmax %d, txop %d",
pWmm->acvo_aifsn, pWmm->acvo_acm, pWmm->acvo_aci,
pWmm->acvo_acwmin, pWmm->acvo_acwmax, pWmm->acvo_txoplimit);
return;
}
/* ////////////////////////////////////////////////////////////////////// */
/* Functions for populating "dot11f" style IEs */
/* return: >= 0, the starting location of the IE in rsnIEdata inside tSirRSNie */
/* < 0, cannot find */
int find_ie_location(struct mac_context *mac, tpSirRSNie pRsnIe, uint8_t EID)
{
int idx, ieLen, bytesLeft;
int ret_val = -1;
/* Here's what's going on: 'rsnIe' looks like this: */
/* typedef struct sSirRSNie */
/* { */
/* uint16_t length; */
/* uint8_t rsnIEdata[WLAN_MAX_IE_LEN+2]; */
/* } tSirRSNie, *tpSirRSNie; */
/* other code records both the WPA & RSN IEs (including their EIDs & */
/* lengths) into the array 'rsnIEdata'. We may have: */
/* With WAPI support, there may be 3 IEs here */
/* It can be only WPA IE, or only RSN IE or only WAPI IE */
/* Or two or all three of them with no particular ordering */
/* The if/then/else statements that follow are here to figure out */
/* whether we have the WPA IE, and where it is if we *do* have it. */
/* Save the first IE length */
ieLen = pRsnIe->rsnIEdata[1] + 2;
idx = 0;
bytesLeft = pRsnIe->length;
while (1) {
if (EID == pRsnIe->rsnIEdata[idx])
/* Found it */
return idx;
if (EID != pRsnIe->rsnIEdata[idx] &&
/* & if no more IE, */
bytesLeft <= (uint16_t)(ieLen))
return ret_val;
bytesLeft -= ieLen;
ieLen = pRsnIe->rsnIEdata[idx + 1] + 2;
idx += ieLen;
}
return ret_val;
}
QDF_STATUS
populate_dot11f_capabilities(struct mac_context *mac,
tDot11fFfCapabilities *pDot11f,
struct pe_session *pe_session)
{
uint16_t cfg;
QDF_STATUS nSirStatus;
nSirStatus = lim_get_capability_info(mac, &cfg, pe_session);
if (QDF_STATUS_SUCCESS != nSirStatus) {
pe_err("Failed to retrieve the Capabilities bitfield from CFG status: %d",
nSirStatus);
return nSirStatus;
}
swap_bit_field16(cfg, (uint16_t *) pDot11f);
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_capabilities. */
/**
* populate_dot_11_f_ext_chann_switch_ann() - Function to populate ECS
* @mac_ptr: Pointer to PMAC structure
* @dot_11_ptr: ECS element
* @session_entry: PE session entry
*
* This function is used to populate the extended channel switch element
*
* Return: None
*/
void populate_dot_11_f_ext_chann_switch_ann(struct mac_context *mac_ptr,
tDot11fIEext_chan_switch_ann *dot_11_ptr,
struct pe_session *session_entry)
{
uint8_t ch_offset;
uint32_t sw_target_freq;
uint8_t primary_channel;
enum phy_ch_width ch_width;
ch_width = session_entry->gLimChannelSwitch.ch_width;
ch_offset = session_entry->gLimChannelSwitch.sec_ch_offset;
dot_11_ptr->switch_mode = session_entry->gLimChannelSwitch.switchMode;
sw_target_freq = session_entry->gLimChannelSwitch.sw_target_freq;
primary_channel = session_entry->gLimChannelSwitch.primaryChannel;
dot_11_ptr->new_reg_class =
lim_op_class_from_bandwidth(mac_ptr, sw_target_freq, ch_width,
ch_offset);
dot_11_ptr->new_channel =
session_entry->gLimChannelSwitch.primaryChannel;
dot_11_ptr->switch_count =
session_entry->gLimChannelSwitch.switchCount;
dot_11_ptr->present = 1;
pe_debug("country:%s chan:%d freq %d width:%d reg:%d off:%d",
mac_ptr->scan.countryCodeCurrent,
session_entry->gLimChannelSwitch.primaryChannel,
sw_target_freq,
session_entry->gLimChannelSwitch.ch_width,
dot_11_ptr->new_reg_class,
session_entry->gLimChannelSwitch.sec_ch_offset);
}
void
populate_dot11f_chan_switch_ann(struct mac_context *mac,
tDot11fIEChanSwitchAnn *pDot11f,
struct pe_session *pe_session)
{
pDot11f->switchMode = pe_session->gLimChannelSwitch.switchMode;
pDot11f->newChannel = pe_session->gLimChannelSwitch.primaryChannel;
pDot11f->switchCount =
(uint8_t) pe_session->gLimChannelSwitch.switchCount;
pDot11f->present = 1;
}
/**
* populate_dot11_supp_operating_classes() - Function to populate supported
* operating class IE
* @mac_ptr: Pointer to PMAC structure
* @dot_11_ptr: Operating class element
* @session_entry: PE session entry
*
* Return: None
*/
void
populate_dot11_supp_operating_classes(struct mac_context *mac_ptr,
tDot11fIESuppOperatingClasses *dot_11_ptr,
struct pe_session *session_entry)
{
uint8_t ch_offset;
if (session_entry->ch_width == CH_WIDTH_80MHZ) {
ch_offset = BW80;
} else {
switch (session_entry->htSecondaryChannelOffset) {
case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
ch_offset = BW40_HIGH_PRIMARY;
break;
case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
ch_offset = BW40_LOW_PRIMARY;
break;
default:
ch_offset = BW20;
break;
}
}
wlan_reg_dmn_get_curr_opclasses(&dot_11_ptr->num_classes,
&dot_11_ptr->classes[1]);
dot_11_ptr->classes[0] =
lim_op_class_from_bandwidth(mac_ptr,
session_entry->curr_op_freq,
session_entry->ch_width,
ch_offset);
dot_11_ptr->num_classes++;
dot_11_ptr->present = 1;
}
void
populate_dot11f_vht_tx_power_env(struct mac_context *mac,
tDot11fIEvht_transmit_power_env *pDot11f,
enum phy_ch_width ch_width, uint32_t chan_freq)
{
uint8_t num_tx_power, i, tx_power;
int reg_max;
switch (ch_width) {
case CH_WIDTH_20MHZ:
/* Max Transmit Power count = 0 (20 MHz) */
num_tx_power = 0;
break;
case CH_WIDTH_40MHZ:
/* Max Transmit Power count = 1 (20, 40 MHz) */
num_tx_power = 1;
break;
case CH_WIDTH_80MHZ:
/* Max Transmit Power count = 2 (20, 40, and 80 MHz) */
num_tx_power = 2;
break;
case CH_WIDTH_160MHZ:
case CH_WIDTH_80P80MHZ:
/* Max Transmit Power count = 3 (20, 40, 80, 160/80+80 MHz) */
num_tx_power = 3;
break;
default:
return;
}
reg_max = wlan_reg_get_channel_reg_power_for_freq(mac->pdev, chan_freq);
/* in 0.5 dB steps */
reg_max *= 2;
if (reg_max > 127)
/* 63.5 has special meaning of 63.5 dBm or higher */
reg_max = 127;
if (reg_max < -128)
reg_max = -128;
if (reg_max < 0)
tx_power = 0x80 + reg_max + 128;
else
tx_power = reg_max;
/* Ignore EID field */
pDot11f->present = 1;
pDot11f->num_bytes = num_tx_power + 2;
/*
* Max Transmit Power count and
* Max Transmit Power units = 0 (EIRP)
*/
pDot11f->bytes[0] = num_tx_power;
for (i = 0; i <= num_tx_power; i++)
pDot11f->bytes[i + 1] = tx_power;
}
void
populate_dot11f_chan_switch_wrapper(struct mac_context *mac,
tDot11fIEChannelSwitchWrapper *pDot11f,
struct pe_session *pe_session)
{
/*
* The new country subelement is present only when
* 1. AP performs Extended Channel switching to new country.
* 2. New Operating Class table or a changed set of operating
* classes relative to the contents of the country element sent
* in the beacons.
*
* In the current scenario Channel Switch wrapper IE is included
* when we a radar is found and the AP does a channel change in
* the same regulatory domain(No country change or Operating class
* table). So, we do not need to include the New Country IE.
*
* Transmit Power Envlope Subelement is optional
* in Channel Switch Wrapper IE. So, not setting
* the TPE subelement. We include only WiderBWChanSwitchAnn.
*/
pDot11f->present = 1;
/*
* Add the Wide Channel Bandwidth Sublement.
*/
pDot11f->WiderBWChanSwitchAnn.newChanWidth =
pe_session->gLimWiderBWChannelSwitch.newChanWidth;
pDot11f->WiderBWChanSwitchAnn.newCenterChanFreq0 =
pe_session->gLimWiderBWChannelSwitch.newCenterChanFreq0;
pDot11f->WiderBWChanSwitchAnn.newCenterChanFreq1 =
pe_session->gLimWiderBWChannelSwitch.newCenterChanFreq1;
pDot11f->WiderBWChanSwitchAnn.present = 1;
/*
* Add the VHT Transmit power Envelope Sublement.
*/
if (pe_session->vhtCapability) {
populate_dot11f_vht_tx_power_env(mac,
&pDot11f->vht_transmit_power_env,
pe_session->gLimChannelSwitch.ch_width,
pe_session->gLimChannelSwitch.primaryChannel);
}
}
#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
void
populate_dot11f_avoid_channel_ie(struct mac_context *mac_ctx,
tDot11fIEQComVendorIE *dot11f,
struct pe_session *pe_session)
{
if (!pe_session->sap_advertise_avoid_ch_ie)
return;
dot11f->present = true;
dot11f->type = QCOM_VENDOR_IE_MCC_AVOID_CH;
dot11f->channel = wlan_reg_freq_to_chan(
mac_ctx->pdev, pe_session->curr_op_freq);
}
#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
QDF_STATUS
populate_dot11f_country(struct mac_context *mac,
tDot11fIECountry *pDot11f, struct pe_session *pe_session)
{
uint32_t len, j = 0;
enum reg_wifi_band rfBand;
uint8_t temp[CFG_MAX_STR_LEN], code[3];
tSirMacChanInfo *max_tx_power_data;
uint32_t rem_length = 0, copied_length = 0;
if (!pe_session->lim11dEnabled)
return QDF_STATUS_SUCCESS;
lim_get_rf_band_new(mac, &rfBand, pe_session);
if (rfBand == REG_BAND_5G) {
len = mac->mlme_cfg->power.max_tx_power_5.len;
max_tx_power_data =
(tSirMacChanInfo *)mac->mlme_cfg->power.max_tx_power_5.data;
rem_length = len;
while (rem_length >= (sizeof(tSirMacChanInfo))) {
temp[copied_length++] =
(uint8_t)wlan_reg_freq_to_chan(
mac->pdev,
max_tx_power_data[j].first_freq);
temp[copied_length++] =
max_tx_power_data[j].numChannels;
temp[copied_length++] =
max_tx_power_data[j].maxTxPower;
j++;
rem_length -= (sizeof(tSirMacChanInfo));
}
} else {
len = mac->mlme_cfg->power.max_tx_power_24.len;
max_tx_power_data =
(tSirMacChanInfo *)mac->mlme_cfg->power.max_tx_power_24.data;
rem_length = len;
while (rem_length >= (sizeof(tSirMacChanInfo))) {
temp[copied_length++] =
(uint8_t)wlan_reg_freq_to_chan(
mac->pdev,
max_tx_power_data[j].first_freq);
temp[copied_length++] =
max_tx_power_data[j].numChannels;
temp[copied_length++] =
max_tx_power_data[j].maxTxPower;
j++;
rem_length -= (sizeof(tSirMacChanInfo));
}
}
if (sizeof(tSirMacChanInfo) > len) {
/* no limit on tx power, cannot include the IE because at */
/* atleast one (channel,num,tx power) must be present */
return QDF_STATUS_SUCCESS;
}
wlan_reg_read_current_country(mac->psoc, code);
qdf_mem_copy(pDot11f->country, code, 2);
/* a wi-fi agile multiband AP shall include a country */
/* element in all beacon and probe response frames */
/* where the last octet of country string field is */
/* set to 0x04 */
if (mac->mlme_cfg->oce.oce_sap_enabled)
pDot11f->country[2] = 0x04;
if (copied_length > MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE) {
pe_err("len:%d is out of bounds, resetting", len);
copied_length = MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE;
}
pDot11f->num_triplets = (uint8_t)(copied_length / 3);
qdf_mem_copy((uint8_t *)pDot11f->triplets, temp, copied_length);
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_country. */
/**
* populate_dot11f_ds_params() - To populate DS IE params
* mac_ctx: Pointer to global mac context
* dot11f_param: pointer to DS params IE
* channel: channel number
*
* This routine will populate DS param in management frame like
* beacon, probe response, and etc.
*
* Return: Overall success
*/
QDF_STATUS
populate_dot11f_ds_params(struct mac_context *mac_ctx,
tDot11fIEDSParams *dot11f_param, uint8_t channel)
{
if (IS_24G_CH(channel)) {
/* .11b/g mode PHY => Include the DS Parameter Set IE: */
dot11f_param->curr_channel = channel;
dot11f_param->present = 1;
}
return QDF_STATUS_SUCCESS;
}
#define SET_AIFSN(aifsn) (((aifsn) < 2) ? 2 : (aifsn))
void
populate_dot11f_edca_param_set(struct mac_context *mac,
tDot11fIEEDCAParamSet *pDot11f,
struct pe_session *pe_session)
{
if (pe_session->limQosEnabled) {
/* change to bitwise operation, after this is fixed in frames. */
pDot11f->qos =
(uint8_t) (0xf0 &
(pe_session->gLimEdcaParamSetCount << 4));
/* Fill each EDCA parameter set in order: be, bk, vi, vo */
pDot11f->acbe_aifsn =
(0xf &
SET_AIFSN(pe_session->gLimEdcaParamsBC[0].aci.aifsn));
pDot11f->acbe_acm =
(0x1 & pe_session->gLimEdcaParamsBC[0].aci.acm);
pDot11f->acbe_aci = (0x3 & QCA_WLAN_AC_BE);
pDot11f->acbe_acwmin =
(0xf & pe_session->gLimEdcaParamsBC[0].cw.min);
pDot11f->acbe_acwmax =
(0xf & pe_session->gLimEdcaParamsBC[0].cw.max);
pDot11f->acbe_txoplimit =
pe_session->gLimEdcaParamsBC[0].txoplimit;
pDot11f->acbk_aifsn =
(0xf &
SET_AIFSN(pe_session->gLimEdcaParamsBC[1].aci.aifsn));
pDot11f->acbk_acm =
(0x1 & pe_session->gLimEdcaParamsBC[1].aci.acm);
pDot11f->acbk_aci = (0x3 & QCA_WLAN_AC_BK);
pDot11f->acbk_acwmin =
(0xf & pe_session->gLimEdcaParamsBC[1].cw.min);
pDot11f->acbk_acwmax =
(0xf & pe_session->gLimEdcaParamsBC[1].cw.max);
pDot11f->acbk_txoplimit =
pe_session->gLimEdcaParamsBC[1].txoplimit;
pDot11f->acvi_aifsn =
(0xf &
SET_AIFSN(pe_session->gLimEdcaParamsBC[2].aci.aifsn));
pDot11f->acvi_acm =
(0x1 & pe_session->gLimEdcaParamsBC[2].aci.acm);
pDot11f->acvi_aci = (0x3 & QCA_WLAN_AC_VI);
pDot11f->acvi_acwmin =
(0xf & pe_session->gLimEdcaParamsBC[2].cw.min);
pDot11f->acvi_acwmax =
(0xf & pe_session->gLimEdcaParamsBC[2].cw.max);
pDot11f->acvi_txoplimit =
pe_session->gLimEdcaParamsBC[2].txoplimit;
pDot11f->acvo_aifsn =
(0xf &
SET_AIFSN(pe_session->gLimEdcaParamsBC[3].aci.aifsn));
pDot11f->acvo_acm =
(0x1 & pe_session->gLimEdcaParamsBC[3].aci.acm);
pDot11f->acvo_aci = (0x3 & QCA_WLAN_AC_VO);
pDot11f->acvo_acwmin =
(0xf & pe_session->gLimEdcaParamsBC[3].cw.min);
pDot11f->acvo_acwmax =
(0xf & pe_session->gLimEdcaParamsBC[3].cw.max);
pDot11f->acvo_txoplimit =
pe_session->gLimEdcaParamsBC[3].txoplimit;
pDot11f->present = 1;
}
} /* End PopluateDot11fEDCAParamSet. */
QDF_STATUS
populate_dot11f_erp_info(struct mac_context *mac,
tDot11fIEERPInfo *pDot11f, struct pe_session *pe_session)
{
uint32_t val;
enum reg_wifi_band rfBand = REG_BAND_UNKNOWN;
lim_get_rf_band_new(mac, &rfBand, pe_session);
if (REG_BAND_2G == rfBand) {
pDot11f->present = 1;
val = pe_session->cfgProtection.fromllb;
if (!val) {
pe_err("11B protection not enabled. Not populating ERP IE %d",
val);
return QDF_STATUS_SUCCESS;
}
if (pe_session->gLim11bParams.protectionEnabled) {
pDot11f->non_erp_present = 1;
pDot11f->use_prot = 1;
}
if (pe_session->gLimOlbcParams.protectionEnabled) {
/* FIXME_PROTECTION: we should be setting non_erp present also. */
/* check the test plan first. */
pDot11f->use_prot = 1;
}
if ((pe_session->gLimNoShortParams.numNonShortPreambleSta)
|| !pe_session->beaconParams.fShortPreamble) {
pDot11f->barker_preamble = 1;
}
}
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_erp_info. */
QDF_STATUS
populate_dot11f_ext_supp_rates(struct mac_context *mac, uint8_t nChannelNum,
tDot11fIEExtSuppRates *pDot11f,
struct pe_session *pe_session)
{
QDF_STATUS nsir_status;
qdf_size_t nRates = 0;
uint8_t rates[WLAN_SUPPORTED_RATES_IE_MAX_LEN];
/* Use the ext rates present in session entry whenever nChannelNum is set to OPERATIONAL
else use the ext supported rate set from CFG, which is fixed and does not change dynamically and is used for
sending mgmt frames (lile probe req) which need to go out before any session is present.
*/
if (POPULATE_DOT11F_RATES_OPERATIONAL == nChannelNum) {
if (pe_session) {
nRates = pe_session->extRateSet.numRates;
qdf_mem_copy(rates, pe_session->extRateSet.rate,
nRates);
} else {
pe_err("no session context exists while populating Operational Rate Set");
}
} else if (HIGHEST_24GHZ_CHANNEL_NUM >= nChannelNum) {
nRates = mac->mlme_cfg->rates.ext_opr_rate_set.len;
nsir_status = wlan_mlme_get_cfg_str(
rates,
&mac->mlme_cfg->rates.ext_opr_rate_set, &nRates);
if (QDF_IS_STATUS_ERROR(nsir_status)) {
nRates = 0;
pe_err("Failed to retrieve nItem from CFG status: %d",
(nsir_status));
return nsir_status;
}
}
if (0 != nRates) {
pDot11f->num_rates = (uint8_t) nRates;
qdf_mem_copy(pDot11f->rates, rates, nRates);
pDot11f->present = 1;
}
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_ext_supp_rates. */
QDF_STATUS
populate_dot11f_ext_supp_rates1(struct mac_context *mac,
uint8_t nChannelNum,
tDot11fIEExtSuppRates *pDot11f)
{
qdf_size_t nRates;
QDF_STATUS nsir_status;
uint8_t rates[SIR_MAC_MAX_NUMBER_OF_RATES];
if (14 < nChannelNum) {
pDot11f->present = 0;
return QDF_STATUS_SUCCESS;
}
/* N.B. I have *no* idea why we're calling 'wlan_cfg_get_str' with an argument */
/* of WNI_CFG_SUPPORTED_RATES_11A here, but that's what was done */
/* previously & I'm afraid to change it! */
nRates = SIR_MAC_MAX_NUMBER_OF_RATES;
nsir_status = wlan_mlme_get_cfg_str(
rates,
&mac->mlme_cfg->rates.supported_11a,
&nRates);
if (QDF_IS_STATUS_ERROR(nsir_status)) {
pe_err("Failed to retrieve nItem from CFG status: %d",
(nsir_status));
return nsir_status;
}
if (0 != nRates) {
pDot11f->num_rates = (uint8_t) nRates;
qdf_mem_copy(pDot11f->rates, rates, nRates);
pDot11f->present = 1;
}
return QDF_STATUS_SUCCESS;
} /* populate_dot11f_ext_supp_rates1. */
QDF_STATUS
populate_dot11f_ht_caps(struct mac_context *mac,
struct pe_session *pe_session, tDot11fIEHTCaps *pDot11f)
{
qdf_size_t ncfglen;
QDF_STATUS nSirStatus;
uint8_t disable_high_ht_mcs_2x2 = 0;
tSirMacTxBFCapabilityInfo *pTxBFCapabilityInfo;
tSirMacASCapabilityInfo *pASCapabilityInfo;
struct mlme_ht_capabilities_info *ht_cap_info;
struct mlme_vht_capabilities_info *vht_cap_info;
ht_cap_info = &mac->mlme_cfg->ht_caps.ht_cap_info;
vht_cap_info = &mac->mlme_cfg->vht_caps.vht_cap_info;
pDot11f->mimoPowerSave = ht_cap_info->mimo_power_save;
pDot11f->greenField = ht_cap_info->green_field;
pDot11f->delayedBA = ht_cap_info->delayed_ba;
pDot11f->maximalAMSDUsize = ht_cap_info->maximal_amsdu_size;
pDot11f->dsssCckMode40MHz = ht_cap_info->dsss_cck_mode_40_mhz;
pDot11f->psmp = ht_cap_info->psmp;
pDot11f->stbcControlFrame = ht_cap_info->stbc_control_frame;
pDot11f->lsigTXOPProtection = ht_cap_info->l_sig_tx_op_protection;
/* All sessionized entries will need the check below */
if (!pe_session) { /* Only in case of NO session */
pDot11f->supportedChannelWidthSet =
ht_cap_info->supported_channel_width_set;
pDot11f->advCodingCap = ht_cap_info->adv_coding_cap;
pDot11f->txSTBC = ht_cap_info->tx_stbc;
pDot11f->rxSTBC = ht_cap_info->rx_stbc;
pDot11f->shortGI20MHz = ht_cap_info->short_gi_20_mhz;
pDot11f->shortGI40MHz = ht_cap_info->short_gi_40_mhz;
} else {
pDot11f->advCodingCap = pe_session->ht_config.ht_rx_ldpc;
pDot11f->supportedChannelWidthSet =
pe_session->htSupportedChannelWidthSet;
pDot11f->txSTBC = pe_session->ht_config.ht_tx_stbc;
pDot11f->rxSTBC = pe_session->ht_config.ht_rx_stbc;
pDot11f->shortGI20MHz = pe_session->ht_config.ht_sgi20;
pDot11f->shortGI40MHz = pe_session->ht_config.ht_sgi40;
}
/* Ensure that shortGI40MHz is Disabled if supportedChannelWidthSet is
eHT_CHANNEL_WIDTH_20MHZ */
if (pDot11f->supportedChannelWidthSet == eHT_CHANNEL_WIDTH_20MHZ) {
pDot11f->shortGI40MHz = 0;
}
pDot11f->maxRxAMPDUFactor =
mac->mlme_cfg->ht_caps.ampdu_params.max_rx_ampdu_factor;
pDot11f->mpduDensity =
mac->mlme_cfg->ht_caps.ampdu_params.mpdu_density;
pDot11f->reserved1 = mac->mlme_cfg->ht_caps.ampdu_params.reserved;
ncfglen = SIZE_OF_SUPPORTED_MCS_SET;
nSirStatus = wlan_mlme_get_cfg_str(
pDot11f->supportedMCSSet,
&mac->mlme_cfg->rates.supported_mcs_set,
&ncfglen);
if (QDF_IS_STATUS_ERROR(nSirStatus)) {
pe_err("Failed to retrieve nItem from CFG status: %d",
(nSirStatus));
return nSirStatus;
}
if (pe_session) {
disable_high_ht_mcs_2x2 =
mac->mlme_cfg->rates.disable_high_ht_mcs_2x2;
if (pe_session->nss == NSS_1x1_MODE) {
pDot11f->supportedMCSSet[1] = 0;
} else if (wlan_reg_is_24ghz_ch_freq(
pe_session->curr_op_freq) &&
disable_high_ht_mcs_2x2 &&
(pe_session->opmode == QDF_STA_MODE)) {
pe_debug("Disabling high HT MCS [%d]",
disable_high_ht_mcs_2x2);
pDot11f->supportedMCSSet[1] =
(pDot11f->supportedMCSSet[1] >>
disable_high_ht_mcs_2x2);
}
}
/* If STA mode, session supported NSS > 1 and
* SMPS enabled publish HT SMPS IE
*/
if (pe_session &&
LIM_IS_STA_ROLE(pe_session) &&
(pe_session->enableHtSmps) &&
(!pe_session->supported_nss_1x1)) {
pe_debug("Add SM power save IE: %d",
pe_session->htSmpsvalue);
pDot11f->mimoPowerSave = pe_session->htSmpsvalue;
}
pDot11f->pco = mac->mlme_cfg->ht_caps.ext_cap_info.pco;
pDot11f->transitionTime =
mac->mlme_cfg->ht_caps.ext_cap_info.transition_time;
pDot11f->mcsFeedback =
mac->mlme_cfg->ht_caps.ext_cap_info.mcs_feedback;
pTxBFCapabilityInfo =
(tSirMacTxBFCapabilityInfo *)&vht_cap_info->tx_bf_cap;
pDot11f->txBF = pTxBFCapabilityInfo->txBF;
pDot11f->rxStaggeredSounding = pTxBFCapabilityInfo->rxStaggeredSounding;
pDot11f->txStaggeredSounding = pTxBFCapabilityInfo->txStaggeredSounding;
pDot11f->rxZLF = pTxBFCapabilityInfo->rxZLF;
pDot11f->txZLF = pTxBFCapabilityInfo->txZLF;
pDot11f->implicitTxBF = pTxBFCapabilityInfo->implicitTxBF;
pDot11f->calibration = pTxBFCapabilityInfo->calibration;
pDot11f->explicitCSITxBF = pTxBFCapabilityInfo->explicitCSITxBF;
pDot11f->explicitUncompressedSteeringMatrix =
pTxBFCapabilityInfo->explicitUncompressedSteeringMatrix;
pDot11f->explicitBFCSIFeedback =
pTxBFCapabilityInfo->explicitBFCSIFeedback;
pDot11f->explicitUncompressedSteeringMatrixFeedback =
pTxBFCapabilityInfo->explicitUncompressedSteeringMatrixFeedback;
pDot11f->explicitCompressedSteeringMatrixFeedback =
pTxBFCapabilityInfo->explicitCompressedSteeringMatrixFeedback;
pDot11f->csiNumBFAntennae = pTxBFCapabilityInfo->csiNumBFAntennae;
pDot11f->uncompressedSteeringMatrixBFAntennae =
pTxBFCapabilityInfo->uncompressedSteeringMatrixBFAntennae;
pDot11f->compressedSteeringMatrixBFAntennae =
pTxBFCapabilityInfo->compressedSteeringMatrixBFAntennae;
pASCapabilityInfo = (tSirMacASCapabilityInfo *)&vht_cap_info->as_cap;
pDot11f->antennaSelection = pASCapabilityInfo->antennaSelection;
pDot11f->explicitCSIFeedbackTx =
pASCapabilityInfo->explicitCSIFeedbackTx;
pDot11f->antennaIndicesFeedbackTx =
pASCapabilityInfo->antennaIndicesFeedbackTx;
pDot11f->explicitCSIFeedback = pASCapabilityInfo->explicitCSIFeedback;
pDot11f->antennaIndicesFeedback =
pASCapabilityInfo->antennaIndicesFeedback;
pDot11f->rxAS = pASCapabilityInfo->rxAS;
pDot11f->txSoundingPPDUs = pASCapabilityInfo->txSoundingPPDUs;
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_ht_caps. */
void lim_log_vht_cap(struct mac_context *mac, tDot11fIEVHTCaps *pDot11f)
{
#ifdef DUMP_MGMT_CNTNTS
pe_debug("maxMPDULen (2): %d", pDot11f->maxMPDULen);
pe_debug("supportedChannelWidthSet (2): %d",
pDot11f->supportedChannelWidthSet);
pe_debug("ldpcCodingCap (1): %d",
pDot11f->ldpcCodingCap);
pe_debug("shortGI80MHz (1): %d", pDot11f->shortGI80MHz);
pe_debug("shortGI160and80plus80MHz (1): %d",
pDot11f->shortGI160and80plus80MHz);
pe_debug("txSTBC (1): %d", pDot11f->txSTBC);
pe_debug("rxSTBC (3): %d", pDot11f->rxSTBC);
pe_debug("suBeamFormerCap (1): %d",
pDot11f->suBeamFormerCap);
pe_debug("suBeamformeeCap (1): %d",
pDot11f->suBeamformeeCap);
pe_debug("csnofBeamformerAntSup (3): %d",
pDot11f->csnofBeamformerAntSup);
pe_debug("numSoundingDim (3): %d",
pDot11f->numSoundingDim);
pe_debug("muBeamformerCap (1): %d",
pDot11f->muBeamformerCap);
pe_debug("muBeamformeeCap (1): %d",
pDot11f->muBeamformeeCap);
pe_debug("vhtTXOPPS (1): %d", pDot11f->vhtTXOPPS);
pe_debug("htcVHTCap (1): %d", pDot11f->htcVHTCap);
pe_debug("maxAMPDULenExp (3): %d",
pDot11f->maxAMPDULenExp);
pe_debug("vhtLinkAdaptCap (2): %d",
pDot11f->vhtLinkAdaptCap);
pe_debug("rxAntPattern (1): %d",
pDot11f->rxAntPattern;
pe_debug("txAntPattern (1): %d",
pDot11f->txAntPattern);
pe_debug("reserved1 (2): %d", pDot11f->reserved1);
pe_debug("rxMCSMap (16): %d", pDot11f->rxMCSMap);
pe_debug("rxHighSupDataRate (13): %d",
pDot11f->rxHighSupDataRate);
pe_debug("reserved2(3): %d", pDot11f->reserved2);
pe_debug("txMCSMap (16): %d", pDot11f->txMCSMap);
pe_debug("txSupDataRate (13): %d"),
pDot11f->txSupDataRate;
pe_debug("reserved3 (3): %d", pDot11f->reserved3);
#endif /* DUMP_MGMT_CNTNTS */
}
static void lim_log_vht_operation(struct mac_context *mac,
tDot11fIEVHTOperation *pDot11f)
{
#ifdef DUMP_MGMT_CNTNTS
pe_debug("chanWidth: %d", pDot11f->chanWidth);
pe_debug("chan_center_freq_seg0: %d",
pDot11f->chan_center_freq_seg0);
pe_debug("chan_center_freq_seg1: %d",
pDot11f->chan_center_freq_seg1);
pe_debug("basicMCSSet: %d", pDot11f->basicMCSSet);
#endif /* DUMP_MGMT_CNTNTS */
}
static void lim_log_operating_mode(struct mac_context *mac,
tDot11fIEOperatingMode *pDot11f)
{
#ifdef DUMP_MGMT_CNTNTS
pe_debug("ChanWidth: %d", pDot11f->chanWidth);
pe_debug("reserved: %d", pDot11f->reserved);
pe_debug("rxNSS: %d", pDot11f->rxNSS);
pe_debug("rxNSS Type: %d", pDot11f->rxNSSType);
#endif /* DUMP_MGMT_CNTNTS */
}
static void lim_log_qos_map_set(struct mac_context *mac,
struct qos_map_set *pQosMapSet)
{
uint8_t i;
if (pQosMapSet->num_dscp_exceptions > QOS_MAP_MAX_EX)
pQosMapSet->num_dscp_exceptions = QOS_MAP_MAX_EX;
pe_debug("num of dscp exceptions: %d",
pQosMapSet->num_dscp_exceptions);
for (i = 0; i < pQosMapSet->num_dscp_exceptions; i++)
pe_nofl_debug("dscp value: %d, User priority value: %d",
pQosMapSet->dscp_exceptions[i][0],
pQosMapSet->dscp_exceptions[i][1]);
for (i = 0; i < 8; i++)
pe_nofl_debug("For up %d: dscp low: %d, dscp high: %d", i,
pQosMapSet->dscp_range[i][0],
pQosMapSet->dscp_range[i][1]);
}
QDF_STATUS
populate_dot11f_vht_caps(struct mac_context *mac,
struct pe_session *pe_session, tDot11fIEVHTCaps *pDot11f)
{
uint32_t nCfgValue = 0;
struct mlme_vht_capabilities_info *vht_cap_info;
if (!(mac->mlme_cfg)) {
pe_err("invalid mlme cfg");
return QDF_STATUS_E_FAILURE;
}
vht_cap_info = &mac->mlme_cfg->vht_caps.vht_cap_info;
pDot11f->present = 1;
nCfgValue = vht_cap_info->ampdu_len;
pDot11f->maxMPDULen = (nCfgValue & 0x0003);
nCfgValue = vht_cap_info->supp_chan_width;
pDot11f->supportedChannelWidthSet = (nCfgValue & 0x0003);
nCfgValue = 0;
/* With VHT it suffices if we just examine HT */
if (pe_session) {
if (lim_is_he_6ghz_band(pe_session)) {
pDot11f->present = 0;
return QDF_STATUS_SUCCESS;
}
if (pe_session->ht_config.ht_rx_ldpc)
pDot11f->ldpcCodingCap =
pe_session->vht_config.ldpc_coding;
if (pe_session->ch_width < CH_WIDTH_80MHZ) {
pDot11f->shortGI80MHz = 0;
} else {
pDot11f->shortGI80MHz =
pe_session->vht_config.shortgi80;
}
if (pe_session->ch_width < CH_WIDTH_160MHZ) {
pDot11f->shortGI160and80plus80MHz = 0;
pDot11f->supportedChannelWidthSet = 0;
} else {
pDot11f->shortGI160and80plus80MHz =
pe_session->vht_config.shortgi160and80plus80;
}
if (pe_session->ht_config.ht_tx_stbc)
pDot11f->txSTBC = pe_session->vht_config.tx_stbc;
if (pe_session->ht_config.ht_rx_stbc)
pDot11f->rxSTBC = pe_session->vht_config.rx_stbc;
pDot11f->suBeamformeeCap =
pe_session->vht_config.su_beam_formee;
if (pe_session->vht_config.su_beam_formee) {
pDot11f->muBeamformeeCap =
pe_session->vht_config.mu_beam_formee;
pDot11f->csnofBeamformerAntSup =
pe_session->vht_config.csnof_beamformer_antSup;
} else {
pDot11f->muBeamformeeCap = 0;
}
pDot11f->suBeamFormerCap =
pe_session->vht_config.su_beam_former;
pDot11f->vhtTXOPPS = pe_session->vht_config.vht_txops;
pDot11f->numSoundingDim =
pe_session->vht_config.num_soundingdim;
pDot11f->htcVHTCap = pe_session->vht_config.htc_vhtcap;
pDot11f->rxAntPattern = pe_session->vht_config.rx_antpattern;
pDot11f->txAntPattern = pe_session->vht_config.tx_antpattern;
pDot11f->extended_nss_bw_supp =
pe_session->vht_config.extended_nss_bw_supp;
pDot11f->maxAMPDULenExp =
pe_session->vht_config.max_ampdu_lenexp;
pDot11f->vhtLinkAdaptCap =
pe_session->vht_config.vht_link_adapt;
} else {
nCfgValue = vht_cap_info->ldpc_coding_cap;
pDot11f->ldpcCodingCap = (nCfgValue & 0x0001);
nCfgValue = vht_cap_info->short_gi_80mhz;
pDot11f->shortGI80MHz = (nCfgValue & 0x0001);
nCfgValue = vht_cap_info->short_gi_160mhz;
pDot11f->shortGI160and80plus80MHz = (nCfgValue & 0x0001);
nCfgValue = vht_cap_info->tx_stbc;
pDot11f->txSTBC = (nCfgValue & 0x0001);
nCfgValue = vht_cap_info->rx_stbc;
pDot11f->rxSTBC = (nCfgValue & 0x0007);
nCfgValue = vht_cap_info->su_bformee;
pDot11f->suBeamformeeCap = (nCfgValue & 0x0001);
nCfgValue = vht_cap_info->enable_mu_bformee;
pDot11f->muBeamformeeCap = (nCfgValue & 0x0001);
nCfgValue = vht_cap_info->su_bformer;
pDot11f->suBeamFormerCap = (nCfgValue & 0x0001);
nCfgValue = vht_cap_info->tx_bfee_ant_supp;
pDot11f->csnofBeamformerAntSup = (nCfgValue & 0x0007);
nCfgValue = vht_cap_info->txop_ps;
pDot11f->vhtTXOPPS = (nCfgValue & 0x0001);
nCfgValue = vht_cap_info->num_soundingdim;
pDot11f->numSoundingDim = (nCfgValue & 0x0007);
nCfgValue = vht_cap_info->htc_vhtc;
pDot11f->htcVHTCap = (nCfgValue & 0x0001);
pDot11f->rxAntPattern = vht_cap_info->rx_antpattern;
pDot11f->txAntPattern = vht_cap_info->tx_antpattern;
nCfgValue = vht_cap_info->ampdu_len_exponent;
pDot11f->maxAMPDULenExp = (nCfgValue & 0x0007);
nCfgValue = vht_cap_info->link_adap_cap;
pDot11f->vhtLinkAdaptCap = (nCfgValue & 0x0003);
pDot11f->extended_nss_bw_supp =
vht_cap_info->extended_nss_bw_supp;
}
pDot11f->max_nsts_total = vht_cap_info->max_nsts_total;
pDot11f->vht_extended_nss_bw_cap =
vht_cap_info->vht_extended_nss_bw_cap;
nCfgValue = vht_cap_info->mu_bformer;
pDot11f->muBeamformerCap = (nCfgValue & 0x0001);
nCfgValue = vht_cap_info->rx_mcs_map;
pDot11f->rxMCSMap = (nCfgValue & 0x0000FFFF);
nCfgValue = vht_cap_info->rx_supp_data_rate;
pDot11f->rxHighSupDataRate = (nCfgValue & 0x00001FFF);
nCfgValue = vht_cap_info->tx_mcs_map;
pDot11f->txMCSMap = (nCfgValue & 0x0000FFFF);
nCfgValue = vht_cap_info->tx_supp_data_rate;
pDot11f->txSupDataRate = (nCfgValue & 0x00001FFF);
if (pe_session) {
if (pe_session->nss == NSS_1x1_MODE) {
pDot11f->txMCSMap |= DISABLE_NSS2_MCS;
pDot11f->rxMCSMap |= DISABLE_NSS2_MCS;
pDot11f->txSupDataRate =
VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
pDot11f->rxHighSupDataRate =
VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1;
if (!pe_session->ch_width &&
!vht_cap_info->enable_vht20_mcs9 &&
((pDot11f->txMCSMap & VHT_1x1_MCS_MASK) ==
VHT_1x1_MCS9_MAP)) {
DISABLE_VHT_MCS_9(pDot11f->txMCSMap,
NSS_1x1_MODE);
DISABLE_VHT_MCS_9(pDot11f->rxMCSMap,
NSS_1x1_MODE);
}
} else {
if (!pe_session->ch_width &&
!vht_cap_info->enable_vht20_mcs9 &&
((pDot11f->txMCSMap & VHT_2x2_MCS_MASK) ==
VHT_2x2_MCS9_MAP)) {
DISABLE_VHT_MCS_9(pDot11f->txMCSMap,
NSS_2x2_MODE);
DISABLE_VHT_MCS_9(pDot11f->rxMCSMap,
NSS_2x2_MODE);
}
}
}
lim_log_vht_cap(mac, pDot11f);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
populate_dot11f_vht_operation(struct mac_context *mac,
struct pe_session *pe_session,
tDot11fIEVHTOperation *pDot11f)
{
if (!pe_session || !pe_session->vhtCapability)
return QDF_STATUS_SUCCESS;
pDot11f->present = 1;
if (pe_session->ch_width > CH_WIDTH_40MHZ) {
pDot11f->chanWidth = 1;
pDot11f->chan_center_freq_seg0 =
pe_session->ch_center_freq_seg0;
if (pe_session->ch_width == CH_WIDTH_80P80MHZ ||
pe_session->ch_width == CH_WIDTH_160MHZ)
pDot11f->chan_center_freq_seg1 =
pe_session->ch_center_freq_seg1;
else
pDot11f->chan_center_freq_seg1 = 0;
} else {
pDot11f->chanWidth = 0;
pDot11f->chan_center_freq_seg0 = 0;
pDot11f->chan_center_freq_seg1 = 0;
}
pDot11f->basicMCSSet =
(uint16_t)mac->mlme_cfg->vht_caps.vht_cap_info.basic_mcs_set;
lim_log_vht_operation(mac, pDot11f);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
populate_dot11f_ext_cap(struct mac_context *mac,
bool isVHTEnabled, tDot11fIEExtCap *pDot11f,
struct pe_session *pe_session)
{
struct s_ext_cap *p_ext_cap;
pDot11f->present = 1;
if (!pe_session) {
pe_debug("11MC - enabled for non-SAP cases");
pDot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN;
} else if (pe_session->sap_dot11mc) {
pe_debug("11MC support enabled");
pDot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN;
} else {
if (eLIM_AP_ROLE != pe_session->limSystemRole)
pDot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN;
else
pDot11f->num_bytes = DOT11F_IE_EXTCAP_MIN_LEN;
}
p_ext_cap = (struct s_ext_cap *)pDot11f->bytes;
if (isVHTEnabled == true)
p_ext_cap->oper_mode_notification = 1;
if (mac->mlme_cfg->gen.rtt3_enabled) {
uint32_t ftm = ucfg_wifi_pos_get_ftm_cap(mac->psoc);
if (!pe_session || LIM_IS_STA_ROLE(pe_session)) {
p_ext_cap->fine_time_meas_initiator =
(ftm & WMI_FW_STA_RTT_INITR) ? 1 : 0;
p_ext_cap->fine_time_meas_responder =
(ftm & WMI_FW_STA_RTT_RESPR) ? 1 : 0;
} else if (LIM_IS_AP_ROLE(pe_session)) {
p_ext_cap->fine_time_meas_initiator =
(ftm & WMI_FW_AP_RTT_INITR) ? 1 : 0;
p_ext_cap->fine_time_meas_responder =
(ftm & WMI_FW_AP_RTT_RESPR) ? 1 : 0;
}
}
#ifdef QCA_HT_2040_COEX
if (mac->roam.configParam.obssEnabled)
p_ext_cap->bss_coexist_mgmt_support = 1;
#endif
p_ext_cap->ext_chan_switch = 1;
if (pe_session && pe_session->enable_bcast_probe_rsp)
p_ext_cap->fils_capability = 1;
if (pe_session && pe_session->is_mbssid_enabled)
p_ext_cap->multi_bssid = 1;
/* Need to calculate the num_bytes based on bits set */
if (pDot11f->present)
pDot11f->num_bytes = lim_compute_ext_cap_ie_length(pDot11f);
return QDF_STATUS_SUCCESS;
}
void populate_dot11f_qcn_ie(struct mac_context *mac,
tDot11fIEqcn_ie *qcn_ie,
uint8_t attr_id)
{
qcn_ie->present = 0;
if (mac->mlme_cfg->sta.qcn_ie_support &&
((attr_id == QCN_IE_ATTR_ID_ALL) ||
(attr_id == QCN_IE_ATTR_ID_VERSION))) {
qcn_ie->present = 1;
qcn_ie->version_attr.present = 1;
qcn_ie->version_attr.version = QCN_IE_VERSION_SUPPORTED;
qcn_ie->version_attr.sub_version = QCN_IE_SUBVERSION_SUPPORTED;
}
if (mac->mlme_cfg->vht_caps.vht_cap_info.vht_mcs_10_11_supp) {
qcn_ie->present = 1;
qcn_ie->vht_mcs11_attr.present = 1;
qcn_ie->vht_mcs11_attr.vht_mcs_10_11_supp = 1;
}
}
QDF_STATUS
populate_dot11f_operating_mode(struct mac_context *mac,
tDot11fIEOperatingMode *pDot11f,
struct pe_session *pe_session)
{
pDot11f->present = 1;
pDot11f->chanWidth = pe_session->gLimOperatingMode.chanWidth;
pDot11f->rxNSS = pe_session->gLimOperatingMode.rxNSS;
pDot11f->rxNSSType = pe_session->gLimOperatingMode.rxNSSType;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
populate_dot11f_ht_info(struct mac_context *mac,
tDot11fIEHTInfo *pDot11f, struct pe_session *pe_session)
{
qdf_size_t ncfglen;
QDF_STATUS nSirStatus;
if (!pe_session) {
pe_err("Invalid session entry");
return QDF_STATUS_E_FAILURE;
}
pDot11f->primaryChannel = wlan_reg_freq_to_chan(
mac->pdev, pe_session->curr_op_freq);
pDot11f->secondaryChannelOffset =
pe_session->htSecondaryChannelOffset;
pDot11f->recommendedTxWidthSet =
pe_session->htRecommendedTxWidthSet;
pDot11f->rifsMode = pe_session->beaconParams.fRIFSMode;
pDot11f->controlledAccessOnly =
mac->mlme_cfg->ht_caps.info_field_1.controlled_access_only;
pDot11f->serviceIntervalGranularity =
mac->lim.gHTServiceIntervalGranularity;
if (LIM_IS_AP_ROLE(pe_session)) {
pDot11f->opMode = pe_session->htOperMode;
pDot11f->nonGFDevicesPresent =
pe_session->beaconParams.llnNonGFCoexist;
pDot11f->obssNonHTStaPresent =
pe_session->beaconParams.gHTObssMode;
pDot11f->reserved = 0;
} else {
pDot11f->opMode = 0;
pDot11f->nonGFDevicesPresent = 0;
pDot11f->obssNonHTStaPresent = 0;
pDot11f->reserved = 0;
}
pDot11f->basicSTBCMCS = mac->lim.gHTSTBCBasicMCS;
pDot11f->dualCTSProtection = mac->lim.gHTDualCTSProtection;
pDot11f->secondaryBeacon = mac->lim.gHTSecondaryBeacon;
pDot11f->lsigTXOPProtectionFullSupport =
pe_session->beaconParams.fLsigTXOPProtectionFullSupport;
pDot11f->pcoActive = mac->lim.gHTPCOActive;
pDot11f->pcoPhase = mac->lim.gHTPCOPhase;
pDot11f->reserved2 = 0;
ncfglen = SIZE_OF_BASIC_MCS_SET;
nSirStatus = wlan_mlme_get_cfg_str(pDot11f->basicMCSSet,
&mac->mlme_cfg->rates.basic_mcs_set,
&ncfglen);
if (QDF_IS_STATUS_ERROR(nSirStatus)) {
pe_err("Failed to retrieve nItem from CFG status: %d",
(nSirStatus));
return nSirStatus;
}
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_ht_info. */
void
populate_dot11f_ibss_params(struct mac_context *mac,
tDot11fIEIBSSParams *pDot11f,
struct pe_session *pe_session)
{
if (LIM_IS_IBSS_ROLE(pe_session)) {
pDot11f->atim = mac->mlme_cfg->ibss.atim_win_size;
pDot11f->present = 1;
}
} /* End populate_dot11f_ibss_params. */
#ifdef ANI_SUPPORT_11H
QDF_STATUS
populate_dot11f_measurement_report0(struct mac_context *mac,
tpSirMacMeasReqActionFrame pReq,
tDot11fIEMeasurementReport *pDot11f)
{
pDot11f->token = pReq->measReqIE.measToken;
pDot11f->late = 0;
pDot11f->incapable = 0;
pDot11f->refused = 1;
pDot11f->type = SIR_MAC_BASIC_MEASUREMENT_TYPE;
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
} /* End PopulatedDot11fMeasurementReport0. */
QDF_STATUS
populate_dot11f_measurement_report1(struct mac_context *mac,
tpSirMacMeasReqActionFrame pReq,
tDot11fIEMeasurementReport *pDot11f)
{
pDot11f->token = pReq->measReqIE.measToken;
pDot11f->late = 0;
pDot11f->incapable = 0;
pDot11f->refused = 1;
pDot11f->type = SIR_MAC_CCA_MEASUREMENT_TYPE;
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
} /* End PopulatedDot11fMeasurementReport1. */
QDF_STATUS
populate_dot11f_measurement_report2(struct mac_context *mac,
tpSirMacMeasReqActionFrame pReq,
tDot11fIEMeasurementReport *pDot11f)
{
pDot11f->token = pReq->measReqIE.measToken;
pDot11f->late = 0;
pDot11f->incapable = 0;
pDot11f->refused = 1;
pDot11f->type = SIR_MAC_RPI_MEASUREMENT_TYPE;
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
} /* End PopulatedDot11fMeasurementReport2. */
#endif
void
populate_dot11f_power_caps(struct mac_context *mac,
tDot11fIEPowerCaps *pCaps,
uint8_t nAssocType, struct pe_session *pe_session)
{
struct vdev_mlme_obj *mlme_obj;
if (nAssocType == LIM_REASSOC) {
pCaps->minTxPower =
pe_session->pLimReAssocReq->powerCap.minTxPower;
pCaps->maxTxPower =
pe_session->pLimReAssocReq->powerCap.maxTxPower;
} else {
pCaps->minTxPower =
pe_session->lim_join_req->powerCap.minTxPower;
pCaps->maxTxPower =
pe_session->lim_join_req->powerCap.maxTxPower;
}
/* Use firmware updated max tx power if non zero */
mlme_obj = wlan_vdev_mlme_get_cmpt_obj(pe_session->vdev);
if (mlme_obj && mlme_obj->mgmt.generic.tx_pwrlimit)
pCaps->maxTxPower = mlme_obj->mgmt.generic.tx_pwrlimit;
pCaps->present = 1;
} /* End populate_dot11f_power_caps. */
QDF_STATUS
populate_dot11f_power_constraints(struct mac_context *mac,
tDot11fIEPowerConstraints *pDot11f)
{
pDot11f->localPowerConstraints =
mac->mlme_cfg->power.local_power_constraint;
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_power_constraints. */
void
populate_dot11f_qos_caps_station(struct mac_context *mac, struct pe_session *pe_session,
tDot11fIEQOSCapsStation *pDot11f)
{
uint8_t max_sp_length = 0;
max_sp_length = mac->mlme_cfg->wmm_params.max_sp_length;
pDot11f->more_data_ack = 0;
pDot11f->max_sp_length = max_sp_length;
pDot11f->qack = 0;
if (mac->lim.gUapsdEnable) {
pDot11f->acbe_uapsd =
LIM_UAPSD_GET(ACBE, pe_session->gUapsdPerAcBitmask);
pDot11f->acbk_uapsd =
LIM_UAPSD_GET(ACBK, pe_session->gUapsdPerAcBitmask);
pDot11f->acvi_uapsd =
LIM_UAPSD_GET(ACVI, pe_session->gUapsdPerAcBitmask);
pDot11f->acvo_uapsd =
LIM_UAPSD_GET(ACVO, pe_session->gUapsdPerAcBitmask);
}
pDot11f->present = 1;
} /* End PopulatedDot11fQOSCaps. */
QDF_STATUS
populate_dot11f_rsn(struct mac_context *mac,
tpSirRSNie pRsnIe, tDot11fIERSN *pDot11f)
{
uint32_t status;
int idx;
if (pRsnIe->length) {
idx = find_ie_location(mac, pRsnIe, DOT11F_EID_RSN);
if (0 <= idx) {
status = dot11f_unpack_ie_rsn(mac, pRsnIe->rsnIEdata + idx + 2, /* EID, length */
pRsnIe->rsnIEdata[idx + 1],
pDot11f, false);
if (DOT11F_FAILED(status)) {
pe_err("Parse failure in Populate Dot11fRSN (0x%08x)",
status);
return QDF_STATUS_E_FAILURE;
}
pe_debug("status 0x%08x", status);
}
}
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_rsn. */
QDF_STATUS populate_dot11f_rsn_opaque(struct mac_context *mac,
tpSirRSNie pRsnIe,
tDot11fIERSNOpaque *pDot11f)
{
int idx;
if (pRsnIe->length) {
idx = find_ie_location(mac, pRsnIe, DOT11F_EID_RSN);
if (0 <= idx) {
pDot11f->present = 1;
pDot11f->num_data = pRsnIe->rsnIEdata[idx + 1];
qdf_mem_copy(pDot11f->data, pRsnIe->rsnIEdata + idx + 2, /* EID, len */
pRsnIe->rsnIEdata[idx + 1]);
}
}
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_rsn_opaque. */
#if defined(FEATURE_WLAN_WAPI)
QDF_STATUS
populate_dot11f_wapi(struct mac_context *mac,
tpSirRSNie pRsnIe, tDot11fIEWAPI *pDot11f)
{
uint32_t status;
int idx;
if (pRsnIe->length) {
idx = find_ie_location(mac, pRsnIe, DOT11F_EID_WAPI);
if (0 <= idx) {
status = dot11f_unpack_ie_wapi(mac, pRsnIe->rsnIEdata + idx + 2, /* EID, length */
pRsnIe->rsnIEdata[idx + 1],
pDot11f, false);
if (DOT11F_FAILED(status)) {
pe_err("Parse failure (0x%08x)", status);
return QDF_STATUS_E_FAILURE;
}
pe_debug("status 0x%08x", status);
}
}
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_wapi. */
QDF_STATUS populate_dot11f_wapi_opaque(struct mac_context *mac,
tpSirRSNie pRsnIe,
tDot11fIEWAPIOpaque *pDot11f)
{
int idx;
if (pRsnIe->length) {
idx = find_ie_location(mac, pRsnIe, DOT11F_EID_WAPI);
if (0 <= idx) {
pDot11f->present = 1;
pDot11f->num_data = pRsnIe->rsnIEdata[idx + 1];
qdf_mem_copy(pDot11f->data, pRsnIe->rsnIEdata + idx + 2, /* EID, len */
pRsnIe->rsnIEdata[idx + 1]);
}
}
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_wapi_opaque. */
#endif /* defined(FEATURE_WLAN_WAPI) */
void
populate_dot11f_ssid(struct mac_context *mac,
tSirMacSSid *pInternal, tDot11fIESSID *pDot11f)
{
pDot11f->present = 1;
pDot11f->num_ssid = pInternal->length;
if (pInternal->length) {
qdf_mem_copy((uint8_t *) pDot11f->ssid,
(uint8_t *) &pInternal->ssId, pInternal->length);
}
} /* End populate_dot11f_ssid. */
QDF_STATUS populate_dot11f_ssid2(struct mac_context *mac, tDot11fIESSID *pDot11f)
{
qdf_mem_copy(pDot11f->ssid, mac->mlme_cfg->sap_cfg.cfg_ssid,
mac->mlme_cfg->sap_cfg.cfg_ssid_len);
pDot11f->num_ssid = mac->mlme_cfg->sap_cfg.cfg_ssid_len;
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_ssid2. */
void
populate_dot11f_schedule(tSirMacScheduleIE *pSchedule,
tDot11fIESchedule *pDot11f)
{
pDot11f->aggregation = pSchedule->info.aggregation;
pDot11f->tsid = pSchedule->info.tsid;
pDot11f->direction = pSchedule->info.direction;
pDot11f->reserved = pSchedule->info.rsvd;
pDot11f->service_start_time = pSchedule->svcStartTime;
pDot11f->service_interval = pSchedule->svcInterval;
pDot11f->max_service_dur = pSchedule->maxSvcDuration;
pDot11f->spec_interval = pSchedule->specInterval;
pDot11f->present = 1;
} /* End populate_dot11f_schedule. */
void
populate_dot11f_supp_channels(struct mac_context *mac,
tDot11fIESuppChannels *pDot11f,
uint8_t nAssocType, struct pe_session *pe_session)
{
uint8_t i;
uint8_t *p;
if (nAssocType == LIM_REASSOC) {
p = (uint8_t *) pe_session->pLimReAssocReq->
supportedChannels.channelList;
pDot11f->num_bands =
pe_session->pLimReAssocReq->supportedChannels.numChnl;
} else {
p = (uint8_t *)pe_session->lim_join_req->supportedChannels.
channelList;
pDot11f->num_bands =
pe_session->lim_join_req->supportedChannels.numChnl;
}
for (i = 0U; i < pDot11f->num_bands; ++i, ++p) {
pDot11f->bands[i][0] = *p;
pDot11f->bands[i][1] = 1;
}
pDot11f->present = 1;
} /* End populate_dot11f_supp_channels. */
QDF_STATUS
populate_dot11f_supp_rates(struct mac_context *mac,
uint8_t nChannelNum,
tDot11fIESuppRates *pDot11f,
struct pe_session *pe_session)
{
QDF_STATUS nsir_status;
qdf_size_t nRates;
uint8_t rates[SIR_MAC_MAX_NUMBER_OF_RATES];
/* Use the operational rates present in session entry whenever
* nChannelNum is set to OPERATIONAL else use the supported
* rate set from CFG, which is fixed and does not change
* dynamically and is used for sending mgmt frames (lile probe
* req) which need to go out before any session is present.
*/
if (POPULATE_DOT11F_RATES_OPERATIONAL == nChannelNum) {
if (pe_session) {
nRates = pe_session->rateSet.numRates;
qdf_mem_copy(rates, pe_session->rateSet.rate,
nRates);
} else {
pe_err("no session context exists while populating Operational Rate Set");
nRates = 0;
}
} else if (14 >= nChannelNum) {
nRates = SIR_MAC_MAX_NUMBER_OF_RATES;
nsir_status = wlan_mlme_get_cfg_str(
rates,
&mac->mlme_cfg->rates.supported_11b,
&nRates);
if (QDF_IS_STATUS_ERROR(nsir_status)) {
pe_err("Failed to retrieve nItem from CFG status: %d",
(nsir_status));
return nsir_status;
}
} else {
nRates = SIR_MAC_MAX_NUMBER_OF_RATES;
nsir_status = wlan_mlme_get_cfg_str(
rates,
&mac->mlme_cfg->rates.supported_11a,
&nRates);
if (QDF_IS_STATUS_ERROR(nsir_status)) {
pe_err("Failed to retrieve nItem from CFG status: %d",
(nsir_status));
return nsir_status;
}
}
if (0 != nRates) {
pDot11f->num_rates = (uint8_t) nRates;
qdf_mem_copy(pDot11f->rates, rates, nRates);
pDot11f->present = 1;
}
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_supp_rates. */
/**
* populate_dot11f_rates_tdls() - populate supported rates and
* extended supported rates IE.
* @p_mac gloabl - header.
* @p_supp_rates - pointer to supported rates IE
* @p_ext_supp_rates - pointer to extended supported rates IE
* @curr_oper_channel - current operating channel
*
* This function populates the supported rates and extended supported
* rates IE based in the STA capability. If the number of rates
* supported is less than MAX_NUM_SUPPORTED_RATES, only supported rates
* IE is populated.
*
* Return: QDF_STATUS QDF_STATUS_SUCCESS on Success and QDF_STATUS_E_FAILURE
* on failure.
*/
QDF_STATUS
populate_dot11f_rates_tdls(struct mac_context *p_mac,
tDot11fIESuppRates *p_supp_rates,
tDot11fIEExtSuppRates *p_ext_supp_rates,
uint8_t curr_oper_channel)
{
tSirMacRateSet temp_rateset;
tSirMacRateSet temp_rateset2;
uint32_t i;
uint32_t self_dot11mode = 0;
qdf_size_t num_rates;
self_dot11mode = p_mac->mlme_cfg->dot11_mode.dot11_mode;
/**
* Include 11b rates only when the device configured in
* auto, 11a/b/g or 11b_only and also if current base
* channel is 5 GHz then no need to advertise the 11b rates.
* If devices move to 2.4GHz off-channel then they can communicate
* in 11g rates i.e. (6, 9, 12, 18, 24, 36 and 54).
*/
pe_debug("Current operating channel %d self_dot11mode = %d",
curr_oper_channel, self_dot11mode);
if ((curr_oper_channel <= SIR_11B_CHANNEL_END) &&
((self_dot11mode == MLME_DOT11_MODE_ALL) ||
(self_dot11mode == MLME_DOT11_MODE_11A) ||
(self_dot11mode == MLME_DOT11_MODE_11AC) ||
(self_dot11mode == MLME_DOT11_MODE_11N) ||
(self_dot11mode == MLME_DOT11_MODE_11G) ||
(self_dot11mode == MLME_DOT11_MODE_11B))) {
num_rates = p_mac->mlme_cfg->rates.supported_11b.len;
wlan_mlme_get_cfg_str((uint8_t *)&temp_rateset.rate,
&p_mac->mlme_cfg->rates.supported_11b,
&num_rates);
temp_rateset.numRates = (uint8_t)num_rates;
} else {
temp_rateset.numRates = 0;
}
/* Include 11a rates when the device configured in non-11b mode */
if (!IS_DOT11_MODE_11B(self_dot11mode)) {
num_rates = p_mac->mlme_cfg->rates.supported_11a.len;
wlan_mlme_get_cfg_str((uint8_t *)&temp_rateset2.rate,
&p_mac->mlme_cfg->rates.supported_11a,
&num_rates);
temp_rateset2.numRates = (uint8_t)num_rates;
} else {
temp_rateset2.numRates = 0;
}
if ((temp_rateset.numRates + temp_rateset2.numRates) >
SIR_MAC_MAX_NUMBER_OF_RATES) {
pe_err("more than %d rates in CFG",
SIR_MAC_MAX_NUMBER_OF_RATES);
return QDF_STATUS_E_FAILURE;
}
/**
* copy all rates in temp_rateset,
* there are SIR_MAC_MAX_NUMBER_OF_RATES rates max
*/
for (i = 0; i < temp_rateset2.numRates; i++)
temp_rateset.rate[i + temp_rateset.numRates] =
temp_rateset2.rate[i];
temp_rateset.numRates += temp_rateset2.numRates;
if (temp_rateset.numRates <= MAX_NUM_SUPPORTED_RATES) {
p_supp_rates->num_rates = temp_rateset.numRates;
qdf_mem_copy(p_supp_rates->rates, temp_rateset.rate,
p_supp_rates->num_rates);
p_supp_rates->present = 1;
} else { /* Populate extended capability as well */
p_supp_rates->num_rates = MAX_NUM_SUPPORTED_RATES;
qdf_mem_copy(p_supp_rates->rates, temp_rateset.rate,
p_supp_rates->num_rates);
p_supp_rates->present = 1;
p_ext_supp_rates->num_rates = temp_rateset.numRates -
MAX_NUM_SUPPORTED_RATES;
qdf_mem_copy(p_ext_supp_rates->rates,
(uint8_t *)temp_rateset.rate +
MAX_NUM_SUPPORTED_RATES,
p_ext_supp_rates->num_rates);
p_ext_supp_rates->present = 1;
}
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_rates_tdls */
QDF_STATUS
populate_dot11f_tpc_report(struct mac_context *mac,
tDot11fIETPCReport *pDot11f, struct pe_session *pe_session)
{
uint16_t staid;
uint8_t tx_power;
QDF_STATUS nSirStatus;
nSirStatus = lim_get_mgmt_staid(mac, &staid, pe_session);
if (QDF_STATUS_SUCCESS != nSirStatus) {
pe_err("Failed to get the STAID in Populate Dot11fTPCReport; lim_get_mgmt_staid returned status %d",
nSirStatus);
return QDF_STATUS_E_FAILURE;
}
tx_power = wlan_reg_get_channel_reg_power_for_freq(
mac->pdev, pe_session->curr_op_freq);
pDot11f->tx_power = tx_power;
pDot11f->link_margin = 0;
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_tpc_report. */
void populate_dot11f_ts_info(struct mac_ts_info *pInfo,
tDot11fFfTSInfo *pDot11f)
{
pDot11f->traffic_type = pInfo->traffic.trafficType;
pDot11f->tsid = pInfo->traffic.tsid;
pDot11f->direction = pInfo->traffic.direction;
pDot11f->access_policy = pInfo->traffic.accessPolicy;
pDot11f->aggregation = pInfo->traffic.aggregation;
pDot11f->psb = pInfo->traffic.psb;
pDot11f->user_priority = pInfo->traffic.userPrio;
pDot11f->tsinfo_ack_pol = pInfo->traffic.ackPolicy;
pDot11f->schedule = pInfo->schedule.schedule;
} /* End PopulatedDot11fTSInfo. */
void populate_dot11f_wmm(struct mac_context *mac,
tDot11fIEWMMInfoAp *pInfo,
tDot11fIEWMMParams *pParams,
tDot11fIEWMMCaps *pCaps, struct pe_session *pe_session)
{
if (pe_session->limWmeEnabled) {
if (LIM_IS_IBSS_ROLE(pe_session)) {
/* if ( ! sirIsPropCapabilityEnabled( mac, SIR_MAC_PROP_CAPABILITY_WME ) ) */
{
populate_dot11f_wmm_info_ap(mac, pInfo,
pe_session);
}
} else {
{
populate_dot11f_wmm_params(mac, pParams,
pe_session);
}
if (pe_session->limWsmEnabled) {
populate_dot11f_wmm_caps(pCaps);
}
}
}
} /* End populate_dot11f_wmm. */
void populate_dot11f_wmm_caps(tDot11fIEWMMCaps *pCaps)
{
pCaps->version = SIR_MAC_OUI_VERSION_1;
pCaps->qack = 0;
pCaps->queue_request = 1;
pCaps->txop_request = 0;
pCaps->more_ack = 0;
pCaps->present = 1;
} /* End PopulateDot11fWmmCaps. */
#ifdef FEATURE_WLAN_ESE
void populate_dot11f_re_assoc_tspec(struct mac_context *mac,
tDot11fReAssocRequest *pReassoc,
struct pe_session *pe_session)
{
uint8_t numTspecs = 0, idx;
tTspecInfo *pTspec = NULL;
numTspecs = pe_session->pLimReAssocReq->eseTspecInfo.numTspecs;
pTspec = &pe_session->pLimReAssocReq->eseTspecInfo.tspec[0];
pReassoc->num_WMMTSPEC = numTspecs;
if (numTspecs) {
for (idx = 0; idx < numTspecs; idx++) {
populate_dot11f_wmmtspec(&pTspec->tspec,
&pReassoc->WMMTSPEC[idx]);
pTspec->tspec.mediumTime = 0;
pTspec++;
}
}
}
void ese_populate_wmm_tspec(struct mac_tspec_ie *source,
ese_wmm_tspec_ie *dest)
{
dest->traffic_type = source->tsinfo.traffic.trafficType;
dest->tsid = source->tsinfo.traffic.tsid;
dest->direction = source->tsinfo.traffic.direction;
dest->access_policy = source->tsinfo.traffic.accessPolicy;
dest->aggregation = source->tsinfo.traffic.aggregation;
dest->psb = source->tsinfo.traffic.psb;
dest->user_priority = source->tsinfo.traffic.userPrio;
dest->tsinfo_ack_pol = source->tsinfo.traffic.ackPolicy;
dest->burst_size_defn = source->tsinfo.traffic.burstSizeDefn;
/* As defined in IEEE 802.11-2007, section 7.3.2.30
* Nominal MSDU size: Bit[0:14]=Size, Bit[15]=Fixed
*/
dest->size = (source->nomMsduSz & SIZE_MASK);
dest->fixed = (source->nomMsduSz & FIXED_MASK) ? 1 : 0;
dest->max_msdu_size = source->maxMsduSz;
dest->min_service_int = source->minSvcInterval;
dest->max_service_int = source->maxSvcInterval;
dest->inactivity_int = source->inactInterval;
dest->suspension_int = source->suspendInterval;
dest->service_start_time = source->svcStartTime;
dest->min_data_rate = source->minDataRate;
dest->mean_data_rate = source->meanDataRate;
dest->peak_data_rate = source->peakDataRate;
dest->burst_size = source->maxBurstSz;
dest->delay_bound = source->delayBound;
dest->min_phy_rate = source->minPhyRate;
dest->surplus_bw_allowance = source->surplusBw;
dest->medium_time = source->mediumTime;
}
#endif
void populate_dot11f_wmm_info_ap(struct mac_context *mac, tDot11fIEWMMInfoAp *pInfo,
struct pe_session *pe_session)
{
pInfo->version = SIR_MAC_OUI_VERSION_1;
/* WMM Specification 3.1.3, 3.2.3
* An IBSS station shall always use its default WMM parameters.
*/
if (LIM_IS_IBSS_ROLE(pe_session)) {
pInfo->param_set_count = 0;
pInfo->uapsd = 0;
} else {
pInfo->param_set_count =
(0xf & pe_session->gLimEdcaParamSetCount);
if (LIM_IS_AP_ROLE(pe_session)) {
pInfo->uapsd = (0x1 & pe_session->apUapsdEnable);
} else
pInfo->uapsd = (0x1 & mac->lim.gUapsdEnable);
}
pInfo->present = 1;
}
void populate_dot11f_wmm_info_station_per_session(struct mac_context *mac,
struct pe_session *pe_session,
tDot11fIEWMMInfoStation *pInfo)
{
uint8_t max_sp_length = 0;
max_sp_length = mac->mlme_cfg->wmm_params.max_sp_length;
pInfo->version = SIR_MAC_OUI_VERSION_1;
pInfo->acvo_uapsd =
LIM_UAPSD_GET(ACVO, pe_session->gUapsdPerAcBitmask);
pInfo->acvi_uapsd =
LIM_UAPSD_GET(ACVI, pe_session->gUapsdPerAcBitmask);
pInfo->acbk_uapsd =
LIM_UAPSD_GET(ACBK, pe_session->gUapsdPerAcBitmask);
pInfo->acbe_uapsd =
LIM_UAPSD_GET(ACBE, pe_session->gUapsdPerAcBitmask);
pInfo->max_sp_length = max_sp_length;
pInfo->present = 1;
}
void populate_dot11f_wmm_params(struct mac_context *mac,
tDot11fIEWMMParams *pParams,
struct pe_session *pe_session)
{
pParams->version = SIR_MAC_OUI_VERSION_1;
if (LIM_IS_AP_ROLE(pe_session))
pParams->qosInfo =
(pe_session->
apUapsdEnable << 7) | ((uint8_t) (0x0f & pe_session->
gLimEdcaParamSetCount));
else
pParams->qosInfo =
(mac->lim.
gUapsdEnable << 7) | ((uint8_t) (0x0f & pe_session->
gLimEdcaParamSetCount));
/* Fill each EDCA parameter set in order: be, bk, vi, vo */
pParams->acbe_aifsn =
(0xf & SET_AIFSN(pe_session->gLimEdcaParamsBC[0].aci.aifsn));
pParams->acbe_acm = (0x1 & pe_session->gLimEdcaParamsBC[0].aci.acm);
pParams->acbe_aci = (0x3 & QCA_WLAN_AC_BE);
pParams->acbe_acwmin =
(0xf & pe_session->gLimEdcaParamsBC[0].cw.min);
pParams->acbe_acwmax =
(0xf & pe_session->gLimEdcaParamsBC[0].cw.max);
pParams->acbe_txoplimit = pe_session->gLimEdcaParamsBC[0].txoplimit;
pParams->acbk_aifsn =
(0xf & SET_AIFSN(pe_session->gLimEdcaParamsBC[1].aci.aifsn));
pParams->acbk_acm = (0x1 & pe_session->gLimEdcaParamsBC[1].aci.acm);
pParams->acbk_aci = (0x3 & QCA_WLAN_AC_BK);
pParams->acbk_acwmin =
(0xf & pe_session->gLimEdcaParamsBC[1].cw.min);
pParams->acbk_acwmax =
(0xf & pe_session->gLimEdcaParamsBC[1].cw.max);
pParams->acbk_txoplimit = pe_session->gLimEdcaParamsBC[1].txoplimit;
if (LIM_IS_AP_ROLE(pe_session))
pParams->acvi_aifsn =
(0xf & pe_session->gLimEdcaParamsBC[2].aci.aifsn);
else
pParams->acvi_aifsn =
(0xf &
SET_AIFSN(pe_session->gLimEdcaParamsBC[2].aci.aifsn));
pParams->acvi_acm = (0x1 & pe_session->gLimEdcaParamsBC[2].aci.acm);
pParams->acvi_aci = (0x3 & QCA_WLAN_AC_VI);
pParams->acvi_acwmin =
(0xf & pe_session->gLimEdcaParamsBC[2].cw.min);
pParams->acvi_acwmax =
(0xf & pe_session->gLimEdcaParamsBC[2].cw.max);
pParams->acvi_txoplimit = pe_session->gLimEdcaParamsBC[2].txoplimit;
if (LIM_IS_AP_ROLE(pe_session))
pParams->acvo_aifsn =
(0xf & pe_session->gLimEdcaParamsBC[3].aci.aifsn);
else
pParams->acvo_aifsn =
(0xf &
SET_AIFSN(pe_session->gLimEdcaParamsBC[3].aci.aifsn));
pParams->acvo_acm = (0x1 & pe_session->gLimEdcaParamsBC[3].aci.acm);
pParams->acvo_aci = (0x3 & QCA_WLAN_AC_VO);
pParams->acvo_acwmin =
(0xf & pe_session->gLimEdcaParamsBC[3].cw.min);
pParams->acvo_acwmax =
(0xf & pe_session->gLimEdcaParamsBC[3].cw.max);
pParams->acvo_txoplimit = pe_session->gLimEdcaParamsBC[3].txoplimit;
pParams->present = 1;
} /* End populate_dot11f_wmm_params. */
QDF_STATUS
populate_dot11f_wpa(struct mac_context *mac,
tpSirRSNie pRsnIe, tDot11fIEWPA *pDot11f)
{
uint32_t status;
int idx;
if (pRsnIe->length) {
idx = find_ie_location(mac, pRsnIe, DOT11F_EID_WPA);
if (0 <= idx) {
status = dot11f_unpack_ie_wpa(mac, pRsnIe->rsnIEdata + idx + 2 + 4, /* EID, length, OUI */
pRsnIe->rsnIEdata[idx + 1] - 4, /* OUI */
pDot11f, false);
if (DOT11F_FAILED(status)) {
pe_err("Parse failure in Populate Dot11fWPA (0x%08x)",
status);
return QDF_STATUS_E_FAILURE;
}
}
}
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_wpa. */
QDF_STATUS populate_dot11f_wpa_opaque(struct mac_context *mac,
tpSirRSNie pRsnIe,
tDot11fIEWPAOpaque *pDot11f)
{
int idx;
if (pRsnIe->length) {
idx = find_ie_location(mac, pRsnIe, DOT11F_EID_WPA);
if (0 <= idx) {
pDot11f->present = 1;
pDot11f->num_data = pRsnIe->rsnIEdata[idx + 1] - 4;
qdf_mem_copy(pDot11f->data, pRsnIe->rsnIEdata + idx + 2 + 4, /* EID, len, OUI */
pRsnIe->rsnIEdata[idx + 1] - 4); /* OUI */
}
}
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_wpa_opaque. */
/* ////////////////////////////////////////////////////////////////////// */
QDF_STATUS
sir_convert_probe_req_frame2_struct(struct mac_context *mac,
uint8_t *pFrame,
uint32_t nFrame, tpSirProbeReq pProbeReq)
{
uint32_t status;
tDot11fProbeRequest pr;
/* Ok, zero-init our [out] parameter, */
qdf_mem_zero((uint8_t *) pProbeReq, sizeof(tSirProbeReq));
/* delegate to the framesc-generated code, */
status = dot11f_unpack_probe_request(mac, pFrame, nFrame, &pr, false);
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse a Probe Request (0x%08x, %d bytes):",
status, nFrame);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
pFrame, nFrame);
return QDF_STATUS_E_FAILURE;
} else if (DOT11F_WARNED(status)) {
pe_debug("There were warnings while unpacking a Probe Request (0x%08x, %d bytes):",
status, nFrame);
}
/* & "transliterate" from a 'tDot11fProbeRequestto' a 'tSirProbeReq'... */
if (!pr.SSID.present) {
pe_debug("Mandatory IE SSID not present!");
} else {
pProbeReq->ssidPresent = 1;
convert_ssid(mac, &pProbeReq->ssId, &pr.SSID);
}
if (!pr.SuppRates.present) {
pe_debug_rl("Mandatory IE Supported Rates not present!");
return QDF_STATUS_E_FAILURE;
} else {
pProbeReq->suppRatesPresent = 1;
convert_supp_rates(mac, &pProbeReq->supportedRates,
&pr.SuppRates);
}
if (pr.ExtSuppRates.present) {
pProbeReq->extendedRatesPresent = 1;
convert_ext_supp_rates(mac, &pProbeReq->extendedRates,
&pr.ExtSuppRates);
}
if (pr.HTCaps.present) {
qdf_mem_copy(&pProbeReq->HTCaps, &pr.HTCaps,
sizeof(tDot11fIEHTCaps));
}
if (pr.WscProbeReq.present) {
pProbeReq->wscIePresent = 1;
memcpy(&pProbeReq->probeReqWscIeInfo, &pr.WscProbeReq,
sizeof(tDot11fIEWscProbeReq));
}
if (pr.VHTCaps.present) {
qdf_mem_copy(&pProbeReq->VHTCaps, &pr.VHTCaps,
sizeof(tDot11fIEVHTCaps));
}
if (pr.P2PProbeReq.present) {
pProbeReq->p2pIePresent = 1;
}
if (pr.he_cap.present) {
qdf_mem_copy(&pProbeReq->he_cap, &pr.he_cap,
sizeof(tDot11fIEhe_cap));
pe_debug("11AX: HE cap IE present");
}
return QDF_STATUS_SUCCESS;
} /* End sir_convert_probe_req_frame2_struct. */
/**
* sir_validate_and_rectify_ies() - API to check malformed frame
* @mac_ctx: mac context
* @mgmt_frame: pointer to management frame
* @frame_bytes: no of bytes in frame
* @missing_rsn_bytes: missing rsn bytes
*
* The frame would contain fixed IEs of 12 bytes followed by variable IEs
* (Tagged elements). Every Tagged IE has tag number, tag length and data.
* Tag length indicates the size of data in bytes.
* This function checks for size of Frame received with the sum of all IEs.
* And also rectifies missing optional fields in IE.
*
* NOTE : Presently this function rectifies RSN capability in RSN IE, can
* be extended to rectify other optional fields in other IEs.
*
* Return: 0 on success, error number otherwise.
*/
QDF_STATUS
sir_validate_and_rectify_ies(struct mac_context *mac_ctx,
uint8_t *mgmt_frame,
uint32_t frame_bytes,
uint32_t *missing_rsn_bytes)
{
uint32_t length = SIZE_OF_FIXED_PARAM;
uint8_t *ref_frame = NULL;
/* Frame contains atleast one IE */
if (frame_bytes > (SIZE_OF_FIXED_PARAM +
SIZE_OF_TAG_PARAM_NUM + SIZE_OF_TAG_PARAM_LEN)) {
while (length < frame_bytes) {
/* ref frame points to next IE */
ref_frame = mgmt_frame + length;
length += (uint32_t)(SIZE_OF_TAG_PARAM_NUM +
SIZE_OF_TAG_PARAM_LEN +
(*(ref_frame + SIZE_OF_TAG_PARAM_NUM)));
}
if (length != frame_bytes) {
/*
* Workaround : Some APs may not include RSN
* Capability but the length of which is included in
* RSN IE length. This may cause in updating RSN
* Capability with junk value. To avoid this, add RSN
* Capability value with default value.
*/
if (ref_frame && (*ref_frame == RSNIEID) &&
(length == (frame_bytes +
RSNIE_CAPABILITY_LEN))) {
/* Assume RSN Capability as 00 */
qdf_mem_set((uint8_t *)(mgmt_frame +
(frame_bytes)),
RSNIE_CAPABILITY_LEN,
DEFAULT_RSNIE_CAP_VAL);
*missing_rsn_bytes = RSNIE_CAPABILITY_LEN;
pe_debug("Added RSN Capability to RSNIE as 0x00 0x00");
return QDF_STATUS_SUCCESS;
}
return QDF_STATUS_E_FAILURE;
}
}
return QDF_STATUS_SUCCESS;
}
void sir_copy_caps_info(struct mac_context *mac_ctx, tDot11fFfCapabilities caps,
tpSirProbeRespBeacon pProbeResp)
{
pProbeResp->capabilityInfo.ess = caps.ess;
pProbeResp->capabilityInfo.ibss = caps.ibss;
pProbeResp->capabilityInfo.cfPollable = caps.cfPollable;
pProbeResp->capabilityInfo.cfPollReq = caps.cfPollReq;
pProbeResp->capabilityInfo.privacy = caps.privacy;
pProbeResp->capabilityInfo.shortPreamble = caps.shortPreamble;
pProbeResp->capabilityInfo.pbcc = caps.pbcc;
pProbeResp->capabilityInfo.channelAgility = caps.channelAgility;
pProbeResp->capabilityInfo.spectrumMgt = caps.spectrumMgt;
pProbeResp->capabilityInfo.qos = caps.qos;
pProbeResp->capabilityInfo.shortSlotTime = caps.shortSlotTime;
pProbeResp->capabilityInfo.apsd = caps.apsd;
pProbeResp->capabilityInfo.rrm = caps.rrm;
pProbeResp->capabilityInfo.dsssOfdm = caps.dsssOfdm;
pProbeResp->capabilityInfo.delayedBA = caps.delayedBA;
pProbeResp->capabilityInfo.immediateBA = caps.immediateBA;
}
#ifdef WLAN_FEATURE_FILS_SK
static void populate_dot11f_fils_rsn(struct mac_context *mac_ctx,
tDot11fIERSNOpaque *p_dot11f,
uint8_t *rsn_ie)
{
pe_debug("FILS RSN IE length %d", rsn_ie[1]);
if (rsn_ie[1]) {
p_dot11f->present = 1;
p_dot11f->num_data = rsn_ie[1];
qdf_mem_copy(p_dot11f->data, &rsn_ie[2], rsn_ie[1]);
}
}
void populate_dot11f_fils_params(struct mac_context *mac_ctx,
tDot11fAssocRequest *frm,
struct pe_session *pe_session)
{
struct pe_fils_session *fils_info = pe_session->fils_info;
/* Populate RSN IE with FILS AKM */
populate_dot11f_fils_rsn(mac_ctx, &frm->RSNOpaque,
fils_info->rsn_ie);
/* Populate FILS session IE */
frm->fils_session.present = true;
qdf_mem_copy(frm->fils_session.session,
fils_info->fils_session, FILS_SESSION_LENGTH);
/* Populate FILS Key confirmation IE */
if (fils_info->key_auth_len) {
frm->fils_key_confirmation.present = true;
frm->fils_key_confirmation.num_key_auth =
fils_info->key_auth_len;
qdf_mem_copy(frm->fils_key_confirmation.key_auth,
fils_info->key_auth, fils_info->key_auth_len);
}
}
/**
* update_fils_data: update fils params from beacon/probe response
* @fils_ind: pointer to sir_fils_indication
* @fils_indication: pointer to tDot11fIEfils_indication
*
* Return: None
*/
void update_fils_data(struct sir_fils_indication *fils_ind,
tDot11fIEfils_indication *fils_indication)
{
uint8_t *data;
uint8_t remaining_data = fils_indication->num_variable_data;
data = fils_indication->variable_data;
fils_ind->is_present = true;
fils_ind->is_ip_config_supported =
fils_indication->is_ip_config_supported;
fils_ind->is_fils_sk_auth_supported =
fils_indication->is_fils_sk_auth_supported;
fils_ind->is_fils_sk_auth_pfs_supported =
fils_indication->is_fils_sk_auth_pfs_supported;
fils_ind->is_pk_auth_supported =
fils_indication->is_pk_auth_supported;
if (fils_indication->is_cache_id_present) {
if (remaining_data < SIR_CACHE_IDENTIFIER_LEN) {
pe_err("Failed to copy Cache Identifier, Invalid remaining data %d",
remaining_data);
return;
}
fils_ind->cache_identifier.is_present = true;
qdf_mem_copy(fils_ind->cache_identifier.identifier,
data, SIR_CACHE_IDENTIFIER_LEN);
data = data + SIR_CACHE_IDENTIFIER_LEN;
remaining_data = remaining_data - SIR_CACHE_IDENTIFIER_LEN;
}
if (fils_indication->is_hessid_present) {
if (remaining_data < SIR_HESSID_LEN) {
pe_err("Failed to copy HESSID, Invalid remaining data %d",
remaining_data);
return;
}
fils_ind->hessid.is_present = true;
qdf_mem_copy(fils_ind->hessid.hessid,
data, SIR_HESSID_LEN);
data = data + SIR_HESSID_LEN;
remaining_data = remaining_data - SIR_HESSID_LEN;
}
if (fils_indication->realm_identifiers_cnt) {
if (remaining_data < (fils_indication->realm_identifiers_cnt *
SIR_REALM_LEN)) {
pe_err("Failed to copy Realm Identifier, Invalid remaining data %d realm_cnt %d",
remaining_data,
fils_indication->realm_identifiers_cnt);
return;
}
fils_ind->realm_identifier.is_present = true;
fils_ind->realm_identifier.realm_cnt =
fils_indication->realm_identifiers_cnt;
qdf_mem_copy(fils_ind->realm_identifier.realm,
data, fils_ind->realm_identifier.realm_cnt *
SIR_REALM_LEN);
}
}
#endif
#ifdef WLAN_FEATURE_11AX_BSS_COLOR
static void update_bss_color_change_ie_from_probe_rsp(
tDot11fProbeResponse *prb_frm,
tpSirProbeRespBeacon prb_rsp_struct)
{
if (prb_frm->bss_color_change.present) {
pe_debug("11AX: HE BSS color change present");
qdf_mem_copy(&prb_rsp_struct->vendor_he_bss_color_change,
&prb_frm->bss_color_change,
sizeof(tDot11fIEbss_color_change));
}
}
#else
static inline void update_bss_color_change_ie_from_probe_rsp(
tDot11fProbeResponse *prb_frm,
tpSirProbeRespBeacon prb_rsp_struct)
{}
#endif
QDF_STATUS sir_convert_probe_frame2_struct(struct mac_context *mac,
uint8_t *pFrame,
uint32_t nFrame,
tpSirProbeRespBeacon pProbeResp)
{
uint32_t status;
tDot11fProbeResponse *pr;
/* Ok, zero-init our [out] parameter, */
qdf_mem_zero((uint8_t *) pProbeResp, sizeof(tSirProbeRespBeacon));
pr = qdf_mem_malloc(sizeof(tDot11fProbeResponse));
if (!pr)
return QDF_STATUS_E_NOMEM;
/* delegate to the framesc-generated code, */
status = dot11f_unpack_probe_response(mac, pFrame, nFrame, pr, false);
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse a Probe Response (0x%08x, %d bytes):",
status, nFrame);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
pFrame, nFrame);
qdf_mem_free(pr);
return QDF_STATUS_E_FAILURE;
}
/* & "transliterate" from a 'tDot11fProbeResponse' to a 'tSirProbeRespBeacon'... */
/* Timestamp */
qdf_mem_copy((uint8_t *) pProbeResp->timeStamp,
(uint8_t *) &pr->TimeStamp, sizeof(tSirMacTimeStamp));
/* Beacon Interval */
pProbeResp->beaconInterval = pr->BeaconInterval.interval;
sir_copy_caps_info(mac, pr->Capabilities, pProbeResp);
if (!pr->SSID.present) {
pe_debug("Mandatory IE SSID not present!");
} else {
pProbeResp->ssidPresent = 1;
convert_ssid(mac, &pProbeResp->ssId, &pr->SSID);
}
if (!pr->SuppRates.present) {
pe_debug_rl("Mandatory IE Supported Rates not present!");
} else {
pProbeResp->suppRatesPresent = 1;
convert_supp_rates(mac, &pProbeResp->supportedRates,
&pr->SuppRates);
}
if (pr->ExtSuppRates.present) {
pProbeResp->extendedRatesPresent = 1;
convert_ext_supp_rates(mac, &pProbeResp->extendedRates,
&pr->ExtSuppRates);
}
if (pr->CFParams.present) {
pProbeResp->cfPresent = 1;
convert_cf_params(mac, &pProbeResp->cfParamSet, &pr->CFParams);
}
if (pr->Country.present) {
pProbeResp->countryInfoPresent = 1;
convert_country(mac, &pProbeResp->countryInfoParam,
&pr->Country);
}
if (pr->EDCAParamSet.present) {
pProbeResp->edcaPresent = 1;
convert_edca_param(mac, &pProbeResp->edcaParams,
&pr->EDCAParamSet);
}
if (pr->ChanSwitchAnn.present) {
pProbeResp->channelSwitchPresent = 1;
qdf_mem_copy(&pProbeResp->channelSwitchIE, &pr->ChanSwitchAnn,
sizeof(pProbeResp->channelSwitchIE));
}
if (pr->ext_chan_switch_ann.present) {
pProbeResp->ext_chan_switch_present = 1;
qdf_mem_copy(&pProbeResp->ext_chan_switch,
&pr->ext_chan_switch_ann,
sizeof(tDot11fIEext_chan_switch_ann));
}
if (pr->SuppOperatingClasses.present) {
pProbeResp->supp_operating_class_present = 1;
qdf_mem_copy(&pProbeResp->supp_operating_classes,
&pr->SuppOperatingClasses,
sizeof(tDot11fIESuppOperatingClasses));
}
if (pr->sec_chan_offset_ele.present) {
pProbeResp->sec_chan_offset_present = 1;
qdf_mem_copy(&pProbeResp->sec_chan_offset,
&pr->sec_chan_offset_ele,
sizeof(pProbeResp->sec_chan_offset));
}
if (pr->TPCReport.present) {
pProbeResp->tpcReportPresent = 1;
qdf_mem_copy(&pProbeResp->tpcReport, &pr->TPCReport,
sizeof(tDot11fIETPCReport));
}
if (pr->PowerConstraints.present) {
pProbeResp->powerConstraintPresent = 1;
qdf_mem_copy(&pProbeResp->localPowerConstraint,
&pr->PowerConstraints,
sizeof(tDot11fIEPowerConstraints));
}
if (pr->Quiet.present) {
pProbeResp->quietIEPresent = 1;
qdf_mem_copy(&pProbeResp->quietIE, &pr->Quiet,
sizeof(tDot11fIEQuiet));
}
if (pr->HTCaps.present) {
qdf_mem_copy(&pProbeResp->HTCaps, &pr->HTCaps,
sizeof(tDot11fIEHTCaps));
}
if (pr->HTInfo.present) {
qdf_mem_copy(&pProbeResp->HTInfo, &pr->HTInfo,
sizeof(tDot11fIEHTInfo));
}
if (pr->he_op.oper_info_6g_present) {
pProbeResp->chan_freq = wlan_reg_chan_band_to_freq(mac->pdev,
pr->he_op.oper_info_6g.info.primary_ch,
BIT(REG_BAND_6G));
} else if (pr->DSParams.present) {
pProbeResp->dsParamsPresent = 1;
pProbeResp->chan_freq =
wlan_reg_legacy_chan_to_freq(mac->pdev, pr->DSParams.curr_channel);
} else if (pr->HTInfo.present) {
pProbeResp->chan_freq =
wlan_reg_legacy_chan_to_freq(mac->pdev, pr->HTInfo.primaryChannel);
}
if (pr->RSNOpaque.present) {
pProbeResp->rsnPresent = 1;
convert_rsn_opaque(mac, &pProbeResp->rsn, &pr->RSNOpaque);
}
if (pr->WPA.present) {
pProbeResp->wpaPresent = 1;
convert_wpa(mac, &pProbeResp->wpa, &pr->WPA);
}
if (pr->WMMParams.present) {
pProbeResp->wmeEdcaPresent = 1;
convert_wmm_params(mac, &pProbeResp->edcaParams, &pr->WMMParams);
}
if (pr->WMMInfoAp.present) {
pProbeResp->wmeInfoPresent = 1;
pe_debug("WMM Information Element present in Probe Response Frame!");
}
if (pr->WMMCaps.present) {
pProbeResp->wsmCapablePresent = 1;
}
if (pr->ERPInfo.present) {
pProbeResp->erpPresent = 1;
convert_erp_info(mac, &pProbeResp->erpIEInfo, &pr->ERPInfo);
}
if (pr->MobilityDomain.present) {
/* MobilityDomain */
pProbeResp->mdiePresent = 1;
qdf_mem_copy((uint8_t *) &(pProbeResp->mdie[0]),
(uint8_t *) &(pr->MobilityDomain.MDID),
sizeof(uint16_t));
pProbeResp->mdie[2] =
((pr->MobilityDomain.overDSCap << 0) | (pr->MobilityDomain.
resourceReqCap <<
1));
pe_debug("mdie=%02x%02x%02x",
(unsigned int)pProbeResp->mdie[0],
(unsigned int)pProbeResp->mdie[1],
(unsigned int)pProbeResp->mdie[2]);
}
#if defined FEATURE_WLAN_ESE
if (pr->ESEVersion.present)
pProbeResp->is_ese_ver_ie_present = 1;
if (pr->QBSSLoad.present) {
qdf_mem_copy(&pProbeResp->QBSSLoad, &pr->QBSSLoad,
sizeof(tDot11fIEQBSSLoad));
}
#endif
if (pr->P2PProbeRes.present) {
qdf_mem_copy(&pProbeResp->P2PProbeRes, &pr->P2PProbeRes,
sizeof(tDot11fIEP2PProbeRes));
}
if (pr->VHTCaps.present) {
qdf_mem_copy(&pProbeResp->VHTCaps, &pr->VHTCaps,
sizeof(tDot11fIEVHTCaps));
}
if (pr->VHTOperation.present) {
qdf_mem_copy(&pProbeResp->VHTOperation, &pr->VHTOperation,
sizeof(tDot11fIEVHTOperation));
}
if (pr->VHTExtBssLoad.present) {
qdf_mem_copy(&pProbeResp->VHTExtBssLoad, &pr->VHTExtBssLoad,
sizeof(tDot11fIEVHTExtBssLoad));
}
pProbeResp->Vendor1IEPresent = pr->Vendor1IE.present;
pProbeResp->Vendor3IEPresent = pr->Vendor3IE.present;
pProbeResp->vendor_vht_ie.present = pr->vendor_vht_ie.present;
if (pr->vendor_vht_ie.present)
pProbeResp->vendor_vht_ie.sub_type = pr->vendor_vht_ie.sub_type;
if (pr->vendor_vht_ie.VHTCaps.present) {
qdf_mem_copy(&pProbeResp->vendor_vht_ie.VHTCaps,
&pr->vendor_vht_ie.VHTCaps,
sizeof(tDot11fIEVHTCaps));
}
if (pr->vendor_vht_ie.VHTOperation.present) {
qdf_mem_copy(&pProbeResp->vendor_vht_ie.VHTOperation,
&pr->vendor_vht_ie.VHTOperation,
sizeof(tDot11fIEVHTOperation));
}
/* Update HS 2.0 Information Element */
if (pr->hs20vendor_ie.present) {
pe_debug("HS20 Indication Element Present, rel#:%u, id:%u",
pr->hs20vendor_ie.release_num,
pr->hs20vendor_ie.hs_id_present);
qdf_mem_copy(&pProbeResp->hs20vendor_ie,
&pr->hs20vendor_ie,
sizeof(tDot11fIEhs20vendor_ie) -
sizeof(pr->hs20vendor_ie.hs_id));
if (pr->hs20vendor_ie.hs_id_present)
qdf_mem_copy(&pProbeResp->hs20vendor_ie.hs_id,
&pr->hs20vendor_ie.hs_id,
sizeof(pr->hs20vendor_ie.hs_id));
}
if (pr->MBO_IE.present) {
pProbeResp->MBO_IE_present = true;
if (pr->MBO_IE.cellular_data_cap.present)
pProbeResp->MBO_capability =
pr->MBO_IE.cellular_data_cap.cellular_connectivity;
if (pr->MBO_IE.assoc_disallowed.present) {
pProbeResp->assoc_disallowed = true;
pProbeResp->assoc_disallowed_reason =
pr->MBO_IE.assoc_disallowed.reason_code;
}
}
if (pr->qcn_ie.present)
qdf_mem_copy(&pProbeResp->qcn_ie, &pr->qcn_ie,
sizeof(tDot11fIEqcn_ie));
if (pr->he_cap.present) {
pe_debug("11AX: HE cap IE present");
qdf_mem_copy(&pProbeResp->he_cap, &pr->he_cap,
sizeof(tDot11fIEhe_cap));
}
if (pr->he_op.present) {
pe_debug("11AX: HE operation IE present");
qdf_mem_copy(&pProbeResp->he_op, &pr->he_op,
sizeof(tDot11fIEhe_op));
}
update_bss_color_change_ie_from_probe_rsp(pr, pProbeResp);
qdf_mem_free(pr);
return QDF_STATUS_SUCCESS;
} /* End sir_convert_probe_frame2_struct. */
QDF_STATUS
sir_convert_assoc_req_frame2_struct(struct mac_context *mac,
uint8_t *pFrame,
uint32_t nFrame, tpSirAssocReq pAssocReq)
{
tDot11fAssocRequest *ar;
uint32_t status;
ar = qdf_mem_malloc(sizeof(tDot11fAssocRequest));
if (!ar)
return QDF_STATUS_E_NOMEM;
/* Zero-init our [out] parameter, */
qdf_mem_zero((uint8_t *) pAssocReq, sizeof(tSirAssocReq));
/* delegate to the framesc-generated code, */
status = dot11f_unpack_assoc_request(mac, pFrame, nFrame, ar, false);
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse an Association Request (0x%08x, %d bytes):",
status, nFrame);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
pFrame, nFrame);
qdf_mem_free(ar);
return QDF_STATUS_E_FAILURE;
} else if (DOT11F_WARNED(status)) {
pe_debug("There were warnings while unpacking an Assoication Request (0x%08x, %d bytes):",
status, nFrame);
}
/* & "transliterate" from a 'tDot11fAssocRequest' to a 'tSirAssocReq'... */
/* make sure this is seen as an assoc request */
pAssocReq->reassocRequest = 0;
/* Capabilities */
pAssocReq->capabilityInfo.ess = ar->Capabilities.ess;
pAssocReq->capabilityInfo.ibss = ar->Capabilities.ibss;
pAssocReq->capabilityInfo.cfPollable = ar->Capabilities.cfPollable;
pAssocReq->capabilityInfo.cfPollReq = ar->Capabilities.cfPollReq;
pAssocReq->capabilityInfo.privacy = ar->Capabilities.privacy;
pAssocReq->capabilityInfo.shortPreamble =
ar->Capabilities.shortPreamble;
pAssocReq->capabilityInfo.pbcc = ar->Capabilities.pbcc;
pAssocReq->capabilityInfo.channelAgility =
ar->Capabilities.channelAgility;
pAssocReq->capabilityInfo.spectrumMgt = ar->Capabilities.spectrumMgt;
pAssocReq->capabilityInfo.qos = ar->Capabilities.qos;
pAssocReq->capabilityInfo.shortSlotTime =
ar->Capabilities.shortSlotTime;
pAssocReq->capabilityInfo.apsd = ar->Capabilities.apsd;
pAssocReq->capabilityInfo.rrm = ar->Capabilities.rrm;
pAssocReq->capabilityInfo.dsssOfdm = ar->Capabilities.dsssOfdm;
pAssocReq->capabilityInfo.delayedBA = ar->Capabilities.delayedBA;
pAssocReq->capabilityInfo.immediateBA = ar->Capabilities.immediateBA;
/* Listen Interval */
pAssocReq->listenInterval = ar->ListenInterval.interval;
/* SSID */
if (ar->SSID.present) {
pAssocReq->ssidPresent = 1;
convert_ssid(mac, &pAssocReq->ssId, &ar->SSID);
}
/* Supported Rates */
if (ar->SuppRates.present) {
pAssocReq->suppRatesPresent = 1;
convert_supp_rates(mac, &pAssocReq->supportedRates,
&ar->SuppRates);
}
/* Extended Supported Rates */
if (ar->ExtSuppRates.present) {
pAssocReq->extendedRatesPresent = 1;
convert_ext_supp_rates(mac, &pAssocReq->extendedRates,
&ar->ExtSuppRates);
}
/* QOS Capabilities: */
if (ar->QOSCapsStation.present) {
pAssocReq->qosCapabilityPresent = 1;
convert_qos_caps_station(mac, &pAssocReq->qosCapability,
&ar->QOSCapsStation);
}
/* WPA */
if (ar->WPAOpaque.present) {
pAssocReq->wpaPresent = 1;
convert_wpa_opaque(mac, &pAssocReq->wpa, &ar->WPAOpaque);
}
#ifdef FEATURE_WLAN_WAPI
if (ar->WAPIOpaque.present) {
pAssocReq->wapiPresent = 1;
convert_wapi_opaque(mac, &pAssocReq->wapi, &ar->WAPIOpaque);
}
#endif
/* RSN */
if (ar->RSNOpaque.present) {
pAssocReq->rsnPresent = 1;
convert_rsn_opaque(mac, &pAssocReq->rsn, &ar->RSNOpaque);
}
/* WSC IE */
if (ar->WscIEOpaque.present) {
pAssocReq->addIEPresent = 1;
convert_wsc_opaque(mac, &pAssocReq->addIE, &ar->WscIEOpaque);
}
if (ar->P2PIEOpaque.present) {
pAssocReq->addIEPresent = 1;
convert_p2p_opaque(mac, &pAssocReq->addIE, &ar->P2PIEOpaque);
}
#ifdef WLAN_FEATURE_WFD
if (ar->WFDIEOpaque.present) {
pAssocReq->addIEPresent = 1;
convert_wfd_opaque(mac, &pAssocReq->addIE, &ar->WFDIEOpaque);
}
#endif
/* Power Capabilities */
if (ar->PowerCaps.present) {
pAssocReq->powerCapabilityPresent = 1;
convert_power_caps(mac, &pAssocReq->powerCapability,
&ar->PowerCaps);
}
/* Supported Channels */
if (ar->SuppChannels.present) {
pAssocReq->supportedChannelsPresent = 1;
convert_supp_channels(mac, &pAssocReq->supportedChannels,
&ar->SuppChannels);
}
if (ar->HTCaps.present) {
qdf_mem_copy(&pAssocReq->HTCaps, &ar->HTCaps,
sizeof(tDot11fIEHTCaps));
}
if (ar->WMMInfoStation.present) {
pAssocReq->wmeInfoPresent = 1;
qdf_mem_copy(&pAssocReq->WMMInfoStation, &ar->WMMInfoStation,
sizeof(tDot11fIEWMMInfoStation));
}
if (ar->WMMCaps.present)
pAssocReq->wsmCapablePresent = 1;
if (!pAssocReq->ssidPresent) {
pe_debug("Received Assoc without SSID IE");
qdf_mem_free(ar);
return QDF_STATUS_E_FAILURE;
}
if (!pAssocReq->suppRatesPresent && !pAssocReq->extendedRatesPresent) {
pe_debug("Received Assoc without supp rate IE");
qdf_mem_free(ar);
return QDF_STATUS_E_FAILURE;
}
if (ar->VHTCaps.present) {
qdf_mem_copy(&pAssocReq->VHTCaps, &ar->VHTCaps,
sizeof(tDot11fIEVHTCaps));
pe_debug("Received Assoc Req with VHT Cap");
lim_log_vht_cap(mac, &pAssocReq->VHTCaps);
}
if (ar->OperatingMode.present) {
qdf_mem_copy(&pAssocReq->operMode, &ar->OperatingMode,
sizeof(tDot11fIEOperatingMode));
pe_debug("Received Assoc Req with Operating Mode IE");
lim_log_operating_mode(mac, &pAssocReq->operMode);
}
if (ar->ExtCap.present) {
struct s_ext_cap *ext_cap;
qdf_mem_copy(&pAssocReq->ExtCap, &ar->ExtCap,
sizeof(tDot11fIEExtCap));
ext_cap = (struct s_ext_cap *)&pAssocReq->ExtCap.bytes;
pe_debug("timingMeas: %d, finetimingMeas Init: %d, Resp: %d",
ext_cap->timing_meas, ext_cap->fine_time_meas_initiator,
ext_cap->fine_time_meas_responder);
}
if (ar->SuppOperatingClasses.present) {
uint8_t num_classes = ar->SuppOperatingClasses.num_classes;
if (num_classes > sizeof(ar->SuppOperatingClasses.classes))
num_classes =
sizeof(ar->SuppOperatingClasses.classes);
qdf_mem_copy(&pAssocReq->supp_operating_classes,
&ar->SuppOperatingClasses,
sizeof(tDot11fIESuppOperatingClasses));
QDF_TRACE_HEX_DUMP(
QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
ar->SuppOperatingClasses.classes, num_classes);
}
pAssocReq->vendor_vht_ie.present = ar->vendor_vht_ie.present;
if (ar->vendor_vht_ie.present) {
pAssocReq->vendor_vht_ie.sub_type = ar->vendor_vht_ie.sub_type;
if (ar->vendor_vht_ie.VHTCaps.present) {
qdf_mem_copy(&pAssocReq->vendor_vht_ie.VHTCaps,
&ar->vendor_vht_ie.VHTCaps,
sizeof(tDot11fIEVHTCaps));
pe_debug("Received Assoc Request with Vendor specific VHT Cap");
lim_log_vht_cap(mac, &pAssocReq->VHTCaps);
}
}
if (ar->qcn_ie.present)
qdf_mem_copy(&pAssocReq->qcn_ie, &ar->qcn_ie,
sizeof(tDot11fIEqcn_ie));
if (ar->he_cap.present) {
qdf_mem_copy(&pAssocReq->he_cap, &ar->he_cap,
sizeof(tDot11fIEhe_cap));
pe_debug("Received Assoc Req with HE Capability IE");
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
&pAssocReq->he_cap, sizeof(tDot11fIEhe_cap));
}
if (ar->he_6ghz_band_cap.present) {
qdf_mem_copy(&pAssocReq->he_6ghz_band_cap,
&ar->he_6ghz_band_cap,
sizeof(tDot11fIEhe_6ghz_band_cap));
pe_debug("Received Assoc Req with HE Band Capability IE");
}
qdf_mem_free(ar);
return QDF_STATUS_SUCCESS;
} /* End sir_convert_assoc_req_frame2_struct. */
/**
* dot11f_parse_assoc_response() - API to parse Assoc IE buffer to struct
* @mac_ctx: MAC context
* @p_buf: Pointer to the assoc IE buffer
* @n_buf: length of the @p_buf
* @p_frm: Struct to populate the IE buffer after parsing
* @append_ie: Boolean to indicate whether to reset @p_frm or not. If @append_ie
* is true, @p_frm struct is not reset to zeros.
*
* Return: QDF_STATUS
*/
static QDF_STATUS dot11f_parse_assoc_response(struct mac_context *mac_ctx,
uint8_t *p_buf, uint32_t n_buf,
tDot11fAssocResponse *p_frm,
bool append_ie)
{
uint32_t status;
status = dot11f_unpack_assoc_response(mac_ctx, p_buf,
n_buf, p_frm, append_ie);
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse an Association Response (0x%08x, %d bytes):",
status, n_buf);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
p_buf, n_buf);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
#ifdef WLAN_FEATURE_FILS_SK
/**
* fils_convert_assoc_rsp_frame2_struct() - Copy FILS IE's to Assoc rsp struct
* @ar: frame parser Assoc response struct
* @pAssocRsp: LIM Assoc response
*
* Return: None
*/
static void fils_convert_assoc_rsp_frame2_struct(tDot11fAssocResponse *ar,
tpSirAssocRsp pAssocRsp)
{
if (ar->fils_session.present) {
pe_debug("fils session IE present");
pAssocRsp->fils_session.present = true;
qdf_mem_copy(pAssocRsp->fils_session.session,
ar->fils_session.session,
DOT11F_IE_FILS_SESSION_MAX_LEN);
}
if (ar->fils_key_confirmation.present) {
pe_debug("fils key conf IE present");
pAssocRsp->fils_key_auth.num_key_auth =
ar->fils_key_confirmation.num_key_auth;
qdf_mem_copy(pAssocRsp->fils_key_auth.key_auth,
ar->fils_key_confirmation.key_auth,
pAssocRsp->fils_key_auth.num_key_auth);
}
if (ar->fils_kde.present) {
pe_debug("fils kde IE present %d",
ar->fils_kde.num_kde_list);
pAssocRsp->fils_kde.num_kde_list =
ar->fils_kde.num_kde_list;
qdf_mem_copy(pAssocRsp->fils_kde.key_rsc,
ar->fils_kde.key_rsc, KEY_RSC_LEN);
qdf_mem_copy(&pAssocRsp->fils_kde.kde_list,
&ar->fils_kde.kde_list,
pAssocRsp->fils_kde.num_kde_list);
}
if (ar->fils_hlp_container.present) {
pe_debug("FILS HLP container IE present");
sir_copy_mac_addr(pAssocRsp->dst_mac.bytes,
ar->fils_hlp_container.dest_mac);
sir_copy_mac_addr(pAssocRsp->src_mac.bytes,
ar->fils_hlp_container.src_mac);
pAssocRsp->hlp_data_len = ar->fils_hlp_container.num_hlp_packet;
qdf_mem_copy(pAssocRsp->hlp_data,
ar->fils_hlp_container.hlp_packet,
pAssocRsp->hlp_data_len);
if (ar->fragment_ie.present) {
pe_debug("FILS fragment ie present");
qdf_mem_copy(pAssocRsp->hlp_data +
pAssocRsp->hlp_data_len,
ar->fragment_ie.data,
ar->fragment_ie.num_data);
pAssocRsp->hlp_data_len += ar->fragment_ie.num_data;
}
}
}
#else
static inline void fils_convert_assoc_rsp_frame2_struct(tDot11fAssocResponse
*ar, tpSirAssocRsp
pAssocRsp)
{ }
#endif
QDF_STATUS wlan_parse_ftie_sha384(uint8_t *frame, uint32_t frame_len,
struct sSirAssocRsp *assoc_rsp)
{
const uint8_t *ie, *ie_end, *pos;
uint8_t ie_len, remaining_ie_len;
struct wlan_sha384_ftinfo_subelem *ft_subelem;
ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_FTINFO, frame, frame_len);
if (!ie) {
pe_err("FT IE not present");
return QDF_STATUS_E_FAILURE;
}
if (!ie[1]) {
pe_err("FT IE length is zero");
return QDF_STATUS_E_FAILURE;
}
ie_len = ie[1];
if (ie_len < sizeof(struct wlan_sha384_ftinfo)) {
pe_err("Invalid FTIE len:%d", ie_len);
return QDF_STATUS_E_FAILURE;
}
remaining_ie_len = ie_len;
pos = ie + 2;
qdf_mem_copy(&assoc_rsp->sha384_ft_info, pos,
sizeof(struct wlan_sha384_ftinfo));
ie_end = ie + ie_len;
pos += sizeof(struct wlan_sha384_ftinfo);
remaining_ie_len -= sizeof(struct wlan_sha384_ftinfo);
ft_subelem = &assoc_rsp->sha384_ft_subelem;
qdf_mem_zero(ft_subelem, sizeof(*ft_subelem));
while (ie_end - pos >= 2) {
uint8_t id, len;
id = *pos++;
len = *pos++;
/* Subtract data length(len) + 1 bytes for
* Subelement ID + 1 bytes for length from
* remaining FTIE buffer len (ie_len).
* Subelement Parameter(s) field :
* Subelement ID Length Data
* Octets: 1 1 variable
*/
if (len < 1 || remaining_ie_len < (len + 2)) {
pe_err("Invalid FT subelem length");
return QDF_STATUS_E_FAILURE;
}
remaining_ie_len -= (len + 2);
switch (id) {
case FTIE_SUBELEM_R1KH_ID:
if (len != FTIE_R1KH_LEN) {
pe_err("Invalid R1KH-ID length: %d",
len);
return QDF_STATUS_E_FAILURE;
}
ft_subelem->r1kh_id.present = 1;
qdf_mem_copy(ft_subelem->r1kh_id.PMK_R1_ID,
pos, FTIE_R1KH_LEN);
break;
case FTIE_SUBELEM_GTK:
if (ft_subelem->gtk) {
qdf_mem_zero(ft_subelem->gtk,
ft_subelem->gtk_len);
ft_subelem->gtk_len = 0;
qdf_mem_free(ft_subelem->gtk);
}
ft_subelem->gtk = qdf_mem_malloc(len);
if (!ft_subelem->gtk)
return QDF_STATUS_E_NOMEM;
qdf_mem_copy(ft_subelem->gtk, pos, len);
ft_subelem->gtk_len = len;
break;
case FTIE_SUBELEM_R0KH_ID:
if (len < 1 || len > FTIE_R0KH_MAX_LEN) {
pe_err("Invalid R0KH-ID length: %d",
len);
return QDF_STATUS_E_FAILURE;
}
ft_subelem->r0kh_id.present = 1;
ft_subelem->r0kh_id.num_PMK_R0_ID = len;
qdf_mem_copy(ft_subelem->r0kh_id.PMK_R0_ID,
pos, len);
break;
case FTIE_SUBELEM_IGTK:
if (ft_subelem->igtk) {
qdf_mem_zero(ft_subelem->igtk,
ft_subelem->igtk_len);
ft_subelem->igtk_len = 0;
qdf_mem_free(ft_subelem->igtk);
}
ft_subelem->igtk = qdf_mem_malloc(len);
if (!ft_subelem->igtk)
return QDF_STATUS_E_NOMEM;
qdf_mem_copy(ft_subelem->igtk, pos, len);
ft_subelem->igtk_len = len;
break;
default:
pe_debug("Unknown subelem id %d len:%d",
id, len);
break;
}
pos += len;
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
sir_convert_assoc_resp_frame2_struct(struct mac_context *mac,
struct pe_session *session_entry,
uint8_t *frame, uint32_t frame_len,
tpSirAssocRsp pAssocRsp)
{
tDot11fAssocResponse *ar;
enum ani_akm_type auth_type;
uint32_t status, ie_len;
QDF_STATUS qdf_status;
uint8_t cnt = 0;
bool sha384_akm;
uint8_t *ie_ptr;
ar = qdf_mem_malloc(sizeof(*ar));
if (!ar)
return QDF_STATUS_E_FAILURE;
/* decrypt the cipher text using AEAD decryption */
if (lim_is_fils_connection(session_entry)) {
status = aead_decrypt_assoc_rsp(mac, session_entry,
ar, frame, &frame_len);
if (!QDF_IS_STATUS_SUCCESS(status)) {
pe_err("FILS assoc rsp AEAD decrypt fails");
qdf_mem_free(ar);
return QDF_STATUS_E_FAILURE;
}
}
status = dot11f_parse_assoc_response(mac, frame, frame_len, ar, false);
if (QDF_STATUS_SUCCESS != status) {
qdf_mem_free(ar);
return status;
}
/* Capabilities */
pAssocRsp->capabilityInfo.ess = ar->Capabilities.ess;
pAssocRsp->capabilityInfo.ibss = ar->Capabilities.ibss;
pAssocRsp->capabilityInfo.cfPollable = ar->Capabilities.cfPollable;
pAssocRsp->capabilityInfo.cfPollReq = ar->Capabilities.cfPollReq;
pAssocRsp->capabilityInfo.privacy = ar->Capabilities.privacy;
pAssocRsp->capabilityInfo.shortPreamble =
ar->Capabilities.shortPreamble;
pAssocRsp->capabilityInfo.pbcc = ar->Capabilities.pbcc;
pAssocRsp->capabilityInfo.channelAgility =
ar->Capabilities.channelAgility;
pAssocRsp->capabilityInfo.spectrumMgt = ar->Capabilities.spectrumMgt;
pAssocRsp->capabilityInfo.qos = ar->Capabilities.qos;
pAssocRsp->capabilityInfo.shortSlotTime =
ar->Capabilities.shortSlotTime;
pAssocRsp->capabilityInfo.apsd = ar->Capabilities.apsd;
pAssocRsp->capabilityInfo.rrm = ar->Capabilities.rrm;
pAssocRsp->capabilityInfo.dsssOfdm = ar->Capabilities.dsssOfdm;
pAssocRsp->capabilityInfo.delayedBA = ar->Capabilities.delayedBA;
pAssocRsp->capabilityInfo.immediateBA = ar->Capabilities.immediateBA;
pAssocRsp->status_code = ar->Status.status;
pAssocRsp->aid = ar->AID.associd;
#ifdef WLAN_FEATURE_11W
if (ar->TimeoutInterval.present) {
pAssocRsp->TimeoutInterval.present = 1;
pAssocRsp->TimeoutInterval.timeoutType =
ar->TimeoutInterval.timeoutType;
pAssocRsp->TimeoutInterval.timeoutValue =
ar->TimeoutInterval.timeoutValue;
}
#endif
if (!ar->SuppRates.present) {
pAssocRsp->suppRatesPresent = 0;
pe_debug_rl("Mandatory IE Supported Rates not present!");
} else {
pAssocRsp->suppRatesPresent = 1;
convert_supp_rates(mac, &pAssocRsp->supportedRates,
&ar->SuppRates);
}
if (ar->ExtSuppRates.present) {
pAssocRsp->extendedRatesPresent = 1;
convert_ext_supp_rates(mac, &pAssocRsp->extendedRates,
&ar->ExtSuppRates);
}
if (ar->EDCAParamSet.present) {
pAssocRsp->edcaPresent = 1;
convert_edca_param(mac, &pAssocRsp->edca, &ar->EDCAParamSet);
}
if (ar->WMMParams.present) {
pAssocRsp->wmeEdcaPresent = 1;
convert_wmm_params(mac, &pAssocRsp->edca, &ar->WMMParams);
pe_debug("Received Assoc Resp with WMM Param");
__print_wmm_params(mac, &ar->WMMParams);
}
if (ar->HTCaps.present) {
pe_debug("Received Assoc Resp with HT Cap");
qdf_mem_copy(&pAssocRsp->HTCaps, &ar->HTCaps,
sizeof(tDot11fIEHTCaps));
}
if (ar->HTInfo.present) {
pe_debug("Received Assoc Resp with HT Info");
qdf_mem_copy(&pAssocRsp->HTInfo, &ar->HTInfo,
sizeof(tDot11fIEHTInfo));
}
if (ar->MobilityDomain.present) {
/* MobilityDomain */
pAssocRsp->mdiePresent = 1;
qdf_mem_copy((uint8_t *) &(pAssocRsp->mdie[0]),
(uint8_t *) &(ar->MobilityDomain.MDID),
sizeof(uint16_t));
pAssocRsp->mdie[2] = ((ar->MobilityDomain.overDSCap << 0) |
(ar->MobilityDomain.resourceReqCap << 1));
pe_debug("new mdie=%02x%02x%02x",
(unsigned int)pAssocRsp->mdie[0],
(unsigned int)pAssocRsp->mdie[1],
(unsigned int)pAssocRsp->mdie[2]);
}
/*
* If the connection is based on SHA384 AKM suite,
* then the length of MIC is 24 bytes, but frame parser
* has FTIE MIC of 16 bytes only. This results in parsing FTIE
* failure and R0KH and R1KH are not sent to firmware over RSO
* command. Frame parser doesn't have
* info on the connected AKM. So parse the FTIE again if
* AKM is sha384 based and extract the R0KH and R1KH using the new
* parsing logic.
*/
auth_type = session_entry->connected_akm;
sha384_akm = lim_is_sha384_akm(auth_type);
if (sha384_akm) {
ie_ptr = frame + FIXED_PARAM_OFFSET_ASSOC_RSP;
ie_len = frame_len - FIXED_PARAM_OFFSET_ASSOC_RSP;
qdf_status = wlan_parse_ftie_sha384(ie_ptr, ie_len, pAssocRsp);
if (QDF_IS_STATUS_ERROR(qdf_status)) {
pe_err("FT IE parsing failed status:%d", status);
} else {
pe_debug("FT: R0KH present:%d len:%d R1KH present%d",
pAssocRsp->sha384_ft_subelem.r0kh_id.present,
pAssocRsp->sha384_ft_subelem.r0kh_id.num_PMK_R0_ID,
pAssocRsp->sha384_ft_subelem.r1kh_id.present);
ar->FTInfo.present = false;
}
} else if (ar->FTInfo.present) {
pe_debug("FT: R0KH present:%d, len:%d R1KH present:%d",
ar->FTInfo.R0KH_ID.present,
ar->FTInfo.R0KH_ID.num_PMK_R0_ID,
ar->FTInfo.R1KH_ID.present);
pAssocRsp->ftinfoPresent = 1;
qdf_mem_copy(&pAssocRsp->FTInfo, &ar->FTInfo,
sizeof(tDot11fIEFTInfo));
}
if (ar->num_RICDataDesc && ar->num_RICDataDesc <= 2) {
for (cnt = 0; cnt < ar->num_RICDataDesc; cnt++) {
if (ar->RICDataDesc[cnt].present) {
qdf_mem_copy(&pAssocRsp->RICData[cnt],
&ar->RICDataDesc[cnt],
sizeof(tDot11fIERICDataDesc));
}
}
pAssocRsp->num_RICData = ar->num_RICDataDesc;
pAssocRsp->ricPresent = true;
}
#ifdef FEATURE_WLAN_ESE
if (ar->num_WMMTSPEC) {
pAssocRsp->num_tspecs = ar->num_WMMTSPEC;
for (cnt = 0; cnt < ar->num_WMMTSPEC; cnt++) {
qdf_mem_copy(&pAssocRsp->TSPECInfo[cnt],
&ar->WMMTSPEC[cnt],
sizeof(tDot11fIEWMMTSPEC));
}
pAssocRsp->tspecPresent = true;
}
if (ar->ESETrafStrmMet.present) {
pAssocRsp->tsmPresent = 1;
qdf_mem_copy(&pAssocRsp->tsmIE.tsid,
&ar->ESETrafStrmMet.tsid,
sizeof(struct ese_tsm_ie));
}
#endif
if (ar->VHTCaps.present) {
qdf_mem_copy(&pAssocRsp->VHTCaps, &ar->VHTCaps,
sizeof(tDot11fIEVHTCaps));
pe_debug("Received Assoc Response with VHT Cap");
lim_log_vht_cap(mac, &pAssocRsp->VHTCaps);
}
if (ar->VHTOperation.present) {
qdf_mem_copy(&pAssocRsp->VHTOperation, &ar->VHTOperation,
sizeof(tDot11fIEVHTOperation));
pe_debug("Received Assoc Response with VHT Operation");
lim_log_vht_operation(mac, &pAssocRsp->VHTOperation);
}
if (ar->ExtCap.present) {
struct s_ext_cap *ext_cap;
qdf_mem_copy(&pAssocRsp->ExtCap, &ar->ExtCap,
sizeof(tDot11fIEExtCap));
ext_cap = (struct s_ext_cap *)&pAssocRsp->ExtCap.bytes;
pe_debug("timingMeas: %d, finetimingMeas Init: %d, Resp: %d",
ext_cap->timing_meas, ext_cap->fine_time_meas_initiator,
ext_cap->fine_time_meas_responder);
}
if (ar->QosMapSet.present) {
pAssocRsp->QosMapSet.present = 1;
convert_qos_mapset_frame(mac, &pAssocRsp->QosMapSet,
&ar->QosMapSet);
pe_debug("Received Assoc Response with Qos Map Set");
lim_log_qos_map_set(mac, &pAssocRsp->QosMapSet);
}
pAssocRsp->vendor_vht_ie.present = ar->vendor_vht_ie.present;
if (ar->vendor_vht_ie.present)
pAssocRsp->vendor_vht_ie.sub_type = ar->vendor_vht_ie.sub_type;
if (ar->OBSSScanParameters.present) {
qdf_mem_copy(&pAssocRsp->obss_scanparams,
&ar->OBSSScanParameters,
sizeof(struct sDot11fIEOBSSScanParameters));
}
if (ar->vendor_vht_ie.VHTCaps.present) {
qdf_mem_copy(&pAssocRsp->vendor_vht_ie.VHTCaps,
&ar->vendor_vht_ie.VHTCaps,
sizeof(tDot11fIEVHTCaps));
pe_debug("Received Assoc Response with Vendor specific VHT Cap");
lim_log_vht_cap(mac, &pAssocRsp->VHTCaps);
}
if (ar->vendor_vht_ie.VHTOperation.present) {
qdf_mem_copy(&pAssocRsp->vendor_vht_ie.VHTOperation,
&ar->vendor_vht_ie.VHTOperation,
sizeof(tDot11fIEVHTOperation));
pe_debug("Received Assoc Response with Vendor specific VHT Oper");
lim_log_vht_operation(mac, &pAssocRsp->VHTOperation);
}
if (ar->qcn_ie.present)
qdf_mem_copy(&pAssocRsp->qcn_ie, &ar->qcn_ie,
sizeof(tDot11fIEqcn_ie));
if (ar->he_cap.present) {
pe_debug("11AX: HE cap IE present");
qdf_mem_copy(&pAssocRsp->he_cap, &ar->he_cap,
sizeof(tDot11fIEhe_cap));
}
if (ar->he_op.present) {
pe_debug("11AX: HE Operation IE present");
qdf_mem_copy(&pAssocRsp->he_op, &ar->he_op,
sizeof(tDot11fIEhe_op));
pe_debug("bss_clr %d def_pe %d part_bss_clr %d bss_col_dis %d",
pAssocRsp->he_op.bss_color,
pAssocRsp->he_op.default_pe,
pAssocRsp->he_op.partial_bss_col,
pAssocRsp->he_op.bss_col_disabled);
}
if (ar->he_6ghz_band_cap.present) {
pe_debug("11AX: HE Band Capability IE present");
qdf_mem_copy(&pAssocRsp->he_6ghz_band_cap,
&ar->he_6ghz_band_cap,
sizeof(tDot11fIEhe_6ghz_band_cap));
}
if (ar->mu_edca_param_set.present) {
pe_debug("11AX: HE MU EDCA param IE present");
pAssocRsp->mu_edca_present = true;
convert_mu_edca_param(mac, &pAssocRsp->mu_edca,
&ar->mu_edca_param_set);
}
if (ar->MBO_IE.present && ar->MBO_IE.rssi_assoc_rej.present) {
qdf_mem_copy(&pAssocRsp->rssi_assoc_rej,
&ar->MBO_IE.rssi_assoc_rej,
sizeof(tDot11fTLVrssi_assoc_rej));
pe_debug("Received Assoc Response with rssi based assoc rej");
}
fils_convert_assoc_rsp_frame2_struct(ar, pAssocRsp);
qdf_mem_free(ar);
return QDF_STATUS_SUCCESS;
} /* End sir_convert_assoc_resp_frame2_struct. */
QDF_STATUS
sir_convert_reassoc_req_frame2_struct(struct mac_context *mac,
uint8_t *pFrame,
uint32_t nFrame, tpSirAssocReq pAssocReq)
{
tDot11fReAssocRequest *ar;
uint32_t status;
ar = qdf_mem_malloc(sizeof(*ar));
if (!ar)
return QDF_STATUS_E_NOMEM;
/* Zero-init our [out] parameter, */
qdf_mem_zero((uint8_t *) pAssocReq, sizeof(tSirAssocReq));
/* delegate to the framesc-generated code, */
status = dot11f_unpack_re_assoc_request(mac, pFrame, nFrame,
ar, false);
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse a Re-association Request (0x%08x, %d bytes):",
status, nFrame);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
pFrame, nFrame);
qdf_mem_free(ar);
return QDF_STATUS_E_FAILURE;
} else if (DOT11F_WARNED(status)) {
pe_debug("There were warnings while unpacking a Re-association Request (0x%08x, %d bytes):",
status, nFrame);
}
/* & "transliterate" from a 'tDot11fReAssocRequest' to a 'tSirAssocReq'... */
/* make sure this is seen as a re-assoc request */
pAssocReq->reassocRequest = 1;
/* Capabilities */
pAssocReq->capabilityInfo.ess = ar->Capabilities.ess;
pAssocReq->capabilityInfo.ibss = ar->Capabilities.ibss;
pAssocReq->capabilityInfo.cfPollable = ar->Capabilities.cfPollable;
pAssocReq->capabilityInfo.cfPollReq = ar->Capabilities.cfPollReq;
pAssocReq->capabilityInfo.privacy = ar->Capabilities.privacy;
pAssocReq->capabilityInfo.shortPreamble = ar->Capabilities.shortPreamble;
pAssocReq->capabilityInfo.pbcc = ar->Capabilities.pbcc;
pAssocReq->capabilityInfo.channelAgility =
ar->Capabilities.channelAgility;
pAssocReq->capabilityInfo.spectrumMgt = ar->Capabilities.spectrumMgt;
pAssocReq->capabilityInfo.qos = ar->Capabilities.qos;
pAssocReq->capabilityInfo.shortSlotTime = ar->Capabilities.shortSlotTime;
pAssocReq->capabilityInfo.apsd = ar->Capabilities.apsd;
pAssocReq->capabilityInfo.rrm = ar->Capabilities.rrm;
pAssocReq->capabilityInfo.dsssOfdm = ar->Capabilities.dsssOfdm;
pAssocReq->capabilityInfo.delayedBA = ar->Capabilities.delayedBA;
pAssocReq->capabilityInfo.immediateBA = ar->Capabilities.immediateBA;
/* Listen Interval */
pAssocReq->listenInterval = ar->ListenInterval.interval;
/* SSID */
if (ar->SSID.present) {
pAssocReq->ssidPresent = 1;
convert_ssid(mac, &pAssocReq->ssId, &ar->SSID);
}
/* Supported Rates */
if (ar->SuppRates.present) {
pAssocReq->suppRatesPresent = 1;
convert_supp_rates(mac, &pAssocReq->supportedRates,
&ar->SuppRates);
}
/* Extended Supported Rates */
if (ar->ExtSuppRates.present) {
pAssocReq->extendedRatesPresent = 1;
convert_ext_supp_rates(mac, &pAssocReq->extendedRates,
&ar->ExtSuppRates);
}
/* QOS Capabilities: */
if (ar->QOSCapsStation.present) {
pAssocReq->qosCapabilityPresent = 1;
convert_qos_caps_station(mac, &pAssocReq->qosCapability,
&ar->QOSCapsStation);
}
/* WPA */
if (ar->WPAOpaque.present) {
pAssocReq->wpaPresent = 1;
convert_wpa_opaque(mac, &pAssocReq->wpa, &ar->WPAOpaque);
}
/* RSN */
if (ar->RSNOpaque.present) {
pAssocReq->rsnPresent = 1;
convert_rsn_opaque(mac, &pAssocReq->rsn, &ar->RSNOpaque);
}
/* Power Capabilities */
if (ar->PowerCaps.present) {
pAssocReq->powerCapabilityPresent = 1;
convert_power_caps(mac, &pAssocReq->powerCapability,
&ar->PowerCaps);
}
/* Supported Channels */
if (ar->SuppChannels.present) {
pAssocReq->supportedChannelsPresent = 1;
convert_supp_channels(mac, &pAssocReq->supportedChannels,
&ar->SuppChannels);
}
if (ar->HTCaps.present) {
qdf_mem_copy(&pAssocReq->HTCaps, &ar->HTCaps,
sizeof(tDot11fIEHTCaps));
}
if (ar->WMMInfoStation.present) {
pAssocReq->wmeInfoPresent = 1;
qdf_mem_copy(&pAssocReq->WMMInfoStation, &ar->WMMInfoStation,
sizeof(tDot11fIEWMMInfoStation));
}
if (ar->WMMCaps.present)
pAssocReq->wsmCapablePresent = 1;
if (!pAssocReq->ssidPresent) {
pe_debug("Received Assoc without SSID IE");
qdf_mem_free(ar);
return QDF_STATUS_E_FAILURE;
}
if (!pAssocReq->suppRatesPresent && !pAssocReq->extendedRatesPresent) {
pe_debug("Received Assoc without supp rate IE");
qdf_mem_free(ar);
return QDF_STATUS_E_FAILURE;
}
/* Why no call to 'updateAssocReqFromPropCapability' here, like */
/* there is in 'sir_convert_assoc_req_frame2_struct'? */
/* WSC IE */
if (ar->WscIEOpaque.present) {
pAssocReq->addIEPresent = 1;
convert_wsc_opaque(mac, &pAssocReq->addIE, &ar->WscIEOpaque);
}
if (ar->P2PIEOpaque.present) {
pAssocReq->addIEPresent = 1;
convert_p2p_opaque(mac, &pAssocReq->addIE, &ar->P2PIEOpaque);
}
#ifdef WLAN_FEATURE_WFD
if (ar->WFDIEOpaque.present) {
pAssocReq->addIEPresent = 1;
convert_wfd_opaque(mac, &pAssocReq->addIE, &ar->WFDIEOpaque);
}
#endif
if (ar->SuppOperatingClasses.present) {
uint8_t num_classes = ar->SuppOperatingClasses.num_classes;
if (num_classes > sizeof(ar->SuppOperatingClasses.classes))
num_classes =
sizeof(ar->SuppOperatingClasses.classes);
qdf_mem_copy(&pAssocReq->supp_operating_classes,
&ar->SuppOperatingClasses,
sizeof(tDot11fIESuppOperatingClasses));
QDF_TRACE_HEX_DUMP(
QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
ar->SuppOperatingClasses.classes, num_classes);
}
if (ar->VHTCaps.present) {
qdf_mem_copy(&pAssocReq->VHTCaps, &ar->VHTCaps,
sizeof(tDot11fIEVHTCaps));
}
if (ar->OperatingMode.present) {
qdf_mem_copy(&pAssocReq->operMode, &ar->OperatingMode,
sizeof(tDot11fIEOperatingMode));
pe_warn("Received Assoc Req with Operating Mode IE");
lim_log_operating_mode(mac, &pAssocReq->operMode);
}
if (ar->ExtCap.present) {
struct s_ext_cap *ext_cap;
qdf_mem_copy(&pAssocReq->ExtCap, &ar->ExtCap,
sizeof(tDot11fIEExtCap));
ext_cap = (struct s_ext_cap *)&pAssocReq->ExtCap.bytes;
pe_debug("timingMeas: %d, finetimingMeas Init: %d, Resp: %d",
ext_cap->timing_meas, ext_cap->fine_time_meas_initiator,
ext_cap->fine_time_meas_responder);
}
if (ar->he_cap.present) {
qdf_mem_copy(&pAssocReq->he_cap, &ar->he_cap,
sizeof(tDot11fIEhe_cap));
}
if (ar->he_6ghz_band_cap.present) {
qdf_mem_copy(&pAssocReq->he_6ghz_band_cap,
&ar->he_6ghz_band_cap,
sizeof(tDot11fIEhe_6ghz_band_cap));
}
qdf_mem_free(ar);
return QDF_STATUS_SUCCESS;
} /* End sir_convert_reassoc_req_frame2_struct. */
#ifdef FEATURE_WLAN_ESE
QDF_STATUS
sir_beacon_ie_ese_bcn_report(struct mac_context *mac,
uint8_t *pPayload, const uint32_t nPayload,
uint8_t **outIeBuf, uint32_t *pOutIeLen)
{
tDot11fBeaconIEs *pBies = NULL;
uint32_t status = QDF_STATUS_SUCCESS;
QDF_STATUS retStatus = QDF_STATUS_SUCCESS;
tSirEseBcnReportMandatoryIe eseBcnReportMandatoryIe;
/* To store how many bytes are required to be allocated
for Bcn report mandatory Ies */
uint16_t numBytes = 0, freeBytes = 0;
uint8_t *pos = NULL;
/* Zero-init our [out] parameter, */
qdf_mem_zero((uint8_t *) &eseBcnReportMandatoryIe,
sizeof(eseBcnReportMandatoryIe));
pBies = qdf_mem_malloc(sizeof(tDot11fBeaconIEs));
if (!pBies)
return QDF_STATUS_E_NOMEM;
qdf_mem_zero(pBies, sizeof(tDot11fBeaconIEs));
/* delegate to the framesc-generated code, */
status = dot11f_unpack_beacon_i_es(mac, pPayload, nPayload,
pBies, false);
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse Beacon IEs (0x%08x, %d bytes):",
status, nPayload);
qdf_mem_free(pBies);
return QDF_STATUS_E_FAILURE;
} else if (DOT11F_WARNED(status)) {
pe_debug("There were warnings while unpacking Beacon IEs (0x%08x, %d bytes):",
status, nPayload);
}
/* & "transliterate" from a 'tDot11fBeaconIEs' to a 'eseBcnReportMandatoryIe'... */
if (!pBies->SSID.present) {
pe_debug("Mandatory IE SSID not present!");
} else {
eseBcnReportMandatoryIe.ssidPresent = 1;
convert_ssid(mac, &eseBcnReportMandatoryIe.ssId, &pBies->SSID);
/* 1 for EID, 1 for length and length bytes */
numBytes += 1 + 1 + eseBcnReportMandatoryIe.ssId.length;
}
if (!pBies->SuppRates.present) {
pe_debug_rl("Mandatory IE Supported Rates not present!");
} else {
eseBcnReportMandatoryIe.suppRatesPresent = 1;
convert_supp_rates(mac, &eseBcnReportMandatoryIe.supportedRates,
&pBies->SuppRates);
numBytes +=
1 + 1 + eseBcnReportMandatoryIe.supportedRates.numRates;
}
if (pBies->FHParamSet.present) {
eseBcnReportMandatoryIe.fhParamPresent = 1;
convert_fh_params(mac, &eseBcnReportMandatoryIe.fhParamSet,
&pBies->FHParamSet);
numBytes += 1 + 1 + WLAN_FH_PARAM_IE_MAX_LEN;
}
if (pBies->DSParams.present) {
eseBcnReportMandatoryIe.dsParamsPresent = 1;
eseBcnReportMandatoryIe.dsParamSet.channelNumber =
pBies->DSParams.curr_channel;
numBytes += 1 + 1 + WLAN_DS_PARAM_IE_MAX_LEN;
}
if (pBies->CFParams.present) {
eseBcnReportMandatoryIe.cfPresent = 1;
convert_cf_params(mac, &eseBcnReportMandatoryIe.cfParamSet,
&pBies->CFParams);
numBytes += 1 + 1 + WLAN_CF_PARAM_IE_MAX_LEN;
}
if (pBies->IBSSParams.present) {
eseBcnReportMandatoryIe.ibssParamPresent = 1;
eseBcnReportMandatoryIe.ibssParamSet.atim =
pBies->IBSSParams.atim;
numBytes += 1 + 1 + WLAN_IBSS_IE_MAX_LEN;
}
if (pBies->TIM.present) {
eseBcnReportMandatoryIe.timPresent = 1;
eseBcnReportMandatoryIe.tim.dtimCount = pBies->TIM.dtim_count;
eseBcnReportMandatoryIe.tim.dtimPeriod = pBies->TIM.dtim_period;
eseBcnReportMandatoryIe.tim.bitmapControl = pBies->TIM.bmpctl;
/* As per the ESE spec, May truncate and report first 4 octets only */
numBytes += 1 + 1 + SIR_MAC_TIM_EID_MIN;
}
if (pBies->RRMEnabledCap.present) {
eseBcnReportMandatoryIe.rrmPresent = 1;
qdf_mem_copy(&eseBcnReportMandatoryIe.rmEnabledCapabilities,
&pBies->RRMEnabledCap,
sizeof(tDot11fIERRMEnabledCap));
numBytes += 1 + 1 + WLAN_RM_CAPABILITY_IE_MAX_LEN;
}
*outIeBuf = qdf_mem_malloc(numBytes);
if (!*outIeBuf) {
qdf_mem_free(pBies);
return QDF_STATUS_E_NOMEM;
}
pos = *outIeBuf;
*pOutIeLen = numBytes;
freeBytes = numBytes;
/* Start filling the output Ie with Mandatory IE information */
/* Fill SSID IE */
if (eseBcnReportMandatoryIe.ssidPresent) {
if (freeBytes < (1 + 1 + eseBcnReportMandatoryIe.ssId.length)) {
pe_err("Insufficient memory to copy SSID");
retStatus = QDF_STATUS_E_FAILURE;
goto err_bcnrep;
}
*pos = WLAN_ELEMID_SSID;
pos++;
*pos = eseBcnReportMandatoryIe.ssId.length;
pos++;
qdf_mem_copy(pos,
(uint8_t *) eseBcnReportMandatoryIe.ssId.ssId,
eseBcnReportMandatoryIe.ssId.length);
pos += eseBcnReportMandatoryIe.ssId.length;
freeBytes -= (1 + 1 + eseBcnReportMandatoryIe.ssId.length);
}
/* Fill Supported Rates IE */
if (eseBcnReportMandatoryIe.suppRatesPresent) {
if (freeBytes <
(1 + 1 + eseBcnReportMandatoryIe.supportedRates.numRates)) {
pe_err("Insufficient memory to copy Rates IE");
retStatus = QDF_STATUS_E_FAILURE;
goto err_bcnrep;
}
if (eseBcnReportMandatoryIe.supportedRates.numRates <=
WLAN_SUPPORTED_RATES_IE_MAX_LEN) {
*pos = WLAN_ELEMID_RATES;
pos++;
*pos = eseBcnReportMandatoryIe.supportedRates.numRates;
pos++;
qdf_mem_copy(pos,
(uint8_t *) eseBcnReportMandatoryIe.supportedRates.
rate,
eseBcnReportMandatoryIe.supportedRates.numRates);
pos += eseBcnReportMandatoryIe.supportedRates.numRates;
freeBytes -=
(1 + 1 +
eseBcnReportMandatoryIe.supportedRates.numRates);
}
}
/* Fill FH Parameter set IE */
if (eseBcnReportMandatoryIe.fhParamPresent) {
if (freeBytes < (1 + 1 + WLAN_FH_PARAM_IE_MAX_LEN)) {
pe_err("Insufficient memory to copy FHIE");
retStatus = QDF_STATUS_E_FAILURE;
goto err_bcnrep;
}
*pos = WLAN_ELEMID_FHPARMS;
pos++;
*pos = WLAN_FH_PARAM_IE_MAX_LEN;
pos++;
qdf_mem_copy(pos,
(uint8_t *) &eseBcnReportMandatoryIe.fhParamSet,
WLAN_FH_PARAM_IE_MAX_LEN);
pos += WLAN_FH_PARAM_IE_MAX_LEN;
freeBytes -= (1 + 1 + WLAN_FH_PARAM_IE_MAX_LEN);
}
/* Fill DS Parameter set IE */
if (eseBcnReportMandatoryIe.dsParamsPresent) {
if (freeBytes < (1 + 1 + WLAN_DS_PARAM_IE_MAX_LEN)) {
pe_err("Insufficient memory to copy DS IE");
retStatus = QDF_STATUS_E_FAILURE;
goto err_bcnrep;
}
*pos = WLAN_ELEMID_DSPARMS;
pos++;
*pos = WLAN_DS_PARAM_IE_MAX_LEN;
pos++;
*pos = eseBcnReportMandatoryIe.dsParamSet.channelNumber;
pos += WLAN_DS_PARAM_IE_MAX_LEN;
freeBytes -= (1 + 1 + WLAN_DS_PARAM_IE_MAX_LEN);
}
/* Fill CF Parameter set */
if (eseBcnReportMandatoryIe.cfPresent) {
if (freeBytes < (1 + 1 + WLAN_CF_PARAM_IE_MAX_LEN)) {
pe_err("Insufficient memory to copy CF IE");
retStatus = QDF_STATUS_E_FAILURE;
goto err_bcnrep;
}
*pos = WLAN_ELEMID_CFPARMS;
pos++;
*pos = WLAN_CF_PARAM_IE_MAX_LEN;
pos++;
qdf_mem_copy(pos,
(uint8_t *) &eseBcnReportMandatoryIe.cfParamSet,
WLAN_CF_PARAM_IE_MAX_LEN);
pos += WLAN_CF_PARAM_IE_MAX_LEN;
freeBytes -= (1 + 1 + WLAN_CF_PARAM_IE_MAX_LEN);
}
/* Fill IBSS Parameter set IE */
if (eseBcnReportMandatoryIe.ibssParamPresent) {
if (freeBytes < (1 + 1 + WLAN_IBSS_IE_MAX_LEN)) {
pe_err("Insufficient memory to copy IBSS IE");
retStatus = QDF_STATUS_E_FAILURE;
goto err_bcnrep;
}
*pos = WLAN_ELEMID_IBSSPARMS;
pos++;
*pos = WLAN_IBSS_IE_MAX_LEN;
pos++;
qdf_mem_copy(pos,
(uint8_t *) &eseBcnReportMandatoryIe.ibssParamSet.
atim, WLAN_IBSS_IE_MAX_LEN);
pos += WLAN_IBSS_IE_MAX_LEN;
freeBytes -= (1 + 1 + WLAN_IBSS_IE_MAX_LEN);
}
/* Fill TIM IE */
if (eseBcnReportMandatoryIe.timPresent) {
if (freeBytes < (1 + 1 + SIR_MAC_TIM_EID_MIN)) {
pe_err("Insufficient memory to copy TIM IE");
retStatus = QDF_STATUS_E_FAILURE;
goto err_bcnrep;
}
*pos = WLAN_ELEMID_TIM;
pos++;
*pos = SIR_MAC_TIM_EID_MIN;
pos++;
qdf_mem_copy(pos,
(uint8_t *) &eseBcnReportMandatoryIe.tim,
SIR_MAC_TIM_EID_MIN);
pos += SIR_MAC_TIM_EID_MIN;
freeBytes -= (1 + 1 + SIR_MAC_TIM_EID_MIN);
}
/* Fill RM Capability IE */
if (eseBcnReportMandatoryIe.rrmPresent) {
if (freeBytes < (1 + 1 + WLAN_RM_CAPABILITY_IE_MAX_LEN)) {
pe_err("Insufficient memory to copy RRM IE");
retStatus = QDF_STATUS_E_FAILURE;
goto err_bcnrep;
}
*pos = WLAN_ELEMID_RRM;
pos++;
*pos = WLAN_RM_CAPABILITY_IE_MAX_LEN;
pos++;
qdf_mem_copy(pos,
(uint8_t *) &eseBcnReportMandatoryIe.
rmEnabledCapabilities,
WLAN_RM_CAPABILITY_IE_MAX_LEN);
freeBytes -= (1 + 1 + WLAN_RM_CAPABILITY_IE_MAX_LEN);
}
if (freeBytes != 0) {
pe_err("Mismatch in allocation and copying of IE in Bcn Rep");
retStatus = QDF_STATUS_E_FAILURE;
}
err_bcnrep:
/* The message counter would not be incremented in case of
* returning failure and hence next time, this function gets
* called, it would be using the same msg ctr for a different
* BSS.So, it is good to clear the memory allocated for a BSS
* that is returning failure.On success, the caller would take
* care of freeing up the memory*/
if (retStatus == QDF_STATUS_E_FAILURE) {
qdf_mem_free(*outIeBuf);
*outIeBuf = NULL;
}
qdf_mem_free(pBies);
return retStatus;
}
#endif /* FEATURE_WLAN_ESE */
#ifdef WLAN_FEATURE_11AX_BSS_COLOR
static void update_bss_color_change_from_beacon_ies(tDot11fBeaconIEs *bcn_ies,
tpSirProbeRespBeacon bcn_struct)
{
if (bcn_ies->bss_color_change.present) {
qdf_mem_copy(&bcn_struct->vendor_he_bss_color_change,
&bcn_ies->bss_color_change,
sizeof(tDot11fIEbss_color_change));
}
}
#else
static inline void update_bss_color_change_from_beacon_ies(
tDot11fBeaconIEs *bcn_ies,
tpSirProbeRespBeacon bcn_struct)
{}
#endif
QDF_STATUS
sir_parse_beacon_ie(struct mac_context *mac,
tpSirProbeRespBeacon pBeaconStruct,
uint8_t *pPayload, uint32_t nPayload)
{
tDot11fBeaconIEs *pBies;
uint32_t status;
/* Zero-init our [out] parameter, */
qdf_mem_zero((uint8_t *) pBeaconStruct, sizeof(tSirProbeRespBeacon));
pBies = qdf_mem_malloc(sizeof(tDot11fBeaconIEs));
if (!pBies)
return QDF_STATUS_E_NOMEM;
qdf_mem_zero(pBies, sizeof(tDot11fBeaconIEs));
/* delegate to the framesc-generated code, */
status = dot11f_unpack_beacon_i_es(mac, pPayload, nPayload,
pBies, false);
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse Beacon IEs (0x%08x, %d bytes):",
status, nPayload);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
pPayload, nPayload);
qdf_mem_free(pBies);
return QDF_STATUS_E_FAILURE;
} else if (DOT11F_WARNED(status)) {
pe_debug("warnings (0x%08x, %d bytes):", status, nPayload);
}
/* & "transliterate" from a 'tDot11fBeaconIEs' to a 'tSirProbeRespBeacon'... */
if (!pBies->SSID.present) {
pe_debug("Mandatory IE SSID not present!");
} else {
pBeaconStruct->ssidPresent = 1;
convert_ssid(mac, &pBeaconStruct->ssId, &pBies->SSID);
}
if (!pBies->SuppRates.present) {
pe_debug_rl("Mandatory IE Supported Rates not present!");
} else {
pBeaconStruct->suppRatesPresent = 1;
convert_supp_rates(mac, &pBeaconStruct->supportedRates,
&pBies->SuppRates);
}
if (pBies->ExtSuppRates.present) {
pBeaconStruct->extendedRatesPresent = 1;
convert_ext_supp_rates(mac, &pBeaconStruct->extendedRates,
&pBies->ExtSuppRates);
}
if (pBies->CFParams.present) {
pBeaconStruct->cfPresent = 1;
convert_cf_params(mac, &pBeaconStruct->cfParamSet,
&pBies->CFParams);
}
if (pBies->TIM.present) {
pBeaconStruct->timPresent = 1;
convert_tim(mac, &pBeaconStruct->tim, &pBies->TIM);
}
if (pBies->Country.present) {
pBeaconStruct->countryInfoPresent = 1;
convert_country(mac, &pBeaconStruct->countryInfoParam,
&pBies->Country);
}
/* 11h IEs */
if (pBies->TPCReport.present) {
pBeaconStruct->tpcReportPresent = 1;
qdf_mem_copy(&pBeaconStruct->tpcReport,
&pBies->TPCReport, sizeof(tDot11fIETPCReport));
}
if (pBies->PowerConstraints.present) {
pBeaconStruct->powerConstraintPresent = 1;
qdf_mem_copy(&pBeaconStruct->localPowerConstraint,
&pBies->PowerConstraints,
sizeof(tDot11fIEPowerConstraints));
}
#ifdef FEATURE_WLAN_ESE
if (pBies->ESEVersion.present)
pBeaconStruct->is_ese_ver_ie_present = 1;
if (pBies->ESETxmitPower.present) {
pBeaconStruct->eseTxPwr.present = 1;
pBeaconStruct->eseTxPwr.power_limit =
pBies->ESETxmitPower.power_limit;
}
if (pBies->QBSSLoad.present) {
qdf_mem_copy(&pBeaconStruct->QBSSLoad, &pBies->QBSSLoad,
sizeof(tDot11fIEQBSSLoad));
}
#endif
if (pBies->EDCAParamSet.present) {
pBeaconStruct->edcaPresent = 1;
convert_edca_param(mac, &pBeaconStruct->edcaParams,
&pBies->EDCAParamSet);
}
/* QOS Capabilities: */
if (pBies->QOSCapsAp.present) {
pBeaconStruct->qosCapabilityPresent = 1;
convert_qos_caps(mac, &pBeaconStruct->qosCapability,
&pBies->QOSCapsAp);
}
if (pBies->ChanSwitchAnn.present) {
pBeaconStruct->channelSwitchPresent = 1;
qdf_mem_copy(&pBeaconStruct->channelSwitchIE,
&pBies->ChanSwitchAnn,
sizeof(pBeaconStruct->channelSwitchIE));
}
if (pBies->SuppOperatingClasses.present) {
pBeaconStruct->supp_operating_class_present = 1;
qdf_mem_copy(&pBeaconStruct->supp_operating_classes,
&pBies->SuppOperatingClasses,
sizeof(tDot11fIESuppOperatingClasses));
}
if (pBies->ext_chan_switch_ann.present) {
pBeaconStruct->ext_chan_switch_present = 1;
qdf_mem_copy(&pBeaconStruct->ext_chan_switch,
&pBies->ext_chan_switch_ann,
sizeof(tDot11fIEext_chan_switch_ann));
}
if (pBies->sec_chan_offset_ele.present) {
pBeaconStruct->sec_chan_offset_present = 1;
qdf_mem_copy(&pBeaconStruct->sec_chan_offset,
&pBies->sec_chan_offset_ele,
sizeof(pBeaconStruct->sec_chan_offset));
}
if (pBies->Quiet.present) {
pBeaconStruct->quietIEPresent = 1;
qdf_mem_copy(&pBeaconStruct->quietIE, &pBies->Quiet,
sizeof(tDot11fIEQuiet));
}
if (pBies->HTCaps.present) {
qdf_mem_copy(&pBeaconStruct->HTCaps, &pBies->HTCaps,
sizeof(tDot11fIEHTCaps));
}
if (pBies->HTInfo.present) {
qdf_mem_copy(&pBeaconStruct->HTInfo, &pBies->HTInfo,
sizeof(tDot11fIEHTInfo));
}
if (pBies->he_op.oper_info_6g_present) {
pBeaconStruct->chan_freq = wlan_reg_chan_band_to_freq(mac->pdev,
pBies->he_op.oper_info_6g.info.primary_ch,
BIT(REG_BAND_6G));
} else if (pBies->DSParams.present) {
pBeaconStruct->dsParamsPresent = 1;
pBeaconStruct->chan_freq =
wlan_reg_legacy_chan_to_freq(mac->pdev,
pBies->DSParams.curr_channel);
} else if (pBies->HTInfo.present) {
pBeaconStruct->chan_freq =
wlan_reg_legacy_chan_to_freq(mac->pdev,
pBies->HTInfo.primaryChannel);
}
if (pBies->RSN.present) {
pBeaconStruct->rsnPresent = 1;
convert_rsn(mac, &pBeaconStruct->rsn, &pBies->RSN);
}
if (pBies->WPA.present) {
pBeaconStruct->wpaPresent = 1;
convert_wpa(mac, &pBeaconStruct->wpa, &pBies->WPA);
}
if (pBies->WMMParams.present) {
pBeaconStruct->wmeEdcaPresent = 1;
convert_wmm_params(mac, &pBeaconStruct->edcaParams,
&pBies->WMMParams);
}
if (pBies->WMMInfoAp.present) {
pBeaconStruct->wmeInfoPresent = 1;
}
if (pBies->WMMCaps.present) {
pBeaconStruct->wsmCapablePresent = 1;
}
if (pBies->ERPInfo.present) {
pBeaconStruct->erpPresent = 1;
convert_erp_info(mac, &pBeaconStruct->erpIEInfo,
&pBies->ERPInfo);
}
if (pBies->VHTCaps.present) {
pBeaconStruct->VHTCaps.present = 1;
qdf_mem_copy(&pBeaconStruct->VHTCaps, &pBies->VHTCaps,
sizeof(tDot11fIEVHTCaps));
}
if (pBies->VHTOperation.present) {
pBeaconStruct->VHTOperation.present = 1;
qdf_mem_copy(&pBeaconStruct->VHTOperation, &pBies->VHTOperation,
sizeof(tDot11fIEVHTOperation));
}
if (pBies->VHTExtBssLoad.present) {
pBeaconStruct->VHTExtBssLoad.present = 1;
qdf_mem_copy(&pBeaconStruct->VHTExtBssLoad,
&pBies->VHTExtBssLoad,
sizeof(tDot11fIEVHTExtBssLoad));
}
if (pBies->OperatingMode.present) {
pBeaconStruct->OperatingMode.present = 1;
qdf_mem_copy(&pBeaconStruct->OperatingMode,
&pBies->OperatingMode,
sizeof(tDot11fIEOperatingMode));
}
if (pBies->MobilityDomain.present) {
pBeaconStruct->mdiePresent = 1;
qdf_mem_copy(pBeaconStruct->mdie, &pBies->MobilityDomain.MDID,
SIR_MDIE_SIZE);
}
pBeaconStruct->Vendor1IEPresent = pBies->Vendor1IE.present;
pBeaconStruct->Vendor3IEPresent = pBies->Vendor3IE.present;
pBeaconStruct->vendor_vht_ie.present = pBies->vendor_vht_ie.present;
if (pBies->vendor_vht_ie.present)
pBeaconStruct->vendor_vht_ie.sub_type =
pBies->vendor_vht_ie.sub_type;
if (pBies->vendor_vht_ie.VHTCaps.present) {
pBeaconStruct->vendor_vht_ie.VHTCaps.present = 1;
qdf_mem_copy(&pBeaconStruct->vendor_vht_ie.VHTCaps,
&pBies->vendor_vht_ie.VHTCaps,
sizeof(tDot11fIEVHTCaps));
}
if (pBies->vendor_vht_ie.VHTOperation.present) {
pBeaconStruct->vendor_vht_ie.VHTOperation.present = 1;
qdf_mem_copy(&pBeaconStruct->vendor_vht_ie.VHTOperation,
&pBies->vendor_vht_ie.VHTOperation,
sizeof(tDot11fIEVHTOperation));
}
if (pBies->ExtCap.present) {
qdf_mem_copy(&pBeaconStruct->ext_cap, &pBies->ExtCap,
sizeof(tDot11fIEExtCap));
}
/* Update HS 2.0 Information Element */
if (pBies->hs20vendor_ie.present) {
pe_debug("HS20 Indication Element Present, rel#:%u, id:%u",
pBies->hs20vendor_ie.release_num,
pBies->hs20vendor_ie.hs_id_present);
qdf_mem_copy(&pBeaconStruct->hs20vendor_ie,
&pBies->hs20vendor_ie,
sizeof(tDot11fIEhs20vendor_ie) -
sizeof(pBies->hs20vendor_ie.hs_id));
if (pBies->hs20vendor_ie.hs_id_present)
qdf_mem_copy(&pBeaconStruct->hs20vendor_ie.hs_id,
&pBies->hs20vendor_ie.hs_id,
sizeof(pBies->hs20vendor_ie.hs_id));
}
if (pBies->MBO_IE.present) {
pBeaconStruct->MBO_IE_present = true;
if (pBies->MBO_IE.cellular_data_cap.present)
pBeaconStruct->MBO_capability =
pBies->MBO_IE.cellular_data_cap.cellular_connectivity;
if (pBies->MBO_IE.assoc_disallowed.present) {
pBeaconStruct->assoc_disallowed = true;
pBeaconStruct->assoc_disallowed_reason =
pBies->MBO_IE.assoc_disallowed.reason_code;
}
}
if (pBies->qcn_ie.present)
qdf_mem_copy(&pBeaconStruct->qcn_ie, &pBies->qcn_ie,
sizeof(tDot11fIEqcn_ie));
if (pBies->he_cap.present) {
qdf_mem_copy(&pBeaconStruct->he_cap, &pBies->he_cap,
sizeof(tDot11fIEhe_cap));
}
if (pBies->he_op.present) {
qdf_mem_copy(&pBeaconStruct->he_op, &pBies->he_op,
sizeof(tDot11fIEhe_op));
}
update_bss_color_change_from_beacon_ies(pBies, pBeaconStruct);
qdf_mem_free(pBies);
return QDF_STATUS_SUCCESS;
} /* End sir_parse_beacon_ie. */
#ifdef WLAN_FEATURE_11AX_BSS_COLOR
static void convert_bcon_bss_color_change_ie(tDot11fBeacon *bcn_frm,
tpSirProbeRespBeacon bcn_struct)
{
if (bcn_frm->bss_color_change.present) {
pe_debug("11AX: HE BSS color change present");
qdf_mem_copy(&bcn_struct->vendor_he_bss_color_change,
&bcn_frm->bss_color_change,
sizeof(tDot11fIEbss_color_change));
}
}
#else
static inline void convert_bcon_bss_color_change_ie(tDot11fBeacon *bcn_frm,
tpSirProbeRespBeacon bcn_struct)
{}
#endif
QDF_STATUS
sir_convert_beacon_frame2_struct(struct mac_context *mac,
uint8_t *pFrame,
tpSirProbeRespBeacon pBeaconStruct)
{
tDot11fBeacon *pBeacon;
uint32_t status, nPayload;
uint8_t *pPayload;
tpSirMacMgmtHdr pHdr;
pPayload = WMA_GET_RX_MPDU_DATA(pFrame);
nPayload = WMA_GET_RX_PAYLOAD_LEN(pFrame);
pHdr = WMA_GET_RX_MAC_HEADER(pFrame);
/* Zero-init our [out] parameter, */
qdf_mem_zero((uint8_t *) pBeaconStruct, sizeof(tSirProbeRespBeacon));
pBeacon = qdf_mem_malloc(sizeof(tDot11fBeacon));
if (!pBeacon)
return QDF_STATUS_E_NOMEM;
/* get the MAC address out of the BD, */
qdf_mem_copy(pBeaconStruct->bssid, pHdr->sa, 6);
/* delegate to the framesc-generated code, */
status = dot11f_unpack_beacon(mac, pPayload, nPayload, pBeacon, false);
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse Beacon IEs (0x%08x, %d bytes):",
status, nPayload);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
pPayload, nPayload);
qdf_mem_free(pBeacon);
return QDF_STATUS_E_FAILURE;
}
/* & "transliterate" from a 'tDot11fBeacon' to a 'tSirProbeRespBeacon'... */
/* Timestamp */
qdf_mem_copy((uint8_t *) pBeaconStruct->timeStamp,
(uint8_t *) &pBeacon->TimeStamp,
sizeof(tSirMacTimeStamp));
/* Beacon Interval */
pBeaconStruct->beaconInterval = pBeacon->BeaconInterval.interval;
/* Capabilities */
pBeaconStruct->capabilityInfo.ess = pBeacon->Capabilities.ess;
pBeaconStruct->capabilityInfo.ibss = pBeacon->Capabilities.ibss;
pBeaconStruct->capabilityInfo.cfPollable =
pBeacon->Capabilities.cfPollable;
pBeaconStruct->capabilityInfo.cfPollReq =
pBeacon->Capabilities.cfPollReq;
pBeaconStruct->capabilityInfo.privacy = pBeacon->Capabilities.privacy;
pBeaconStruct->capabilityInfo.shortPreamble =
pBeacon->Capabilities.shortPreamble;
pBeaconStruct->capabilityInfo.pbcc = pBeacon->Capabilities.pbcc;
pBeaconStruct->capabilityInfo.channelAgility =
pBeacon->Capabilities.channelAgility;
pBeaconStruct->capabilityInfo.spectrumMgt =
pBeacon->Capabilities.spectrumMgt;
pBeaconStruct->capabilityInfo.qos = pBeacon->Capabilities.qos;
pBeaconStruct->capabilityInfo.shortSlotTime =
pBeacon->Capabilities.shortSlotTime;
pBeaconStruct->capabilityInfo.apsd = pBeacon->Capabilities.apsd;
pBeaconStruct->capabilityInfo.rrm = pBeacon->Capabilities.rrm;
pBeaconStruct->capabilityInfo.dsssOfdm = pBeacon->Capabilities.dsssOfdm;
pBeaconStruct->capabilityInfo.delayedBA =
pBeacon->Capabilities.delayedBA;
pBeaconStruct->capabilityInfo.immediateBA =
pBeacon->Capabilities.immediateBA;
if (!pBeacon->SSID.present) {
pe_debug("Mandatory IE SSID not present!");
} else {
pBeaconStruct->ssidPresent = 1;
convert_ssid(mac, &pBeaconStruct->ssId, &pBeacon->SSID);
}
if (!pBeacon->SuppRates.present) {
pe_debug_rl("Mandatory IE Supported Rates not present!");
} else {
pBeaconStruct->suppRatesPresent = 1;
convert_supp_rates(mac, &pBeaconStruct->supportedRates,
&pBeacon->SuppRates);
}
if (pBeacon->ExtSuppRates.present) {
pBeaconStruct->extendedRatesPresent = 1;
convert_ext_supp_rates(mac, &pBeaconStruct->extendedRates,
&pBeacon->ExtSuppRates);
}
if (pBeacon->CFParams.present) {
pBeaconStruct->cfPresent = 1;
convert_cf_params(mac, &pBeaconStruct->cfParamSet,
&pBeacon->CFParams);
}
if (pBeacon->TIM.present) {
pBeaconStruct->timPresent = 1;
convert_tim(mac, &pBeaconStruct->tim, &pBeacon->TIM);
}
if (pBeacon->Country.present) {
pBeaconStruct->countryInfoPresent = 1;
convert_country(mac, &pBeaconStruct->countryInfoParam,
&pBeacon->Country);
}
/* QOS Capabilities: */
if (pBeacon->QOSCapsAp.present) {
pBeaconStruct->qosCapabilityPresent = 1;
convert_qos_caps(mac, &pBeaconStruct->qosCapability,
&pBeacon->QOSCapsAp);
}
if (pBeacon->EDCAParamSet.present) {
pBeaconStruct->edcaPresent = 1;
convert_edca_param(mac, &pBeaconStruct->edcaParams,
&pBeacon->EDCAParamSet);
}
if (pBeacon->ChanSwitchAnn.present) {
pBeaconStruct->channelSwitchPresent = 1;
qdf_mem_copy(&pBeaconStruct->channelSwitchIE,
&pBeacon->ChanSwitchAnn,
sizeof(pBeaconStruct->channelSwitchIE));
}
if (pBeacon->ext_chan_switch_ann.present) {
pBeaconStruct->ext_chan_switch_present = 1;
qdf_mem_copy(&pBeaconStruct->ext_chan_switch,
&pBeacon->ext_chan_switch_ann,
sizeof(tDot11fIEext_chan_switch_ann));
}
if (pBeacon->sec_chan_offset_ele.present) {
pBeaconStruct->sec_chan_offset_present = 1;
qdf_mem_copy(&pBeaconStruct->sec_chan_offset,
&pBeacon->sec_chan_offset_ele,
sizeof(pBeaconStruct->sec_chan_offset));
}
if (pBeacon->TPCReport.present) {
pBeaconStruct->tpcReportPresent = 1;
qdf_mem_copy(&pBeaconStruct->tpcReport, &pBeacon->TPCReport,
sizeof(tDot11fIETPCReport));
}
if (pBeacon->PowerConstraints.present) {
pBeaconStruct->powerConstraintPresent = 1;
qdf_mem_copy(&pBeaconStruct->localPowerConstraint,
&pBeacon->PowerConstraints,
sizeof(tDot11fIEPowerConstraints));
}
if (pBeacon->Quiet.present) {
pBeaconStruct->quietIEPresent = 1;
qdf_mem_copy(&pBeaconStruct->quietIE, &pBeacon->Quiet,
sizeof(tDot11fIEQuiet));
}
if (pBeacon->HTCaps.present) {
qdf_mem_copy(&pBeaconStruct->HTCaps, &pBeacon->HTCaps,
sizeof(tDot11fIEHTCaps));
}
if (pBeacon->HTInfo.present) {
qdf_mem_copy(&pBeaconStruct->HTInfo, &pBeacon->HTInfo,
sizeof(tDot11fIEHTInfo));
}
if (pBeacon->he_op.oper_info_6g_present) {
pBeaconStruct->chan_freq = wlan_reg_chan_band_to_freq(mac->pdev,
pBeacon->he_op.oper_info_6g.info.primary_ch,
BIT(REG_BAND_6G));
} else if (pBeacon->DSParams.present) {
pBeaconStruct->dsParamsPresent = 1;
pBeaconStruct->chan_freq =
wlan_reg_legacy_chan_to_freq(mac->pdev,
pBeacon->DSParams.curr_channel);
} else if (pBeacon->HTInfo.present) {
pBeaconStruct->chan_freq =
wlan_reg_legacy_chan_to_freq(mac->pdev,
pBeacon->HTInfo.primaryChannel);
} else {
pBeaconStruct->chan_freq = WMA_GET_RX_FREQ(pFrame);
pe_debug_rl("In Beacon No Channel info");
}
if (pBeacon->RSN.present) {
pBeaconStruct->rsnPresent = 1;
convert_rsn(mac, &pBeaconStruct->rsn, &pBeacon->RSN);
}
if (pBeacon->WPA.present) {
pBeaconStruct->wpaPresent = 1;
convert_wpa(mac, &pBeaconStruct->wpa, &pBeacon->WPA);
}
if (pBeacon->WMMParams.present) {
pBeaconStruct->wmeEdcaPresent = 1;
convert_wmm_params(mac, &pBeaconStruct->edcaParams,
&pBeacon->WMMParams);
}
if (pBeacon->WMMInfoAp.present) {
pBeaconStruct->wmeInfoPresent = 1;
pe_debug("WMM Info present in Beacon Frame!");
}
if (pBeacon->WMMCaps.present) {
pBeaconStruct->wsmCapablePresent = 1;
}
if (pBeacon->ERPInfo.present) {
pBeaconStruct->erpPresent = 1;
convert_erp_info(mac, &pBeaconStruct->erpIEInfo,
&pBeacon->ERPInfo);
}
if (pBeacon->MobilityDomain.present) {
/* MobilityDomain */
pBeaconStruct->mdiePresent = 1;
qdf_mem_copy((uint8_t *) &(pBeaconStruct->mdie[0]),
(uint8_t *) &(pBeacon->MobilityDomain.MDID),
sizeof(uint16_t));
pBeaconStruct->mdie[2] =
((pBeacon->MobilityDomain.overDSCap << 0) | (pBeacon->
MobilityDomain.
resourceReqCap
<< 1));
}
#ifdef FEATURE_WLAN_ESE
if (pBeacon->ESEVersion.present)
pBeaconStruct->is_ese_ver_ie_present = 1;
if (pBeacon->ESETxmitPower.present) {
/* copy ESE TPC info element */
pBeaconStruct->eseTxPwr.present = 1;
qdf_mem_copy(&pBeaconStruct->eseTxPwr,
&pBeacon->ESETxmitPower,
sizeof(tDot11fIEESETxmitPower));
}
if (pBeacon->QBSSLoad.present) {
qdf_mem_copy(&pBeaconStruct->QBSSLoad,
&pBeacon->QBSSLoad, sizeof(tDot11fIEQBSSLoad));
}
#endif
if (pBeacon->VHTCaps.present) {
qdf_mem_copy(&pBeaconStruct->VHTCaps, &pBeacon->VHTCaps,
sizeof(tDot11fIEVHTCaps));
}
if (pBeacon->VHTOperation.present) {
qdf_mem_copy(&pBeaconStruct->VHTOperation,
&pBeacon->VHTOperation,
sizeof(tDot11fIEVHTOperation));
}
if (pBeacon->VHTExtBssLoad.present) {
qdf_mem_copy(&pBeaconStruct->VHTExtBssLoad,
&pBeacon->VHTExtBssLoad,
sizeof(tDot11fIEVHTExtBssLoad));
}
if (pBeacon->OperatingMode.present) {
qdf_mem_copy(&pBeaconStruct->OperatingMode,
&pBeacon->OperatingMode,
sizeof(tDot11fIEOperatingMode));
}
if (pBeacon->WiderBWChanSwitchAnn.present) {
pBeaconStruct->WiderBWChanSwitchAnnPresent = 1;
qdf_mem_copy(&pBeaconStruct->WiderBWChanSwitchAnn,
&pBeacon->WiderBWChanSwitchAnn,
sizeof(tDot11fIEWiderBWChanSwitchAnn));
}
/* IBSS Peer Params */
if (pBeacon->IBSSParams.present) {
pBeaconStruct->IBSSParams.present = 1;
qdf_mem_copy(&pBeaconStruct->IBSSParams, &pBeacon->IBSSParams,
sizeof(tDot11fIEIBSSParams));
}
pBeaconStruct->Vendor1IEPresent = pBeacon->Vendor1IE.present;
pBeaconStruct->Vendor3IEPresent = pBeacon->Vendor3IE.present;
pBeaconStruct->vendor_vht_ie.present = pBeacon->vendor_vht_ie.present;
if (pBeacon->vendor_vht_ie.present) {
pBeaconStruct->vendor_vht_ie.sub_type =
pBeacon->vendor_vht_ie.sub_type;
}
if (pBeacon->vendor_vht_ie.VHTCaps.present) {
qdf_mem_copy(&pBeaconStruct->vendor_vht_ie.VHTCaps,
&pBeacon->vendor_vht_ie.VHTCaps,
sizeof(tDot11fIEVHTCaps));
}
if (pBeacon->vendor_vht_ie.VHTOperation.present) {
qdf_mem_copy(&pBeaconStruct->vendor_vht_ie.VHTOperation,
&pBeacon->VHTOperation,
sizeof(tDot11fIEVHTOperation));
}
/* Update HS 2.0 Information Element */
if (pBeacon->hs20vendor_ie.present) {
qdf_mem_copy(&pBeaconStruct->hs20vendor_ie,
&pBeacon->hs20vendor_ie,
sizeof(tDot11fIEhs20vendor_ie) -
sizeof(pBeacon->hs20vendor_ie.hs_id));
if (pBeacon->hs20vendor_ie.hs_id_present)
qdf_mem_copy(&pBeaconStruct->hs20vendor_ie.hs_id,
&pBeacon->hs20vendor_ie.hs_id,
sizeof(pBeacon->hs20vendor_ie.hs_id));
}
#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
if (pBeacon->QComVendorIE.present) {
pBeaconStruct->AvoidChannelIE.present =
pBeacon->QComVendorIE.present;
pBeaconStruct->AvoidChannelIE.type =
pBeacon->QComVendorIE.type;
pBeaconStruct->AvoidChannelIE.channel =
pBeacon->QComVendorIE.channel;
}
#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
if (pBeacon->OBSSScanParameters.present) {
qdf_mem_copy(&pBeaconStruct->obss_scanparams,
&pBeacon->OBSSScanParameters,
sizeof(struct sDot11fIEOBSSScanParameters));
}
if (pBeacon->MBO_IE.present) {
pBeaconStruct->MBO_IE_present = true;
if (pBeacon->MBO_IE.cellular_data_cap.present)
pBeaconStruct->MBO_capability =
pBeacon->MBO_IE.cellular_data_cap.cellular_connectivity;
if (pBeacon->MBO_IE.assoc_disallowed.present) {
pBeaconStruct->assoc_disallowed = true;
pBeaconStruct->assoc_disallowed_reason =
pBeacon->MBO_IE.assoc_disallowed.reason_code;
}
}
if (pBeacon->qcn_ie.present)
qdf_mem_copy(&pBeaconStruct->qcn_ie, &pBeacon->qcn_ie,
sizeof(tDot11fIEqcn_ie));
if (pBeacon->he_cap.present) {
pe_debug("11AX: HE cap IE present");
qdf_mem_copy(&pBeaconStruct->he_cap,
&pBeacon->he_cap,
sizeof(tDot11fIEhe_cap));
}
if (pBeacon->he_op.present) {
pe_debug("11AX: HE operation IE present");
qdf_mem_copy(&pBeaconStruct->he_op,
&pBeacon->he_op,
sizeof(tDot11fIEhe_op));
}
convert_bcon_bss_color_change_ie(pBeacon, pBeaconStruct);
qdf_mem_free(pBeacon);
return QDF_STATUS_SUCCESS;
} /* End sir_convert_beacon_frame2_struct. */
#ifdef WLAN_FEATURE_FILS_SK
/* update_ftie_in_fils_conf() - API to update fils info from auth
* response packet from AP
* @auth: auth packet pointer received from AP
* @auth_frame: data structure needs to be updated
*
* Return: None
*/
static void
update_ftie_in_fils_conf(tDot11fAuthentication *auth,
tpSirMacAuthFrameBody auth_frame)
{
/**
* Copy the FTIE sent by the AP in the auth request frame.
* This is required for FT-FILS connection.
* This FTIE will be sent in Assoc request frame without
* any modification.
*/
if (auth->FTInfo.present) {
pe_debug("FT-FILS: r0kh_len:%d r1kh_present:%d",
auth->FTInfo.R0KH_ID.num_PMK_R0_ID,
auth->FTInfo.R1KH_ID.present);
auth_frame->ft_ie.present = 1;
if (auth->FTInfo.R1KH_ID.present) {
qdf_mem_copy(auth_frame->ft_ie.r1kh_id,
auth->FTInfo.R1KH_ID.PMK_R1_ID,
FT_R1KH_ID_LEN);
}
if (auth->FTInfo.R0KH_ID.present) {
qdf_mem_copy(auth_frame->ft_ie.r0kh_id,
auth->FTInfo.R0KH_ID.PMK_R0_ID,
auth->FTInfo.R0KH_ID.num_PMK_R0_ID);
auth_frame->ft_ie.r0kh_id_len =
auth->FTInfo.R0KH_ID.num_PMK_R0_ID;
}
if (auth_frame->ft_ie.gtk_ie.present) {
pe_debug("FT-FILS: GTK present");
qdf_mem_copy(&auth_frame->ft_ie.gtk_ie,
&auth->FTInfo.GTK,
sizeof(struct mac_ft_gtk_ie));
}
if (auth_frame->ft_ie.igtk_ie.present) {
pe_debug("FT-FILS: IGTK present");
qdf_mem_copy(&auth_frame->ft_ie.igtk_ie,
&auth->FTInfo.IGTK,
sizeof(struct mac_ft_igtk_ie));
}
qdf_mem_copy(auth_frame->ft_ie.anonce, auth->FTInfo.Anonce,
FT_NONCE_LEN);
qdf_mem_copy(auth_frame->ft_ie.snonce, auth->FTInfo.Snonce,
FT_NONCE_LEN);
qdf_mem_copy(auth_frame->ft_ie.mic, auth->FTInfo.MIC,
FT_MIC_LEN);
auth_frame->ft_ie.element_count = auth->FTInfo.IECount;
}
}
/* sir_update_auth_frame2_struct_fils_conf: API to update fils info from auth
* packet type 2
* @auth: auth packet pointer received from AP
* @auth_frame: data structure needs to be updated
*
* Return: None
*/
static void
sir_update_auth_frame2_struct_fils_conf(tDot11fAuthentication *auth,
tpSirMacAuthFrameBody auth_frame)
{
if (auth->AuthAlgo.algo != SIR_FILS_SK_WITHOUT_PFS)
return;
if (auth->fils_assoc_delay_info.present)
auth_frame->assoc_delay_info =
auth->fils_assoc_delay_info.assoc_delay_info;
if (auth->fils_session.present)
qdf_mem_copy(auth_frame->session, auth->fils_session.session,
SIR_FILS_SESSION_LENGTH);
if (auth->fils_nonce.present)
qdf_mem_copy(auth_frame->nonce, auth->fils_nonce.nonce,
SIR_FILS_NONCE_LENGTH);
if (auth->fils_wrapped_data.present) {
qdf_mem_copy(auth_frame->wrapped_data,
auth->fils_wrapped_data.wrapped_data,
auth->fils_wrapped_data.num_wrapped_data);
auth_frame->wrapped_data_len =
auth->fils_wrapped_data.num_wrapped_data;
}
if (auth->RSNOpaque.present) {
qdf_mem_copy(auth_frame->rsn_ie.info, auth->RSNOpaque.data,
auth->RSNOpaque.num_data);
auth_frame->rsn_ie.length = auth->RSNOpaque.num_data;
}
update_ftie_in_fils_conf(auth, auth_frame);
}
#else
static void sir_update_auth_frame2_struct_fils_conf(tDot11fAuthentication *auth,
tpSirMacAuthFrameBody auth_frame)
{ }
#endif
QDF_STATUS
sir_convert_auth_frame2_struct(struct mac_context *mac,
uint8_t *pFrame,
uint32_t nFrame, tpSirMacAuthFrameBody pAuth)
{
static tDot11fAuthentication auth;
uint32_t status;
/* Zero-init our [out] parameter, */
qdf_mem_zero((uint8_t *) pAuth, sizeof(tSirMacAuthFrameBody));
/* delegate to the framesc-generated code, */
status = dot11f_unpack_authentication(mac, pFrame, nFrame,
&auth, false);
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse an Authentication frame (0x%08x, %d bytes):",
status, nFrame);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
pFrame, nFrame);
return QDF_STATUS_E_FAILURE;
} else if (DOT11F_WARNED(status)) {
pe_debug("There were warnings while unpacking an Authentication frame (0x%08x, %d bytes):",
status, nFrame);
}
/* & "transliterate" from a 'tDot11fAuthentication' to a 'tSirMacAuthFrameBody'... */
pAuth->authAlgoNumber = auth.AuthAlgo.algo;
pAuth->authTransactionSeqNumber = auth.AuthSeqNo.no;
pAuth->authStatusCode = auth.Status.status;
if (auth.ChallengeText.present) {
pAuth->type = WLAN_ELEMID_CHALLENGE;
pAuth->length = auth.ChallengeText.num_text;
qdf_mem_copy(pAuth->challengeText, auth.ChallengeText.text,
auth.ChallengeText.num_text);
}
sir_update_auth_frame2_struct_fils_conf(&auth, pAuth);
return QDF_STATUS_SUCCESS;
} /* End sir_convert_auth_frame2_struct. */
QDF_STATUS
sir_convert_addts_rsp2_struct(struct mac_context *mac,
uint8_t *pFrame,
uint32_t nFrame, tSirAddtsRspInfo *pAddTs)
{
tDot11fAddTSResponse addts = { {0} };
tDot11fWMMAddTSResponse wmmaddts = { {0} };
uint8_t j;
uint16_t i;
uint32_t status;
if (QOS_ADD_TS_RSP != *(pFrame + 1)) {
pe_err("Action of %d; this is not supported & is probably an error",
*(pFrame + 1));
return QDF_STATUS_E_FAILURE;
}
/* Zero-init our [out] parameter, */
qdf_mem_zero((uint8_t *) pAddTs, sizeof(tSirAddtsRspInfo));
qdf_mem_zero((uint8_t *) &addts, sizeof(tDot11fAddTSResponse));
qdf_mem_zero((uint8_t *) &wmmaddts, sizeof(tDot11fWMMAddTSResponse));
/* delegate to the framesc-generated code, */
switch (*pFrame) {
case ACTION_CATEGORY_QOS:
status =
dot11f_unpack_add_ts_response(mac, pFrame, nFrame,
&addts, false);
break;
case ACTION_CATEGORY_WMM:
status =
dot11f_unpack_wmm_add_ts_response(mac, pFrame, nFrame,
&wmmaddts, false);
break;
default:
pe_err("Category of %d; this is not supported & is probably an error",
*pFrame);
return QDF_STATUS_E_FAILURE;
}
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse an Add TS Response frame (0x%08x, %d bytes):",
status, nFrame);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
pFrame, nFrame);
return QDF_STATUS_E_FAILURE;
} else if (DOT11F_WARNED(status)) {
pe_debug("There were warnings while unpacking an Add TS Response frame (0x%08x,%d bytes):",
status, nFrame);
}
/* & "transliterate" from a 'tDot11fAddTSResponse' or a */
/* 'tDot11WMMAddTSResponse' to a 'tSirMacAddtsRspInfo'... */
if (ACTION_CATEGORY_QOS == *pFrame) {
pAddTs->dialogToken = addts.DialogToken.token;
pAddTs->status = (enum mac_status_code)addts.Status.status;
if (addts.TSDelay.present) {
convert_ts_delay(mac, &pAddTs->delay, &addts.TSDelay);
}
/* TS Delay is present iff status indicates its presence */
if (eSIR_MAC_TS_NOT_CREATED_STATUS == pAddTs->status
&& !addts.TSDelay.present) {
pe_warn("Missing TSDelay IE");
}
if (addts.TSPEC.present) {
convert_tspec(mac, &pAddTs->tspec, &addts.TSPEC);
} else {
pe_err("Mandatory TSPEC element missing in Add TS Response");
return QDF_STATUS_E_FAILURE;
}
if (addts.num_TCLAS) {
pAddTs->numTclas = (uint8_t) addts.num_TCLAS;
for (i = 0U; i < addts.num_TCLAS; ++i) {
if (QDF_STATUS_SUCCESS !=
convert_tclas(mac, &(pAddTs->tclasInfo[i]),
&(addts.TCLAS[i]))) {
pe_err("Failed to convert a TCLAS IE");
return QDF_STATUS_E_FAILURE;
}
}
}
if (addts.TCLASSPROC.present) {
pAddTs->tclasProcPresent = 1;
pAddTs->tclasProc = addts.TCLASSPROC.processing;
}
#ifdef FEATURE_WLAN_ESE
if (addts.ESETrafStrmMet.present) {
pAddTs->tsmPresent = 1;
qdf_mem_copy(&pAddTs->tsmIE.tsid,
&addts.ESETrafStrmMet.tsid,
sizeof(struct ese_tsm_ie));
}
#endif
if (addts.Schedule.present) {
pAddTs->schedulePresent = 1;
convert_schedule(mac, &pAddTs->schedule,
&addts.Schedule);
}
if (addts.WMMSchedule.present) {
pAddTs->schedulePresent = 1;
convert_wmm_schedule(mac, &pAddTs->schedule,
&addts.WMMSchedule);
}
if (addts.WMMTSPEC.present) {
pAddTs->wsmTspecPresent = 1;
convert_wmmtspec(mac, &pAddTs->tspec, &addts.WMMTSPEC);
}
if (addts.num_WMMTCLAS) {
j = (uint8_t) (pAddTs->numTclas + addts.num_WMMTCLAS);
if (SIR_MAC_TCLASIE_MAXNUM < j)
j = SIR_MAC_TCLASIE_MAXNUM;
for (i = pAddTs->numTclas; i < j; ++i) {
if (QDF_STATUS_SUCCESS !=
convert_wmmtclas(mac,
&(pAddTs->tclasInfo[i]),
&(addts.WMMTCLAS[i]))) {
pe_err("Failed to convert a TCLAS IE");
return QDF_STATUS_E_FAILURE;
}
}
}
if (addts.WMMTCLASPROC.present) {
pAddTs->tclasProcPresent = 1;
pAddTs->tclasProc = addts.WMMTCLASPROC.processing;
}
if (1 < pAddTs->numTclas && (!pAddTs->tclasProcPresent)) {
pe_err("%d TCLAS IE but not TCLASPROC IE",
pAddTs->numTclas);
return QDF_STATUS_E_FAILURE;
}
} else {
pAddTs->dialogToken = wmmaddts.DialogToken.token;
pAddTs->status =
(enum mac_status_code)wmmaddts.StatusCode.statusCode;
if (wmmaddts.WMMTSPEC.present) {
pAddTs->wmeTspecPresent = 1;
convert_wmmtspec(mac, &pAddTs->tspec,
&wmmaddts.WMMTSPEC);
} else {
pe_err("Mandatory WME TSPEC element missing!");
return QDF_STATUS_E_FAILURE;
}
#ifdef FEATURE_WLAN_ESE
if (wmmaddts.ESETrafStrmMet.present) {
pAddTs->tsmPresent = 1;
qdf_mem_copy(&pAddTs->tsmIE.tsid,
&wmmaddts.ESETrafStrmMet.tsid,
sizeof(struct ese_tsm_ie));
}
#endif
}
return QDF_STATUS_SUCCESS;
} /* End sir_convert_addts_rsp2_struct. */
QDF_STATUS
sir_convert_delts_req2_struct(struct mac_context *mac,
uint8_t *pFrame,
uint32_t nFrame, struct delts_req_info *pDelTs)
{
tDot11fDelTS delts = { {0} };
tDot11fWMMDelTS wmmdelts = { {0} };
uint32_t status;
if (QOS_DEL_TS_REQ != *(pFrame + 1)) {
pe_err("sirConvertDeltsRsp2Struct invoked "
"with an Action of %d; this is not "
"supported & is probably an error",
*(pFrame + 1));
return QDF_STATUS_E_FAILURE;
}
/* Zero-init our [out] parameter, */
qdf_mem_zero(pDelTs, sizeof(*pDelTs));
/* delegate to the framesc-generated code, */
switch (*pFrame) {
case ACTION_CATEGORY_QOS:
status = dot11f_unpack_del_ts(mac, pFrame, nFrame,
&delts, false);
break;
case ACTION_CATEGORY_WMM:
status = dot11f_unpack_wmm_del_ts(mac, pFrame, nFrame,
&wmmdelts, false);
break;
default:
pe_err("sirConvertDeltsRsp2Struct invoked "
"with a Category of %d; this is not"
" supported & is probably an error",
*pFrame);
return QDF_STATUS_E_FAILURE;
}
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse an Del TS Request frame (0x%08x, %d bytes):",
status, nFrame);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
pFrame, nFrame);
return QDF_STATUS_E_FAILURE;
} else if (DOT11F_WARNED(status)) {
pe_debug("There were warnings while unpacking an Del TS Request frame (0x%08x,%d bytes):",
status, nFrame);
}
/* & "transliterate" from a 'tDot11fDelTSResponse' or a */
/* 'tDot11WMMDelTSResponse' to a 'tSirMacDeltsReqInfo'... */
if (ACTION_CATEGORY_QOS == *pFrame) {
pDelTs->tsinfo.traffic.trafficType =
(uint16_t) delts.TSInfo.traffic_type;
pDelTs->tsinfo.traffic.tsid = (uint16_t) delts.TSInfo.tsid;
pDelTs->tsinfo.traffic.direction =
(uint16_t) delts.TSInfo.direction;
pDelTs->tsinfo.traffic.accessPolicy =
(uint16_t) delts.TSInfo.access_policy;
pDelTs->tsinfo.traffic.aggregation =
(uint16_t) delts.TSInfo.aggregation;
pDelTs->tsinfo.traffic.psb = (uint16_t) delts.TSInfo.psb;
pDelTs->tsinfo.traffic.userPrio =
(uint16_t) delts.TSInfo.user_priority;
pDelTs->tsinfo.traffic.ackPolicy =
(uint16_t) delts.TSInfo.tsinfo_ack_pol;
pDelTs->tsinfo.schedule.schedule =
(uint8_t) delts.TSInfo.schedule;
} else {
if (wmmdelts.WMMTSPEC.present) {
pDelTs->wmeTspecPresent = 1;
convert_wmmtspec(mac, &pDelTs->tspec,
&wmmdelts.WMMTSPEC);
} else {
pe_err("Mandatory WME TSPEC element missing!");
return QDF_STATUS_E_FAILURE;
}
}
return QDF_STATUS_SUCCESS;
} /* End sir_convert_delts_req2_struct. */
QDF_STATUS
sir_convert_qos_map_configure_frame2_struct(struct mac_context *mac,
uint8_t *pFrame,
uint32_t nFrame,
struct qos_map_set *pQosMapSet)
{
tDot11fQosMapConfigure mapConfigure;
uint32_t status;
status =
dot11f_unpack_qos_map_configure(mac, pFrame, nFrame,
&mapConfigure, false);
if (DOT11F_FAILED(status) || !mapConfigure.QosMapSet.present) {
pe_err("Failed to parse Qos Map Configure frame (0x%08x, %d bytes):",
status, nFrame);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
pFrame, nFrame);
return QDF_STATUS_E_FAILURE;
} else if (DOT11F_WARNED(status)) {
pe_debug("There were warnings while unpacking Qos Map Configure frame (0x%08x, %d bytes):",
status, nFrame);
}
pQosMapSet->present = mapConfigure.QosMapSet.present;
convert_qos_mapset_frame(mac, pQosMapSet, &mapConfigure.QosMapSet);
lim_log_qos_map_set(mac, pQosMapSet);
return QDF_STATUS_SUCCESS;
}
#ifdef ANI_SUPPORT_11H
QDF_STATUS
sir_convert_tpc_req_frame2_struct(struct mac_context *mac,
uint8_t *pFrame,
tpSirMacTpcReqActionFrame pTpcReqFrame,
uint32_t nFrame)
{
tDot11fTPCRequest req;
uint32_t status;
qdf_mem_zero((uint8_t *) pTpcReqFrame,
sizeof(tSirMacTpcReqActionFrame));
status = dot11f_unpack_tpc_request(mac, pFrame, nFrame, &req, false);
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse a TPC Request frame (0x%08x, %d bytes):",
status, nFrame);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
pFrame, nFrame);
return QDF_STATUS_E_FAILURE;
} else if (DOT11F_WARNED(status)) {
pe_debug("There were warnings while unpacking a TPC Request frame (0x%08x, %d bytes):",
status, nFrame);
}
/* & "transliterate" from a 'tDot11fTPCRequest' to a */
/* 'tSirMacTpcReqActionFrame'... */
pTpcReqFrame->actionHeader.category = req.Category.category;
pTpcReqFrame->actionHeader.actionID = req.Action.action;
pTpcReqFrame->actionHeader.dialogToken = req.DialogToken.token;
if (req.TPCRequest.present) {
pTpcReqFrame->type = DOT11F_EID_TPCREQUEST;
pTpcReqFrame->length = 0;
} else {
pe_warn("!!!Rcv TPC Req of inalid type!");
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
} /* End sir_convert_tpc_req_frame2_struct. */
QDF_STATUS
sir_convert_meas_req_frame2_struct(struct mac_context *mac,
uint8_t *pFrame,
tpSirMacMeasReqActionFrame pMeasReqFrame,
uint32_t nFrame)
{
tDot11fMeasurementRequest mr;
uint32_t status;
/* Zero-init our [out] parameter, */
qdf_mem_zero((uint8_t *) pMeasReqFrame,
sizeof(tpSirMacMeasReqActionFrame));
/* delegate to the framesc-generated code, */
status = dot11f_unpack_measurement_request(mac, pFrame,
nFrame, &mr, false);
if (DOT11F_FAILED(status)) {
pe_err("Failed to parse a Measurement Request frame (0x%08x, %d bytes):",
status, nFrame);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR,
pFrame, nFrame);
return QDF_STATUS_E_FAILURE;
} else if (DOT11F_WARNED(status)) {
pe_debug("There were warnings while unpacking a Measurement Request frame (0x%08x, %d bytes):",
status, nFrame);
}
/* & "transliterate" from a 'tDot11fMeasurementRequest' to a */
/* 'tpSirMacMeasReqActionFrame'... */
pMeasReqFrame->actionHeader.category = mr.Category.category;
pMeasReqFrame->actionHeader.actionID = mr.Action.action;
pMeasReqFrame->actionHeader.dialogToken = mr.DialogToken.token;
if (0 == mr.num_MeasurementRequest) {
pe_err("Missing mandatory IE in Measurement Request Frame");
return QDF_STATUS_E_FAILURE;
} else if (1 < mr.num_MeasurementRequest) {
pe_warn(
FL("Warning: dropping extra Measurement Request IEs!"));
}
pMeasReqFrame->measReqIE.type = DOT11F_EID_MEASUREMENTREQUEST;
pMeasReqFrame->measReqIE.length = DOT11F_IE_MEASUREMENTREQUEST_MIN_LEN;
pMeasReqFrame->measReqIE.measToken =
mr.MeasurementRequest[0].measurement_token;
pMeasReqFrame->measReqIE.measReqMode =
(mr.MeasurementRequest[0].reserved << 3) | (mr.
MeasurementRequest[0].
enable << 2) | (mr.
MeasurementRequest
[0].
request
<< 1) |
(mr.MeasurementRequest[0].report /*<< 0 */);
pMeasReqFrame->measReqIE.measType =
mr.MeasurementRequest[0].measurement_type;
pMeasReqFrame->measReqIE.measReqField.channelNumber =
mr.MeasurementRequest[0].channel_no;
qdf_mem_copy(pMeasReqFrame->measReqIE.measReqField.measStartTime,
mr.MeasurementRequest[0].meas_start_time, 8);
pMeasReqFrame->measReqIE.measReqField.measDuration =
mr.MeasurementRequest[0].meas_duration;
return QDF_STATUS_SUCCESS;
} /* End sir_convert_meas_req_frame2_struct. */
#endif
void populate_dot11f_tspec(struct mac_tspec_ie *pOld, tDot11fIETSPEC *pDot11f)
{
pDot11f->traffic_type = pOld->tsinfo.traffic.trafficType;
pDot11f->tsid = pOld->tsinfo.traffic.tsid;
pDot11f->direction = pOld->tsinfo.traffic.direction;
pDot11f->access_policy = pOld->tsinfo.traffic.accessPolicy;
pDot11f->aggregation = pOld->tsinfo.traffic.aggregation;
pDot11f->psb = pOld->tsinfo.traffic.psb;
pDot11f->user_priority = pOld->tsinfo.traffic.userPrio;
pDot11f->tsinfo_ack_pol = pOld->tsinfo.traffic.ackPolicy;
pDot11f->schedule = pOld->tsinfo.schedule.schedule;
/* As defined in IEEE 802.11-2007, section 7.3.2.30
* Nominal MSDU size: Bit[0:14]=Size, Bit[15]=Fixed
*/
pDot11f->size = (pOld->nomMsduSz & 0x7fff);
pDot11f->fixed = (pOld->nomMsduSz & 0x8000) ? 1 : 0;
pDot11f->max_msdu_size = pOld->maxMsduSz;
pDot11f->min_service_int = pOld->minSvcInterval;
pDot11f->max_service_int = pOld->maxSvcInterval;
pDot11f->inactivity_int = pOld->inactInterval;
pDot11f->suspension_int = pOld->suspendInterval;
pDot11f->service_start_time = pOld->svcStartTime;
pDot11f->min_data_rate = pOld->minDataRate;
pDot11f->mean_data_rate = pOld->meanDataRate;
pDot11f->peak_data_rate = pOld->peakDataRate;
pDot11f->burst_size = pOld->maxBurstSz;
pDot11f->delay_bound = pOld->delayBound;
pDot11f->min_phy_rate = pOld->minPhyRate;
pDot11f->surplus_bw_allowance = pOld->surplusBw;
pDot11f->medium_time = pOld->mediumTime;
pDot11f->present = 1;
} /* End populate_dot11f_tspec. */
void populate_dot11f_wmmtspec(struct mac_tspec_ie *pOld,
tDot11fIEWMMTSPEC *pDot11f)
{
pDot11f->traffic_type = pOld->tsinfo.traffic.trafficType;
pDot11f->tsid = pOld->tsinfo.traffic.tsid;
pDot11f->direction = pOld->tsinfo.traffic.direction;
pDot11f->access_policy = pOld->tsinfo.traffic.accessPolicy;
pDot11f->aggregation = pOld->tsinfo.traffic.aggregation;
pDot11f->psb = pOld->tsinfo.traffic.psb;
pDot11f->user_priority = pOld->tsinfo.traffic.userPrio;
pDot11f->tsinfo_ack_pol = pOld->tsinfo.traffic.ackPolicy;
pDot11f->burst_size_defn = pOld->tsinfo.traffic.burstSizeDefn;
/* As defined in IEEE 802.11-2007, section 7.3.2.30
* Nominal MSDU size: Bit[0:14]=Size, Bit[15]=Fixed
*/
pDot11f->size = (pOld->nomMsduSz & 0x7fff);
pDot11f->fixed = (pOld->nomMsduSz & 0x8000) ? 1 : 0;
pDot11f->max_msdu_size = pOld->maxMsduSz;
pDot11f->min_service_int = pOld->minSvcInterval;
pDot11f->max_service_int = pOld->maxSvcInterval;
pDot11f->inactivity_int = pOld->inactInterval;
pDot11f->suspension_int = pOld->suspendInterval;
pDot11f->service_start_time = pOld->svcStartTime;
pDot11f->min_data_rate = pOld->minDataRate;
pDot11f->mean_data_rate = pOld->meanDataRate;
pDot11f->peak_data_rate = pOld->peakDataRate;
pDot11f->burst_size = pOld->maxBurstSz;
pDot11f->delay_bound = pOld->delayBound;
pDot11f->min_phy_rate = pOld->minPhyRate;
pDot11f->surplus_bw_allowance = pOld->surplusBw;
pDot11f->medium_time = pOld->mediumTime;
pDot11f->version = 1;
pDot11f->present = 1;
} /* End populate_dot11f_wmmtspec. */
#if defined(FEATURE_WLAN_ESE)
/* Fill the ESE version currently supported */
void populate_dot11f_ese_version(tDot11fIEESEVersion *pESEVersion)
{
pESEVersion->present = 1;
pESEVersion->version = ESE_VERSION_SUPPORTED;
}
/* Fill the ESE ie for the station. */
/* The State is Normal (1) */
/* The MBSSID for station is set to 0. */
void populate_dot11f_ese_rad_mgmt_cap(tDot11fIEESERadMgmtCap *pESERadMgmtCap)
{
pESERadMgmtCap->present = 1;
pESERadMgmtCap->mgmt_state = RM_STATE_NORMAL;
pESERadMgmtCap->mbssid_mask = 0;
pESERadMgmtCap->reserved = 0;
}
QDF_STATUS populate_dot11f_ese_cckm_opaque(struct mac_context *mac,
tpSirCCKMie pCCKMie,
tDot11fIEESECckmOpaque *pDot11f)
{
int idx;
if (pCCKMie->length) {
idx = find_ie_location(mac, (tpSirRSNie) pCCKMie,
DOT11F_EID_ESECCKMOPAQUE);
if (0 <= idx) {
pDot11f->present = 1;
/* Dont include OUI */
pDot11f->num_data = pCCKMie->cckmIEdata[idx + 1] - 4;
qdf_mem_copy(pDot11f->data, pCCKMie->cckmIEdata + idx + 2 + 4, /* EID,len,OUI */
pCCKMie->cckmIEdata[idx + 1] - 4); /* Skip OUI */
}
}
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_ese_cckm_opaque. */
void populate_dot11_tsrsie(struct mac_context *mac,
struct ese_tsrs_ie *pOld,
tDot11fIEESETrafStrmRateSet *pDot11f,
uint8_t rate_length)
{
pDot11f->tsid = pOld->tsid;
qdf_mem_copy(pDot11f->tsrates, pOld->rates, rate_length);
pDot11f->num_tsrates = rate_length;
pDot11f->present = 1;
}
#endif
QDF_STATUS
populate_dot11f_tclas(struct mac_context *mac,
tSirTclasInfo *pOld, tDot11fIETCLAS *pDot11f)
{
pDot11f->user_priority = pOld->tclas.userPrio;
pDot11f->classifier_type = pOld->tclas.classifierType;
pDot11f->classifier_mask = pOld->tclas.classifierMask;
switch (pDot11f->classifier_type) {
case SIR_MAC_TCLASTYPE_ETHERNET:
qdf_mem_copy((uint8_t *) &pDot11f->info.EthParams.source,
(uint8_t *) &pOld->tclasParams.eth.srcAddr, 6);
qdf_mem_copy((uint8_t *) &pDot11f->info.EthParams.dest,
(uint8_t *) &pOld->tclasParams.eth.dstAddr, 6);
pDot11f->info.EthParams.type = pOld->tclasParams.eth.type;
break;
case SIR_MAC_TCLASTYPE_TCPUDPIP:
pDot11f->info.IpParams.version = pOld->version;
if (SIR_MAC_TCLAS_IPV4 == pDot11f->info.IpParams.version) {
qdf_mem_copy(pDot11f->info.IpParams.params.IpV4Params.
source, pOld->tclasParams.ipv4.srcIpAddr,
4);
qdf_mem_copy(pDot11f->info.IpParams.params.IpV4Params.
dest, pOld->tclasParams.ipv4.dstIpAddr, 4);
pDot11f->info.IpParams.params.IpV4Params.src_port =
pOld->tclasParams.ipv4.srcPort;
pDot11f->info.IpParams.params.IpV4Params.dest_port =
pOld->tclasParams.ipv4.dstPort;
pDot11f->info.IpParams.params.IpV4Params.DSCP =
pOld->tclasParams.ipv4.dscp;
pDot11f->info.IpParams.params.IpV4Params.proto =
pOld->tclasParams.ipv4.protocol;
pDot11f->info.IpParams.params.IpV4Params.reserved =
pOld->tclasParams.ipv4.rsvd;
} else {
qdf_mem_copy((uint8_t *) &pDot11f->info.IpParams.
params.IpV6Params.source,
(uint8_t *) pOld->tclasParams.ipv6.
srcIpAddr, 16);
qdf_mem_copy((uint8_t *) &pDot11f->info.IpParams.
params.IpV6Params.dest,
(uint8_t *) pOld->tclasParams.ipv6.
dstIpAddr, 16);
pDot11f->info.IpParams.params.IpV6Params.src_port =
pOld->tclasParams.ipv6.srcPort;
pDot11f->info.IpParams.params.IpV6Params.dest_port =
pOld->tclasParams.ipv6.dstPort;
qdf_mem_copy((uint8_t *) &pDot11f->info.IpParams.
params.IpV6Params.flow_label,
(uint8_t *) pOld->tclasParams.ipv6.
flowLabel, 3);
}
break;
case SIR_MAC_TCLASTYPE_8021DQ:
pDot11f->info.Params8021dq.tag_type =
pOld->tclasParams.t8021dq.tag;
break;
default:
pe_err("Bad TCLAS type %d", pDot11f->classifier_type);
return QDF_STATUS_E_FAILURE;
}
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_tclas. */
QDF_STATUS
populate_dot11f_wmmtclas(struct mac_context *mac,
tSirTclasInfo *pOld, tDot11fIEWMMTCLAS *pDot11f)
{
pDot11f->version = 1;
pDot11f->user_priority = pOld->tclas.userPrio;
pDot11f->classifier_type = pOld->tclas.classifierType;
pDot11f->classifier_mask = pOld->tclas.classifierMask;
switch (pDot11f->classifier_type) {
case SIR_MAC_TCLASTYPE_ETHERNET:
qdf_mem_copy((uint8_t *) &pDot11f->info.EthParams.source,
(uint8_t *) &pOld->tclasParams.eth.srcAddr, 6);
qdf_mem_copy((uint8_t *) &pDot11f->info.EthParams.dest,
(uint8_t *) &pOld->tclasParams.eth.dstAddr, 6);
pDot11f->info.EthParams.type = pOld->tclasParams.eth.type;
break;
case SIR_MAC_TCLASTYPE_TCPUDPIP:
pDot11f->info.IpParams.version = pOld->version;
if (SIR_MAC_TCLAS_IPV4 == pDot11f->info.IpParams.version) {
qdf_mem_copy((uint8_t *) &pDot11f->info.IpParams.
params.IpV4Params.source,
(uint8_t *) pOld->tclasParams.ipv4.
srcIpAddr, 4);
qdf_mem_copy((uint8_t *) &pDot11f->info.IpParams.
params.IpV4Params.dest,
(uint8_t *) pOld->tclasParams.ipv4.
dstIpAddr, 4);
pDot11f->info.IpParams.params.IpV4Params.src_port =
pOld->tclasParams.ipv4.srcPort;
pDot11f->info.IpParams.params.IpV4Params.dest_port =
pOld->tclasParams.ipv4.dstPort;
pDot11f->info.IpParams.params.IpV4Params.DSCP =
pOld->tclasParams.ipv4.dscp;
pDot11f->info.IpParams.params.IpV4Params.proto =
pOld->tclasParams.ipv4.protocol;
pDot11f->info.IpParams.params.IpV4Params.reserved =
pOld->tclasParams.ipv4.rsvd;
} else {
qdf_mem_copy((uint8_t *) &pDot11f->info.IpParams.
params.IpV6Params.source,
(uint8_t *) pOld->tclasParams.ipv6.
srcIpAddr, 16);
qdf_mem_copy((uint8_t *) &pDot11f->info.IpParams.
params.IpV6Params.dest,
(uint8_t *) pOld->tclasParams.ipv6.
dstIpAddr, 16);
pDot11f->info.IpParams.params.IpV6Params.src_port =
pOld->tclasParams.ipv6.srcPort;
pDot11f->info.IpParams.params.IpV6Params.dest_port =
pOld->tclasParams.ipv6.dstPort;
qdf_mem_copy((uint8_t *) &pDot11f->info.IpParams.
params.IpV6Params.flow_label,
(uint8_t *) pOld->tclasParams.ipv6.
flowLabel, 3);
}
break;
case SIR_MAC_TCLASTYPE_8021DQ:
pDot11f->info.Params8021dq.tag_type =
pOld->tclasParams.t8021dq.tag;
break;
default:
pe_err("Bad TCLAS type %d in populate_dot11f_tclas",
pDot11f->classifier_type);
return QDF_STATUS_E_FAILURE;
}
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
} /* End populate_dot11f_wmmtclas. */
QDF_STATUS populate_dot11f_wsc(struct mac_context *mac,
tDot11fIEWscBeacon *pDot11f)
{
uint32_t wpsState;
pDot11f->Version.present = 1;
pDot11f->Version.major = 0x01;
pDot11f->Version.minor = 0x00;
wpsState = mac->mlme_cfg->wps_params.wps_state;
pDot11f->WPSState.present = 1;
pDot11f->WPSState.state = (uint8_t) wpsState;
pDot11f->APSetupLocked.present = 0;
pDot11f->SelectedRegistrar.present = 0;
pDot11f->DevicePasswordID.present = 0;
pDot11f->SelectedRegistrarConfigMethods.present = 0;
pDot11f->UUID_E.present = 0;
pDot11f->RFBands.present = 0;
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS populate_dot11f_wsc_registrar_info(struct mac_context *mac,
tDot11fIEWscBeacon *pDot11f)
{
const struct sLimWscIeInfo *const pWscIeInfo = &(mac->lim.wscIeInfo);
pDot11f->APSetupLocked.present = 1;
pDot11f->APSetupLocked.fLocked = pWscIeInfo->apSetupLocked;
pDot11f->SelectedRegistrar.present = 1;
pDot11f->SelectedRegistrar.selected = pWscIeInfo->selectedRegistrar;
pDot11f->DevicePasswordID.present = 1;
pDot11f->DevicePasswordID.id =
(uint16_t)mac->mlme_cfg->wps_params.wps_device_password_id;
pDot11f->SelectedRegistrarConfigMethods.present = 1;
pDot11f->SelectedRegistrarConfigMethods.methods =
pWscIeInfo->selectedRegistrarConfigMethods;
/* UUID_E and RF Bands are applicable only for dual band AP */
return QDF_STATUS_SUCCESS;
}
QDF_STATUS de_populate_dot11f_wsc_registrar_info(struct mac_context *mac,
tDot11fIEWscBeacon *pDot11f)
{
pDot11f->APSetupLocked.present = 0;
pDot11f->SelectedRegistrar.present = 0;
pDot11f->DevicePasswordID.present = 0;
pDot11f->SelectedRegistrarConfigMethods.present = 0;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS populate_dot11f_probe_res_wpsi_es(struct mac_context *mac,
tDot11fIEWscProbeRes *pDot11f,
struct pe_session *pe_session)
{
tSirWPSProbeRspIE *pSirWPSProbeRspIE;
pSirWPSProbeRspIE = &pe_session->APWPSIEs.SirWPSProbeRspIE;
if (pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_VER_PRESENT) {
pDot11f->present = 1;
pDot11f->Version.present = 1;
pDot11f->Version.major =
(uint8_t) ((pSirWPSProbeRspIE->Version & 0xF0) >> 4);
pDot11f->Version.minor =
(uint8_t) (pSirWPSProbeRspIE->Version & 0x0F);
} else {
pDot11f->present = 0;
pDot11f->Version.present = 0;
}
if (pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_STATE_PRESENT) {
pDot11f->WPSState.present = 1;
pDot11f->WPSState.state = (uint8_t) pSirWPSProbeRspIE->wpsState;
} else
pDot11f->WPSState.present = 0;
if (pSirWPSProbeRspIE->
FieldPresent & SIR_WPS_PROBRSP_APSETUPLOCK_PRESENT) {
pDot11f->APSetupLocked.present = 1;
pDot11f->APSetupLocked.fLocked =
pSirWPSProbeRspIE->APSetupLocked;
} else
pDot11f->APSetupLocked.present = 0;
if (pSirWPSProbeRspIE->
FieldPresent & SIR_WPS_PROBRSP_SELECTEDREGISTRA_PRESENT) {
pDot11f->SelectedRegistrar.present = 1;
pDot11f->SelectedRegistrar.selected =
pSirWPSProbeRspIE->SelectedRegistra;
} else
pDot11f->SelectedRegistrar.present = 0;
if (pSirWPSProbeRspIE->
FieldPresent & SIR_WPS_PROBRSP_DEVICEPASSWORDID_PRESENT) {
pDot11f->DevicePasswordID.present = 1;
pDot11f->DevicePasswordID.id =
pSirWPSProbeRspIE->DevicePasswordID;
} else
pDot11f->DevicePasswordID.present = 0;
if (pSirWPSProbeRspIE->
FieldPresent & SIR_WPS_PROBRSP_SELECTEDREGISTRACFGMETHOD_PRESENT) {
pDot11f->SelectedRegistrarConfigMethods.present = 1;
pDot11f->SelectedRegistrarConfigMethods.methods =
pSirWPSProbeRspIE->SelectedRegistraCfgMethod;
} else
pDot11f->SelectedRegistrarConfigMethods.present = 0;
if (pSirWPSProbeRspIE->
FieldPresent & SIR_WPS_PROBRSP_RESPONSETYPE_PRESENT) {
pDot11f->ResponseType.present = 1;
pDot11f->ResponseType.resType = pSirWPSProbeRspIE->ResponseType;
} else
pDot11f->ResponseType.present = 0;
if (pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_UUIDE_PRESENT) {
pDot11f->UUID_E.present = 1;
qdf_mem_copy(pDot11f->UUID_E.uuid, pSirWPSProbeRspIE->UUID_E,
WNI_CFG_WPS_UUID_LEN);
} else
pDot11f->UUID_E.present = 0;
if (pSirWPSProbeRspIE->
FieldPresent & SIR_WPS_PROBRSP_MANUFACTURE_PRESENT) {
pDot11f->Manufacturer.present = 1;
pDot11f->Manufacturer.num_name =
pSirWPSProbeRspIE->Manufacture.num_name;
qdf_mem_copy(pDot11f->Manufacturer.name,
pSirWPSProbeRspIE->Manufacture.name,
pSirWPSProbeRspIE->Manufacture.num_name);
} else
pDot11f->Manufacturer.present = 0;
if (pSirWPSProbeRspIE->
FieldPresent & SIR_WPS_PROBRSP_MODELNUMBER_PRESENT) {
pDot11f->ModelName.present = 1;
pDot11f->ModelName.num_text =
pSirWPSProbeRspIE->ModelName.num_text;
qdf_mem_copy(pDot11f->ModelName.text,
pSirWPSProbeRspIE->ModelName.text,
pDot11f->ModelName.num_text);
} else
pDot11f->ModelName.present = 0;
if (pSirWPSProbeRspIE->
FieldPresent & SIR_WPS_PROBRSP_MODELNUMBER_PRESENT) {
pDot11f->ModelNumber.present = 1;
pDot11f->ModelNumber.num_text =
pSirWPSProbeRspIE->ModelNumber.num_text;
qdf_mem_copy(pDot11f->ModelNumber.text,
pSirWPSProbeRspIE->ModelNumber.text,
pDot11f->ModelNumber.num_text);
} else
pDot11f->ModelNumber.present = 0;
if (pSirWPSProbeRspIE->
FieldPresent & SIR_WPS_PROBRSP_SERIALNUMBER_PRESENT) {
pDot11f->SerialNumber.present = 1;
pDot11f->SerialNumber.num_text =
pSirWPSProbeRspIE->SerialNumber.num_text;
qdf_mem_copy(pDot11f->SerialNumber.text,
pSirWPSProbeRspIE->SerialNumber.text,
pDot11f->SerialNumber.num_text);
} else
pDot11f->SerialNumber.present = 0;
if (pSirWPSProbeRspIE->
FieldPresent & SIR_WPS_PROBRSP_PRIMARYDEVICETYPE_PRESENT) {
pDot11f->PrimaryDeviceType.present = 1;
qdf_mem_copy(pDot11f->PrimaryDeviceType.oui,
pSirWPSProbeRspIE->PrimaryDeviceOUI,
sizeof(pSirWPSProbeRspIE->PrimaryDeviceOUI));
pDot11f->PrimaryDeviceType.primary_category =
(uint16_t) pSirWPSProbeRspIE->PrimaryDeviceCategory;
pDot11f->PrimaryDeviceType.sub_category =
(uint16_t) pSirWPSProbeRspIE->DeviceSubCategory;
} else
pDot11f->PrimaryDeviceType.present = 0;
if (pSirWPSProbeRspIE->
FieldPresent & SIR_WPS_PROBRSP_DEVICENAME_PRESENT) {
pDot11f->DeviceName.present = 1;
pDot11f->DeviceName.num_text =
pSirWPSProbeRspIE->DeviceName.num_text;
qdf_mem_copy(pDot11f->DeviceName.text,
pSirWPSProbeRspIE->DeviceName.text,
pDot11f->DeviceName.num_text);
} else
pDot11f->DeviceName.present = 0;
if (pSirWPSProbeRspIE->
FieldPresent & SIR_WPS_PROBRSP_CONFIGMETHODS_PRESENT) {
pDot11f->ConfigMethods.present = 1;
pDot11f->ConfigMethods.methods =
pSirWPSProbeRspIE->ConfigMethod;
} else
pDot11f->ConfigMethods.present = 0;
if (pSirWPSProbeRspIE->FieldPresent & SIR_WPS_PROBRSP_RF_BANDS_PRESENT) {
pDot11f->RFBands.present = 1;
pDot11f->RFBands.bands = pSirWPSProbeRspIE->RFBand;
} else
pDot11f->RFBands.present = 0;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS populate_dot11f_beacon_wpsi_es(struct mac_context *mac,
tDot11fIEWscBeacon *pDot11f,
struct pe_session *pe_session)
{
tSirWPSBeaconIE *pSirWPSBeaconIE;
pSirWPSBeaconIE = &pe_session->APWPSIEs.SirWPSBeaconIE;
if (pSirWPSBeaconIE->FieldPresent & SIR_WPS_PROBRSP_VER_PRESENT) {
pDot11f->present = 1;
pDot11f->Version.present = 1;
pDot11f->Version.major =
(uint8_t) ((pSirWPSBeaconIE->Version & 0xF0) >> 4);
pDot11f->Version.minor =
(uint8_t) (pSirWPSBeaconIE->Version & 0x0F);
} else {
pDot11f->present = 0;
pDot11f->Version.present = 0;
}
if (pSirWPSBeaconIE->FieldPresent & SIR_WPS_BEACON_STATE_PRESENT) {
pDot11f->WPSState.present = 1;
pDot11f->WPSState.state = (uint8_t) pSirWPSBeaconIE->wpsState;
} else
pDot11f->WPSState.present = 0;
if (pSirWPSBeaconIE->FieldPresent & SIR_WPS_BEACON_APSETUPLOCK_PRESENT) {
pDot11f->APSetupLocked.present = 1;
pDot11f->APSetupLocked.fLocked = pSirWPSBeaconIE->APSetupLocked;
} else
pDot11f->APSetupLocked.present = 0;
if (pSirWPSBeaconIE->
FieldPresent & SIR_WPS_BEACON_SELECTEDREGISTRA_PRESENT) {
pDot11f->SelectedRegistrar.present = 1;
pDot11f->SelectedRegistrar.selected =
pSirWPSBeaconIE->SelectedRegistra;
} else
pDot11f->SelectedRegistrar.present = 0;
if (pSirWPSBeaconIE->
FieldPresent & SIR_WPS_BEACON_DEVICEPASSWORDID_PRESENT) {
pDot11f->DevicePasswordID.present = 1;
pDot11f->DevicePasswordID.id =
pSirWPSBeaconIE->DevicePasswordID;
} else
pDot11f->DevicePasswordID.present = 0;
if (pSirWPSBeaconIE->
FieldPresent & SIR_WPS_BEACON_SELECTEDREGISTRACFGMETHOD_PRESENT) {
pDot11f->SelectedRegistrarConfigMethods.present = 1;
pDot11f->SelectedRegistrarConfigMethods.methods =
pSirWPSBeaconIE->SelectedRegistraCfgMethod;
} else
pDot11f->SelectedRegistrarConfigMethods.present = 0;
if (pSirWPSBeaconIE->FieldPresent & SIR_WPS_BEACON_UUIDE_PRESENT) {
pDot11f->UUID_E.present = 1;
qdf_mem_copy(pDot11f->UUID_E.uuid, pSirWPSBeaconIE->UUID_E,
WNI_CFG_WPS_UUID_LEN);
} else
pDot11f->UUID_E.present = 0;
if (pSirWPSBeaconIE->FieldPresent & SIR_WPS_BEACON_RF_BANDS_PRESENT) {
pDot11f->RFBands.present = 1;
pDot11f->RFBands.bands = pSirWPSBeaconIE->RFBand;
} else
pDot11f->RFBands.present = 0;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS populate_dot11f_wsc_in_probe_res(struct mac_context *mac,
tDot11fIEWscProbeRes *pDot11f)
{
uint32_t cfgStrLen;
uint32_t val;
uint32_t wpsVersion, wpsState;
wpsVersion = mac->mlme_cfg->wps_params.wps_version;
pDot11f->Version.present = 1;
pDot11f->Version.major = (uint8_t) ((wpsVersion & 0xF0) >> 4);
pDot11f->Version.minor = (uint8_t) (wpsVersion & 0x0F);
wpsState = mac->mlme_cfg->wps_params.wps_state;
pDot11f->WPSState.present = 1;
pDot11f->WPSState.state = (uint8_t) wpsState;
pDot11f->APSetupLocked.present = 0;
pDot11f->SelectedRegistrar.present = 0;
pDot11f->DevicePasswordID.present = 0;
pDot11f->SelectedRegistrarConfigMethods.present = 0;
pDot11f->ResponseType.present = 1;
if ((mac->lim.wscIeInfo.reqType == REQ_TYPE_REGISTRAR) ||
(mac->lim.wscIeInfo.reqType == REQ_TYPE_WLAN_MANAGER_REGISTRAR)) {
pDot11f->ResponseType.resType = RESP_TYPE_ENROLLEE_OPEN_8021X;
} else {
pDot11f->ResponseType.resType = RESP_TYPE_AP;
}
/* UUID is a 16 byte long binary*/
pDot11f->UUID_E.present = 1;
*pDot11f->UUID_E.uuid = '\0';
wlan_mlme_get_wps_uuid(&mac->mlme_cfg->wps_params,
pDot11f->UUID_E.uuid);
pDot11f->Manufacturer.present = 1;
cfgStrLen = sizeof(pDot11f->Manufacturer.name);
if (wlan_mlme_get_manufacturer_name(mac->psoc,
pDot11f->Manufacturer.name,
&cfgStrLen) != QDF_STATUS_SUCCESS) {
pDot11f->Manufacturer.num_name = 0;
} else {
pDot11f->Manufacturer.num_name =
(uint8_t) (cfgStrLen & 0x000000FF);
}
pDot11f->ModelName.present = 1;
cfgStrLen = sizeof(pDot11f->ModelName.text);
if (wlan_mlme_get_model_name(mac->psoc,
pDot11f->ModelName.text,
&cfgStrLen) != QDF_STATUS_SUCCESS) {
pDot11f->ModelName.num_text = 0;
} else {
pDot11f->ModelName.num_text =
(uint8_t) (cfgStrLen & 0x000000FF);
}
pDot11f->ModelNumber.present = 1;
cfgStrLen = sizeof(pDot11f->ModelNumber.text);
if (wlan_mlme_get_model_number(mac->psoc,
pDot11f->ModelNumber.text,
&cfgStrLen) != QDF_STATUS_SUCCESS) {
pDot11f->ModelNumber.num_text = 0;
} else {
pDot11f->ModelNumber.num_text =
(uint8_t) (cfgStrLen & 0x000000FF);
}
pDot11f->SerialNumber.present = 1;
cfgStrLen = sizeof(pDot11f->SerialNumber.text);
if (wlan_mlme_get_manufacture_product_version
(mac->psoc,
pDot11f->SerialNumber.text,
&cfgStrLen) != QDF_STATUS_SUCCESS) {
pDot11f->SerialNumber.num_text = 0;
} else {
pDot11f->SerialNumber.num_text =
(uint8_t) (cfgStrLen & 0x000000FF);
}
pDot11f->PrimaryDeviceType.present = 1;
pDot11f->PrimaryDeviceType.primary_category =
(uint16_t)mac->mlme_cfg->wps_params.wps_primary_device_category;
val = mac->mlme_cfg->wps_params.wps_primary_device_oui;
*(pDot11f->PrimaryDeviceType.oui) =
(uint8_t) ((val >> 24) & 0xff);
*(pDot11f->PrimaryDeviceType.oui + 1) =
(uint8_t) ((val >> 16) & 0xff);
*(pDot11f->PrimaryDeviceType.oui + 2) =
(uint8_t) ((val >> 8) & 0xff);
*(pDot11f->PrimaryDeviceType.oui + 3) =
(uint8_t) ((val & 0xff));
pDot11f->PrimaryDeviceType.sub_category =
(uint16_t)mac->mlme_cfg->wps_params.wps_device_sub_category;
pDot11f->DeviceName.present = 1;
cfgStrLen = sizeof(pDot11f->DeviceName.text);
if (wlan_mlme_get_manufacture_product_name(mac->psoc,
pDot11f->DeviceName.text,
&cfgStrLen) !=
QDF_STATUS_SUCCESS) {
pDot11f->DeviceName.num_text = 0;
} else {
pDot11f->DeviceName.num_text =
(uint8_t) (cfgStrLen & 0x000000FF);
}
pDot11f->ConfigMethods.present = 1;
pDot11f->ConfigMethods.methods =
(uint16_t)(mac->mlme_cfg->wps_params.wps_cfg_method &
0x0000FFFF);
pDot11f->RFBands.present = 0;
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
populate_dot11f_wsc_registrar_info_in_probe_res(struct mac_context *mac,
tDot11fIEWscProbeRes *pDot11f)
{
const struct sLimWscIeInfo *const pWscIeInfo = &(mac->lim.wscIeInfo);
pDot11f->APSetupLocked.present = 1;
pDot11f->APSetupLocked.fLocked = pWscIeInfo->apSetupLocked;
pDot11f->SelectedRegistrar.present = 1;
pDot11f->SelectedRegistrar.selected = pWscIeInfo->selectedRegistrar;
pDot11f->DevicePasswordID.present = 1;
pDot11f->DevicePasswordID.id =
(uint16_t)mac->mlme_cfg->wps_params.wps_device_password_id;
pDot11f->SelectedRegistrarConfigMethods.present = 1;
pDot11f->SelectedRegistrarConfigMethods.methods =
pWscIeInfo->selectedRegistrarConfigMethods;
/* UUID_E and RF Bands are applicable only for dual band AP */
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
de_populate_dot11f_wsc_registrar_info_in_probe_res(struct mac_context *mac,
tDot11fIEWscProbeRes *
pDot11f)
{
pDot11f->APSetupLocked.present = 0;
pDot11f->SelectedRegistrar.present = 0;
pDot11f->DevicePasswordID.present = 0;
pDot11f->SelectedRegistrarConfigMethods.present = 0;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS populate_dot11_assoc_res_p2p_ie(struct mac_context *mac,
tDot11fIEP2PAssocRes *pDot11f,
tpSirAssocReq pRcvdAssocReq)
{
const uint8_t *p2pIe;
p2pIe = limGetP2pIEPtr(mac, pRcvdAssocReq->addIE.addIEdata,
pRcvdAssocReq->addIE.length);
if (p2pIe) {
pDot11f->present = 1;
pDot11f->P2PStatus.present = 1;
pDot11f->P2PStatus.status = QDF_STATUS_SUCCESS;
pDot11f->ExtendedListenTiming.present = 0;
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS populate_dot11f_wfatpc(struct mac_context *mac,
tDot11fIEWFATPC *pDot11f, uint8_t txPower,
uint8_t linkMargin)
{
pDot11f->txPower = txPower;
pDot11f->linkMargin = linkMargin;
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
populate_dot11f_beacon_report(struct mac_context *mac,
tDot11fIEMeasurementReport *pDot11f,
tSirMacBeaconReport *pBeaconReport,
bool is_last_frame)
{
tDot11fIEbeacon_report_frm_body_fragment_id *frm_body_frag_id;
pDot11f->report.Beacon.regClass = pBeaconReport->regClass;
pDot11f->report.Beacon.channel = pBeaconReport->channel;
qdf_mem_copy(pDot11f->report.Beacon.meas_start_time,
pBeaconReport->measStartTime,
sizeof(pDot11f->report.Beacon.meas_start_time));
pDot11f->report.Beacon.meas_duration = pBeaconReport->measDuration;
pDot11f->report.Beacon.condensed_PHY = pBeaconReport->phyType;
pDot11f->report.Beacon.reported_frame_type =
!pBeaconReport->bcnProbeRsp;
pDot11f->report.Beacon.RCPI = pBeaconReport->rcpi;
pDot11f->report.Beacon.RSNI = pBeaconReport->rsni;
qdf_mem_copy(pDot11f->report.Beacon.BSSID, pBeaconReport->bssid,
sizeof(tSirMacAddr));
pDot11f->report.Beacon.antenna_id = pBeaconReport->antennaId;
pDot11f->report.Beacon.parent_TSF = pBeaconReport->parentTSF;
if (pBeaconReport->numIes) {
pDot11f->report.Beacon.BeaconReportFrmBody.present = 1;
qdf_mem_copy(pDot11f->report.Beacon.BeaconReportFrmBody.
reportedFields, pBeaconReport->Ies,
pBeaconReport->numIes);
pDot11f->report.Beacon.BeaconReportFrmBody.num_reportedFields =
pBeaconReport->numIes;
}
if (pBeaconReport->last_bcn_report_ind_support) {
pe_debug("Including Last Beacon Report in RRM Frame");
frm_body_frag_id = &pDot11f->report.Beacon.
beacon_report_frm_body_fragment_id;
frm_body_frag_id->present = 1;
frm_body_frag_id->beacon_report_id =
pBeaconReport->frame_body_frag_id.id;
frm_body_frag_id->fragment_id_number =
pBeaconReport->frame_body_frag_id.frag_id;
frm_body_frag_id->more_fragments =
pBeaconReport->frame_body_frag_id.more_frags;
pDot11f->report.Beacon.last_beacon_report_indication.present =
1;
pDot11f->report.Beacon.last_beacon_report_indication.
last_fragment = is_last_frame;
pe_debug("id %d frag_id %d more_frags %d is_last_frame %d",
frm_body_frag_id->beacon_report_id,
frm_body_frag_id->fragment_id_number,
frm_body_frag_id->more_fragments,
is_last_frame);
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS populate_dot11f_rrm_ie(struct mac_context *mac,
tDot11fIERRMEnabledCap *pDot11f,
struct pe_session *pe_session)
{
tpRRMCaps pRrmCaps;
uint8_t *bytes;
pRrmCaps = rrm_get_capabilities(mac, pe_session);
pDot11f->LinkMeasurement = pRrmCaps->LinkMeasurement;
pDot11f->NeighborRpt = pRrmCaps->NeighborRpt;
pDot11f->parallel = pRrmCaps->parallel;
pDot11f->repeated = pRrmCaps->repeated;
pDot11f->BeaconPassive = pRrmCaps->BeaconPassive;
pDot11f->BeaconActive = pRrmCaps->BeaconActive;
pDot11f->BeaconTable = pRrmCaps->BeaconTable;
pDot11f->BeaconRepCond = pRrmCaps->BeaconRepCond;
pDot11f->FrameMeasurement = pRrmCaps->FrameMeasurement;
pDot11f->ChannelLoad = pRrmCaps->ChannelLoad;
pDot11f->NoiseHistogram = pRrmCaps->NoiseHistogram;
pDot11f->statistics = pRrmCaps->statistics;
pDot11f->LCIMeasurement = pRrmCaps->LCIMeasurement;
pDot11f->LCIAzimuth = pRrmCaps->LCIAzimuth;
pDot11f->TCMCapability = pRrmCaps->TCMCapability;
pDot11f->triggeredTCM = pRrmCaps->triggeredTCM;
pDot11f->APChanReport = pRrmCaps->APChanReport;
pDot11f->RRMMIBEnabled = pRrmCaps->RRMMIBEnabled;
pDot11f->operatingChanMax = pRrmCaps->operatingChanMax;
pDot11f->nonOperatinChanMax = pRrmCaps->nonOperatingChanMax;
pDot11f->MeasurementPilot = pRrmCaps->MeasurementPilot;
pDot11f->MeasurementPilotEnabled = pRrmCaps->MeasurementPilotEnabled;
pDot11f->NeighborTSFOffset = pRrmCaps->NeighborTSFOffset;
pDot11f->RCPIMeasurement = pRrmCaps->RCPIMeasurement;
pDot11f->RSNIMeasurement = pRrmCaps->RSNIMeasurement;
pDot11f->BssAvgAccessDelay = pRrmCaps->BssAvgAccessDelay;
pDot11f->BSSAvailAdmission = pRrmCaps->BSSAvailAdmission;
pDot11f->AntennaInformation = pRrmCaps->AntennaInformation;
pDot11f->fine_time_meas_rpt = pRrmCaps->fine_time_meas_rpt;
pDot11f->lci_capability = pRrmCaps->lci_capability;
pDot11f->reserved = pRrmCaps->reserved;
bytes = (uint8_t *) pDot11f + 1; /* ignore present field */
pe_debug("RRM Enabled Cap IE: %02x %02x %02x %02x %02x",
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]);
pDot11f->present = 1;
return QDF_STATUS_SUCCESS;
}
void populate_mdie(struct mac_context *mac,
tDot11fIEMobilityDomain *pDot11f,
uint8_t mdie[SIR_MDIE_SIZE])
{
pDot11f->present = 1;
pDot11f->MDID = (uint16_t) ((mdie[1] << 8) | (mdie[0]));
/* Plugfest fix */
pDot11f->overDSCap = (mdie[2] & 0x01);
pDot11f->resourceReqCap = ((mdie[2] >> 1) & 0x01);
}
#ifdef WLAN_FEATURE_FILS_SK
void populate_fils_ft_info(struct mac_context *mac, tDot11fIEFTInfo *ft_info,
struct pe_session *pe_session)
{
struct pe_fils_session *ft_fils_info = pe_session->fils_info;
if (!ft_fils_info)
return;
if (!ft_fils_info->ft_ie.present) {
ft_info->present = 0;
pe_err("FT IE doesn't exist");
return;
}
ft_info->IECount = ft_fils_info->ft_ie.element_count;
qdf_mem_copy(ft_info->MIC, ft_fils_info->ft_ie.mic,
FT_MIC_LEN);
qdf_mem_copy(ft_info->Anonce, ft_fils_info->ft_ie.anonce,
FT_NONCE_LEN);
qdf_mem_copy(ft_info->Snonce, ft_fils_info->ft_ie.snonce,
FT_NONCE_LEN);
if (ft_fils_info->ft_ie.r0kh_id_len > 0) {
ft_info->R0KH_ID.present = 1;
qdf_mem_copy(ft_info->R0KH_ID.PMK_R0_ID,
ft_fils_info->ft_ie.r0kh_id,
ft_fils_info->ft_ie.r0kh_id_len);
ft_info->R0KH_ID.num_PMK_R0_ID =
ft_fils_info->ft_ie.r0kh_id_len;
}
ft_info->R1KH_ID.present = 1;
qdf_mem_copy(ft_info->R1KH_ID.PMK_R1_ID,
ft_fils_info->ft_ie.r1kh_id,
FT_R1KH_ID_LEN);
qdf_mem_copy(&ft_info->GTK, &ft_fils_info->ft_ie.gtk_ie,
sizeof(struct mac_ft_gtk_ie));
qdf_mem_copy(&ft_info->IGTK, &ft_fils_info->ft_ie.igtk_ie,
sizeof(struct mac_ft_igtk_ie));
ft_info->present = 1;
}
#endif
void populate_dot11f_assoc_rsp_rates(struct mac_context *mac,
tDot11fIESuppRates *pSupp,
tDot11fIEExtSuppRates *pExt,
uint16_t *_11bRates, uint16_t *_11aRates)
{
uint8_t num_supp = 0, num_ext = 0;
uint8_t i, j;
for (i = 0; (i < SIR_NUM_11B_RATES && _11bRates[i]); i++, num_supp++) {
pSupp->rates[num_supp] = (uint8_t) _11bRates[i];
}
for (j = 0; (j < SIR_NUM_11A_RATES && _11aRates[j]); j++) {
if (num_supp < 8)
pSupp->rates[num_supp++] = (uint8_t) _11aRates[j];
else
pExt->rates[num_ext++] = (uint8_t) _11aRates[j];
}
if (num_supp) {
pSupp->num_rates = num_supp;
pSupp->present = 1;
}
if (num_ext) {
pExt->num_rates = num_ext;
pExt->present = 1;
}
}
void populate_dot11f_timeout_interval(struct mac_context *mac,
tDot11fIETimeoutInterval *pDot11f,
uint8_t type, uint32_t value)
{
pDot11f->present = 1;
pDot11f->timeoutType = type;
pDot11f->timeoutValue = value;
}
/**
* populate_dot11f_timing_advert_frame() - Populate the TA mgmt frame fields
* @mac: the MAC context
* @frame: pointer to the TA frame
*
* Return: The SIR status.
*/
QDF_STATUS
populate_dot11f_timing_advert_frame(struct mac_context *mac_ctx,
tDot11fTimingAdvertisementFrame *frame)
{
uint32_t val, len, j = 0;
uint8_t temp[CFG_MAX_STR_LEN], code[3];
tSirMacChanInfo *max_tx_power_data;
int32_t rem_length = 0, copied_length = 0;
/* Capabilities */
val = mac_ctx->mlme_cfg->wep_params.is_privacy_enabled;
if (val)
frame->Capabilities.privacy = 1;
if (mac_ctx->mlme_cfg->ht_caps.short_preamble)
frame->Capabilities.shortPreamble = 1;
if (mac_ctx->mlme_cfg->gen.enabled_11h)
frame->Capabilities.spectrumMgt = 1;
if (mac_ctx->mlme_cfg->wmm_params.qos_enabled)
frame->Capabilities.qos = 1;
if (mac_ctx->mlme_cfg->scoring.apsd_enabled)
frame->Capabilities.apsd = 1;
val = mac_ctx->mlme_cfg->feature_flags.enable_block_ack;
frame->Capabilities.delayedBA =
(uint16_t)((val >> WNI_CFG_BLOCK_ACK_ENABLED_DELAYED) & 1);
frame->Capabilities.immediateBA =
(uint16_t)((val >> WNI_CFG_BLOCK_ACK_ENABLED_IMMEDIATE) & 1);
/* Country */
len = mac_ctx->mlme_cfg->power.max_tx_power_5.len;
max_tx_power_data =
(tSirMacChanInfo *)mac_ctx->mlme_cfg->power.max_tx_power_5.data;
rem_length = len;
while (rem_length >= (sizeof(tSirMacChanInfo))) {
temp[copied_length++] =
(uint8_t)wlan_reg_freq_to_chan(
mac_ctx->pdev,
max_tx_power_data[j].first_freq);
temp[copied_length++] = max_tx_power_data[j].numChannels;
temp[copied_length++] = max_tx_power_data[j].maxTxPower;
j++;
rem_length -= (sizeof(tSirMacChanInfo));
}
wlan_reg_read_current_country(mac_ctx->psoc, code);
qdf_mem_copy(&frame->Country, code, 2);
if (copied_length > MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE)
copied_length = MAX_SIZE_OF_TRIPLETS_IN_COUNTRY_IE;
frame->Country.num_triplets = (uint8_t)(copied_length / 3);
qdf_mem_copy((uint8_t *)&frame->Country.triplets, temp, copied_length);
frame->Country.present = 1;
/* PowerConstraints */
frame->PowerConstraints.localPowerConstraints =
mac_ctx->mlme_cfg->power.local_power_constraint;
frame->PowerConstraints.present = 1;
/* TimeAdvertisement */
frame->TimeAdvertisement.present = 1;
frame->TimeAdvertisement.timing_capabilities = 1;
return QDF_STATUS_SUCCESS;
}
#ifdef WLAN_FEATURE_11AX
/**
* populate_dot11f_he_caps() - pouldate HE Capability IE
* @mac_ctx: Global MAC context
* @session: PE session
* @he_cap: pointer to HE capability IE
*
* Populdate the HE capability IE based on the session.
*/
QDF_STATUS populate_dot11f_he_caps(struct mac_context *mac_ctx, struct pe_session *session,
tDot11fIEhe_cap *he_cap)
{
uint8_t *ppet;
uint32_t value = 0;
he_cap->present = 1;
if (!session) {
qdf_mem_copy(he_cap, &mac_ctx->mlme_cfg->he_caps.dot11_he_cap,
sizeof(tDot11fIEhe_cap));
return QDF_STATUS_SUCCESS;
}
/** TODO: String items needs attention. **/
qdf_mem_copy(he_cap, &session->he_config, sizeof(*he_cap));
if (he_cap->ppet_present) {
value = WNI_CFG_HE_PPET_LEN;
/* if session is present, populate PPET based on band */
if (!wlan_reg_is_24ghz_ch_freq(session->curr_op_freq))
qdf_mem_copy(he_cap->ppet.ppe_threshold.ppe_th,
mac_ctx->mlme_cfg->he_caps.he_ppet_5g,
value);
else
qdf_mem_copy(he_cap->ppet.ppe_threshold.ppe_th,
mac_ctx->mlme_cfg->he_caps.he_ppet_2g,
value);
ppet = he_cap->ppet.ppe_threshold.ppe_th;
he_cap->ppet.ppe_threshold.num_ppe_th =
lim_truncate_ppet(ppet, value);
} else {
he_cap->ppet.ppe_threshold.num_ppe_th = 0;
}
return QDF_STATUS_SUCCESS;
}
/**
* populate_dot11f_he_operation() - pouldate HE Operation IE
* @mac_ctx: Global MAC context
* @session: PE session
* @he_op: pointer to HE Operation IE
*
* Populdate the HE Operation IE based on the session.
*/
QDF_STATUS
populate_dot11f_he_operation(struct mac_context *mac_ctx,
struct pe_session *session, tDot11fIEhe_op *he_op)
{
qdf_mem_copy(he_op, &session->he_op, sizeof(*he_op));
he_op->present = 1;
if (!session->he_6ghz_band) {
he_op->vht_oper_present = 1;
if (session->ch_width > CH_WIDTH_40MHZ) {
he_op->vht_oper.info.chan_width = 1;
he_op->vht_oper.info.center_freq_seg0 =
session->ch_center_freq_seg0;
if (session->ch_width == CH_WIDTH_80P80MHZ ||
session->ch_width == CH_WIDTH_160MHZ)
he_op->vht_oper.info.center_freq_seg1 =
session->ch_center_freq_seg1;
else
he_op->vht_oper.info.center_freq_seg1 = 0;
} else {
he_op->vht_oper.info.chan_width = 0;
he_op->vht_oper.info.center_freq_seg0 = 0;
he_op->vht_oper.info.center_freq_seg1 = 0;
}
} else {
he_op->oper_info_6g_present = 1;
he_op->oper_info_6g.info.ch_width = session->ch_width;
he_op->oper_info_6g.info.center_freq_seg0 =
session->ch_center_freq_seg0;
if (session->ch_width == CH_WIDTH_80P80MHZ ||
session->ch_width == CH_WIDTH_160MHZ) {
he_op->oper_info_6g.info.center_freq_seg1 =
session->ch_center_freq_seg1;
he_op->oper_info_6g.info.ch_width = CH_WIDTH_160MHZ;
} else {
he_op->oper_info_6g.info.center_freq_seg1 = 0;
}
he_op->oper_info_6g.info.primary_ch =
wlan_reg_freq_to_chan(mac_ctx->pdev,
session->curr_op_freq);
he_op->oper_info_6g.info.dup_bcon = 0;
he_op->oper_info_6g.info.min_rate = 0;
}
lim_log_he_op(mac_ctx, he_op, session);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
populate_dot11f_he_6ghz_cap(struct mac_context *mac_ctx,
struct pe_session *session,
tDot11fIEhe_6ghz_band_cap *he_6g_cap)
{
struct mlme_ht_capabilities_info *ht_cap_info;
struct mlme_vht_capabilities_info *vht_cap_info;
if (session && !session->he_6ghz_band)
return QDF_STATUS_SUCCESS;
ht_cap_info = &mac_ctx->mlme_cfg->ht_caps.ht_cap_info;
vht_cap_info = &mac_ctx->mlme_cfg->vht_caps.vht_cap_info;
he_6g_cap->present = 1;
he_6g_cap->min_mpdu_start_spacing =
mac_ctx->mlme_cfg->ht_caps.ampdu_params.mpdu_density;
if (session)
he_6g_cap->max_ampdu_len_exp =
session->vht_config.max_ampdu_lenexp;
else
he_6g_cap->max_ampdu_len_exp =
vht_cap_info->ampdu_len_exponent & 0x7;
he_6g_cap->max_mpdu_len = vht_cap_info->ampdu_len;
he_6g_cap->sm_pow_save = ht_cap_info->mimo_power_save;
he_6g_cap->rd_responder = 0;
he_6g_cap->rx_ant_pattern_consistency = 0;
he_6g_cap->tx_ant_pattern_consistency = 0;
lim_log_he_6g_cap(mac_ctx, he_6g_cap);
return QDF_STATUS_SUCCESS;
}
#ifdef WLAN_FEATURE_11AX_BSS_COLOR
/**
* populate_dot11f_he_bss_color_change() - pouldate HE BSS color change IE
* @mac_ctx: Global MAC context
* @session: PE session
* @he_bss_color: pointer to HE BSS color change IE
*
* Populdate the HE BSS color change IE based on the session.
*/
QDF_STATUS
populate_dot11f_he_bss_color_change(struct mac_context *mac_ctx,
struct pe_session *session,
tDot11fIEbss_color_change *he_bss_color)
{
if (!session->bss_color_changing) {
he_bss_color->present = 0;
return QDF_STATUS_SUCCESS;
}
he_bss_color->present = 1;
he_bss_color->countdown = session->he_bss_color_change.countdown;
he_bss_color->new_color = session->he_bss_color_change.new_color;
lim_log_he_bss_color(mac_ctx, he_bss_color);
return QDF_STATUS_SUCCESS;
}
#endif
#endif
#ifdef WLAN_SUPPORT_TWT
QDF_STATUS populate_dot11f_twt_extended_caps(struct mac_context *mac_ctx,
struct pe_session *pe_session,
tDot11fIEExtCap *dot11f)
{
struct s_ext_cap *p_ext_cap;
if (!pe_session->enable_session_twt_support)
return QDF_STATUS_SUCCESS;
dot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN;
p_ext_cap = (struct s_ext_cap *)dot11f->bytes;
if (pe_session->opmode == QDF_STA_MODE)
p_ext_cap->twt_requestor_support =
mac_ctx->mlme_cfg->twt_cfg.is_twt_requestor_enabled;
if (pe_session->opmode == QDF_SAP_MODE)
p_ext_cap->twt_responder_support =
mac_ctx->mlme_cfg->twt_cfg.is_twt_responder_enabled;
dot11f->num_bytes = lim_compute_ext_cap_ie_length(dot11f);
return QDF_STATUS_SUCCESS;
}
#endif
QDF_STATUS populate_dot11f_btm_caps(struct mac_context *mac_ctx,
struct pe_session *pe_session,
struct sDot11fIEExtCap *dot11f)
{
struct s_ext_cap *p_ext_cap;
uint32_t fw_akm_bitmap;
bool sae_can_roam;
dot11f->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN;
p_ext_cap = (struct s_ext_cap *)dot11f->bytes;
fw_akm_bitmap = mac_ctx->mlme_cfg->lfr.fw_akm_bitmap;
sae_can_roam = (((fw_akm_bitmap) & (1 << AKM_SAE)) ? true : false);
if (pe_session->connected_akm == ANI_AKM_TYPE_SAE &&
!sae_can_roam) {
p_ext_cap->bss_transition = 0;
pe_debug("Disable btm cap for SAE roam not supported");
}
dot11f->num_bytes = lim_compute_ext_cap_ie_length(dot11f);
return QDF_STATUS_SUCCESS;
}
/* parser_api.c ends here. */