Files
Linux_Drivers/osdrv/extdrv/wireless/mediatek/mt7603/common/mlme.c
forum_service 213c880673 add driver of tp、wiegand-gpio and wireless
Change-Id: Ie3c11d9d85cf1a05042f5690ac711856fe8b1ad7
2023-12-22 09:56:05 +08:00

10143 lines
294 KiB
C

/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2004, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
mlme.c
Abstract:
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#include "rt_config.h"
#include <stdarg.h>
#ifdef DOT11R_FT_SUPPORT
#include "ft.h"
#endif /* DOT11R_FT_SUPPORT */
#ifdef DOT11V_WNM_SUPPORT
#include "wnm.h"
#endif /* DOT11V_WNM_SUPPORT */
UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72};
UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
#ifdef CONFIG_STA_SUPPORT
#ifdef IWSC_SUPPORT
UCHAR IWSC_OUI[] = {0x00, 0x50, 0xf2, 0x10};
UCHAR IWSC_ACTION_OUI[] = {0x50, 0x6F, 0x9A, 0x10};
#endif /* IWSC_SUPPORT */
#endif /* CONFIG_STA_SUPPORT */
#ifdef WFA_WFD_SUPPORT
UCHAR WFA_WFD_OUI[] = {0x50, 0x6f, 0x9a, 0x0a};
#endif /* WFA_WFD_SUPPORT */
UCHAR OfdmRateToRxwiMCS[12] = {
0, 0, 0, 0,
0, 1, 2, 3, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */
4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */
};
UCHAR RxwiMCSToOfdmRate[12] = {
RATE_6, RATE_9, RATE_12, RATE_18,
RATE_24, RATE_36, RATE_48, RATE_54, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */
4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */
};
#ifdef WAC_SUPPORT
extern UCHAR SAMSUNG_OUI[];
extern UCHAR SAMSUNG_OUI_TYPE;
#endif /* WAC_SUPPORT */
#if 0
PCHAR ReasonString[] = {
/* 0 */ "Reserved",
/* 1 */ "Unspecified Reason",
/* 2 */ "Previous Auth no longer valid",
/* 3 */ "STA is leaving / has left",
/* 4 */ "DIS-ASSOC due to inactivity",
/* 5 */ "AP unable to hanle all associations",
/* 6 */ "class 2 error",
/* 7 */ "class 3 error",
/* 8 */ "STA is leaving / has left",
/* 9 */ "require auth before assoc/re-assoc",
/* 10 */ "Reserved",
/* 11 */ "Reserved",
/* 12 */ "Reserved",
/* 13 */ "invalid IE",
/* 14 */ "MIC error",
/* 15 */ "4-way handshake timeout",
/* 16 */ "2-way (group key) handshake timeout",
/* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
/* 18 */
};
#endif
/* since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.*/
/* otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate*/
ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than*/
/* this value, then it's quaranteed capable of operating in 36 mbps TX rate in*/
/* clean environment.*/
/* TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100*/
CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
UCHAR SsidIe = IE_SSID;
UCHAR SupRateIe = IE_SUPP_RATES;
UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
#ifdef DOT11_N_SUPPORT
UCHAR HtCapIe = IE_HT_CAP;
UCHAR AddHtInfoIe = IE_ADD_HT;
UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
UCHAR BssCoexistIe = IE_2040_BSS_COEXIST;
UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
#endif /* DOT11_N_SUPPORT */
UCHAR ExtCapIe = IE_EXT_CAPABILITY;
UCHAR ErpIe = IE_ERP;
UCHAR DsIe = IE_DS_PARM;
UCHAR TimIe = IE_TIM;
UCHAR WpaIe = IE_WPA;
UCHAR Wpa2Ie = IE_WPA2;
UCHAR IbssIe = IE_IBSS_PARM;
UCHAR WapiIe = IE_WAPI;
extern UCHAR WPA_OUI[];
UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
#ifdef CONFIG_STA_SUPPORT
static void periodic_monitor_ac_counter(RTMP_ADAPTER *pAd, UINT32 QId)
{
static BOOLEAN curStat=FALSE;
UINT i = 0;
BOOLEAN isUpdate=TRUE;
if(pAd->RalinkCounters.OneSecOsTxCount[QId]> 500)
{
for(i=0;i<NUM_OF_TX_RING;i++)
{
if(i!=QId && (pAd->RalinkCounters.OneSecOsTxCount[i] > 500))
{
isUpdate = FALSE;
}
}
}else
{
isUpdate = FALSE;
}
/*update AIFS*/
if(!curStat && isUpdate)
{
AsicSetWmmParam(pAd,QId,WMM_PARAM_AIFSN,pAd->CommonCfg.APEdcaParm.Aifsn[QId]+2);
curStat = TRUE;
}else
if(curStat && !isUpdate)
{
AsicSetWmmParam(pAd,QId,WMM_PARAM_AIFSN,pAd->CommonCfg.APEdcaParm.Aifsn[QId]);
curStat = FALSE;
}
}
#endif
#ifdef DYNAMIC_VGA_SUPPORT
void periodic_monitor_false_cca_adjust_vga(RTMP_ADAPTER *pAd)
{
if ((pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable) && (pAd->chipCap.dynamic_vga_support) &&
OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) {
UCHAR val1, val2;
UINT32 bbp_val1, bbp_val2;
RTMP_BBP_IO_READ32(pAd, AGC1_R8, &bbp_val1);
val1 = ((bbp_val1 & (0x00007f00)) >> 8) & 0x7f;
RTMP_BBP_IO_READ32(pAd, AGC1_R9, &bbp_val2);
val2 = ((bbp_val2 & (0x00007f00)) >> 8) & 0x7f;
DBGPRINT(RT_DEBUG_INFO, ("vga_init_0 = %x, vga_init_1 = %x\n", pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0, pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1));
DBGPRINT(RT_DEBUG_INFO,
("one second False CCA=%d, fixed agc_vga_0:0%x, fixed agc_vga_1:0%x\n", pAd->RalinkCounters.OneSecFalseCCACnt, val1, val2));
if (pAd->RalinkCounters.OneSecFalseCCACnt > pAd->CommonCfg.lna_vga_ctl.nFalseCCATh) {
if (val1 > (pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0 - 0x10)) {
val1 -= 0x02;
bbp_val1 = (bbp_val1 & 0xffff80ff) | (val1 << 8);
RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val1);
#ifdef DFS_SUPPORT
pAd->CommonCfg.RadarDetect.bAdjustDfsAgc = TRUE;
#endif
}
if (pAd->CommonCfg.RxStream >= 2) {
if (val2 > (pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1 - 0x10)) {
val2 -= 0x02;
bbp_val2 = (bbp_val2 & 0xffff80ff) | (val2 << 8);
RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val2);
}
}
} else if (pAd->RalinkCounters.OneSecFalseCCACnt <
pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh) {
if (val1 < pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0) {
val1 += 0x02;
bbp_val1 = (bbp_val1 & 0xffff80ff) | (val1 << 8);
RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val1);
#ifdef DFS_SUPPORT
pAd->CommonCfg.RadarDetect.bAdjustDfsAgc = TRUE;
#endif
}
if (pAd->CommonCfg.RxStream >= 2) {
if (val2 < pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1) {
val2 += 0x02;
bbp_val2 = (bbp_val2 & 0xffff80ff) | (val2 << 8);
RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val2);
}
}
}
}
}
#ifdef CONFIG_STA_SUPPORT
void periodic_monitor_rssi_adjust_vga(RTMP_ADAPTER *pAd)
{
UINT32 bbp_val1, bbp_val2;
UCHAR val1, val2;
CHAR Rssi = RTMPAvgRssi(pAd, &pAd->StaCfg.RssiSample);
RTMP_BBP_IO_READ32(pAd, AGC1_R8, &bbp_val1);
RTMP_BBP_IO_READ32(pAd, AGC1_R9, &bbp_val2);
DBGPRINT(RT_DEBUG_INFO, ("vga_init_0 = %x, vga_init_1 = %x\n", pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0, pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1));
if (Rssi > -60) {
val1 = pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0 - 0x20;
bbp_val1 = (bbp_val1 & 0xffff80ff) | (val1 << 8);
bbp_val1 &= ~(0xffff << 16);
bbp_val1 |= ((0x1836) << 16);
RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val1);
val2 = pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1 - 0x20;
bbp_val2 = (bbp_val2 & 0xffff80ff) | (val2 << 8);
bbp_val2 &= ~(0xffff << 16);
bbp_val2 |= ((0x1836) << 16);
RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val2);
} else if ((Rssi >= -75) && (Rssi <= -60)) {
val1 = pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0 - 0x10;
bbp_val1 = (bbp_val1 & 0xffff80ff) | (val1 << 8);
bbp_val1 &= ~(0xffff << 16);
bbp_val1 |= ((pAd->CommonCfg.lna_vga_ctl.agc_0_vga_set1_2 & 0xffff) << 16);
RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val1);
val2 = pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1 - 0x10;
bbp_val2 = (bbp_val2 & 0xffff80ff) | (val2 << 8);
bbp_val2 &= ~(0xffff << 16);
bbp_val2 |= ((pAd->CommonCfg.lna_vga_ctl.agc_1_vga_set1_2 & 0xffff) << 16);
RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val2);
} else {
periodic_monitor_false_cca_adjust_vga(pAd);
bbp_val1 &= ~(0xffff << 16);
bbp_val1 |= ((pAd->CommonCfg.lna_vga_ctl.agc_0_vga_set1_2 & 0xffff) << 16);
bbp_val2 &= ~(0xffff << 16);
bbp_val2 |= ((pAd->CommonCfg.lna_vga_ctl.agc_1_vga_set1_2 & 0xffff) << 16);
}
}
#endif
#endif
#ifdef MT76x2
#ifdef CONFIG_STA_SUPPORT
void periodic_check_channel_smoothing(RTMP_ADAPTER *ad)
{
UINT32 bbp_value;
CHAR Rssi = RTMPAvgRssi(ad, &ad->StaCfg.RssiSample);
if (Rssi < -50) {
if (!ad->chipCap.chl_smth_enable) {
RTMP_BBP_IO_READ32(ad, 0x2948, &bbp_value);
bbp_value &= ~(0x1);
bbp_value |= (0x1);
RTMP_BBP_IO_WRITE32(ad, 0x2948, bbp_value);
RTMP_BBP_IO_READ32(ad, 0x2944, &bbp_value);
bbp_value &= ~(0x1);
RTMP_BBP_IO_WRITE32(ad, 0x2944, bbp_value);
ad->chipCap.chl_smth_enable = TRUE;
}
} else {
if (ad->chipCap.chl_smth_enable) {
RTMP_BBP_IO_READ32(ad, 0x2948, &bbp_value);
bbp_value &= ~(0x1);
RTMP_BBP_IO_WRITE32(ad, 0x2948, bbp_value);
RTMP_BBP_IO_READ32(ad, 0x2944, &bbp_value);
bbp_value &= ~(0x1);
bbp_value |= (0x1);
RTMP_BBP_IO_WRITE32(ad, 0x2944, bbp_value);
ad->chipCap.chl_smth_enable = FALSE;
}
}
}
#endif
#endif
VOID set_default_ap_edca_param(RTMP_ADAPTER *pAd)
{
pAd->CommonCfg.APEdcaParm.bValid = TRUE;
pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3;
pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7;
pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1;
pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1;
pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4;
pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4;
pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3;
pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2;
pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6;
pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10;
pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4;
pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3;
pAd->CommonCfg.APEdcaParm.Txop[0] = 0;
pAd->CommonCfg.APEdcaParm.Txop[1] = 0;
pAd->CommonCfg.APEdcaParm.Txop[2] = 94;
pAd->CommonCfg.APEdcaParm.Txop[3] = 47;
}
#ifdef CONFIG_AP_SUPPORT
VOID set_default_sta_edca_param(RTMP_ADAPTER *pAd)
{
pAd->ApCfg.BssEdcaParm.bValid = TRUE;
pAd->ApCfg.BssEdcaParm.Aifsn[0] = 3;
pAd->ApCfg.BssEdcaParm.Aifsn[1] = 7;
pAd->ApCfg.BssEdcaParm.Aifsn[2] = 2;
pAd->ApCfg.BssEdcaParm.Aifsn[3] = 2;
pAd->ApCfg.BssEdcaParm.Cwmin[0] = 4;
pAd->ApCfg.BssEdcaParm.Cwmin[1] = 4;
pAd->ApCfg.BssEdcaParm.Cwmin[2] = 3;
pAd->ApCfg.BssEdcaParm.Cwmin[3] = 2;
pAd->ApCfg.BssEdcaParm.Cwmax[0] = 10;
pAd->ApCfg.BssEdcaParm.Cwmax[1] = 10;
pAd->ApCfg.BssEdcaParm.Cwmax[2] = 4;
pAd->ApCfg.BssEdcaParm.Cwmax[3] = 3;
pAd->ApCfg.BssEdcaParm.Txop[0] = 0;
pAd->ApCfg.BssEdcaParm.Txop[1] = 0;
pAd->ApCfg.BssEdcaParm.Txop[2] = 94; /*96; */
pAd->ApCfg.BssEdcaParm.Txop[3] = 47; /*48; */
}
#endif /* CONFIG_AP_SUPPORT */
UCHAR dot11_max_sup_rate(INT SupRateLen, UCHAR *SupRate, INT ExtRateLen, UCHAR *ExtRate)
{
INT idx;
UCHAR MaxSupportedRateIn500Kbps = 0;
/* supported rates array may not be sorted. sort it and find the maximum rate */
for (idx = 0; idx < SupRateLen; idx++) {
if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f))
MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f;
}
if (ExtRateLen > 0 && ExtRate != NULL)
{
for (idx = 0; idx < ExtRateLen; idx++) {
if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f))
MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f;
}
}
return MaxSupportedRateIn500Kbps;
}
UCHAR dot11_2_ra_rate(UCHAR MaxSupportedRateIn500Kbps)
{
UCHAR MaxSupportedRate;
switch (MaxSupportedRateIn500Kbps)
{
case 108: MaxSupportedRate = RATE_54; break;
case 96: MaxSupportedRate = RATE_48; break;
case 72: MaxSupportedRate = RATE_36; break;
case 48: MaxSupportedRate = RATE_24; break;
case 36: MaxSupportedRate = RATE_18; break;
case 24: MaxSupportedRate = RATE_12; break;
case 18: MaxSupportedRate = RATE_9; break;
case 12: MaxSupportedRate = RATE_6; break;
case 22: MaxSupportedRate = RATE_11; break;
case 11: MaxSupportedRate = RATE_5_5; break;
case 4: MaxSupportedRate = RATE_2; break;
case 2: MaxSupportedRate = RATE_1; break;
default: MaxSupportedRate = RATE_11; break;
}
return MaxSupportedRate;
}
/*
========================================================================
Routine Description:
Suspend MSDU transmission
Arguments:
pAd Pointer to our adapter
Return Value:
None
Note:
========================================================================
*/
VOID RTMPSuspendMsduTransmission(RTMP_ADAPTER *pAd)
{
DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
#ifdef CONFIG_AP_SUPPORT
#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier */
/* no carrier detection when scanning */
if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
CarrierDetectionStop(pAd);
#endif
#endif /* CONFIG_AP_SUPPORT */
/*
Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
use Lowbound as R66 value on ScanNextChannel(...)
*/
bbp_get_agc(pAd, &pAd->BbpTuning.R66CurrentValue, RX_CHAIN_0);
pAd->hw_cfg.bbp_bw = pAd->CommonCfg.BBPCurrentBW;
RTMPSetAGCInitValue(pAd, BW_20);
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
}
/*
========================================================================
Routine Description:
Resume MSDU transmission
Arguments:
pAd Pointer to our adapter
Return Value:
None
IRQL = DISPATCH_LEVEL
Note:
========================================================================
*/
VOID RTMPResumeMsduTransmission(RTMP_ADAPTER *pAd)
{
DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
#ifdef CONFIG_AP_SUPPORT
#ifdef CARRIER_DETECTION_SUPPORT
/* no carrier detection when scanning*/
if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
CarrierDetectionStart(pAd);
#endif /* CARRIER_DETECTION_SUPPORT */
#endif /* CONFIG_AP_SUPPORT */
/*
After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
R66 should not be 0
*/
if (pAd->BbpTuning.R66CurrentValue == 0)
{
pAd->BbpTuning.R66CurrentValue = 0x38;
DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
}
bbp_set_agc(pAd, pAd->BbpTuning.R66CurrentValue, RX_CHAIN_ALL);
pAd->CommonCfg.BBPCurrentBW = pAd->hw_cfg.bbp_bw;
RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
/* sample, for IRQ LOCK to SEM LOCK */
/*
IrqState = pAd->irq_disabled;
if (IrqState)
RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
else
*/
RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, WCID_ALL, MAX_TX_PROCESS);
}
/*
==========================================================================
Description:
Send out a NULL frame to a specified STA at a higher TX rate. The
purpose is to ensure the designated client is okay to received at this
rate.
==========================================================================
*/
VOID RtmpEnqueueNullFrame(
IN RTMP_ADAPTER *pAd,
IN UCHAR *pAddr,
IN UCHAR TxRate,
IN UCHAR AID,
IN UCHAR apidx,
IN BOOLEAN bQosNull,
IN BOOLEAN bEOSP,
IN UCHAR OldUP)
{
NDIS_STATUS NState;
HEADER_802_11 *pNullFr;
UCHAR *pFrame;
UINT frm_len;
#if 1//defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT)
MAC_TABLE_ENTRY *pEntry;
pEntry = MacTableLookup(pAd, pAddr);
#endif /* DOT11Z_TDLS_SUPPORT */
NState = MlmeAllocateMemory(pAd, (UCHAR **)&pFrame);
pNullFr = (PHEADER_802_11) pFrame;
if (NState == NDIS_STATUS_SUCCESS)
{
frm_len = sizeof(HEADER_802_11);
#ifdef CONFIG_AP_SUPPORT
// IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
if (pEntry && pEntry->wdev->wdev_type == WDEV_TYPE_AP)
{
MgtMacHeaderInit(pAd, pNullFr, SUBTYPE_DATA_NULL, 0, pAddr,
pAd->ApCfg.MBSSID[apidx].wdev.if_addr,
pAd->ApCfg.MBSSID[apidx].wdev.bssid);
pNullFr->FC.ToDs = 0;
pNullFr->FC.FrDs = 1;
goto body;
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd) {
pNullFr->FC.FrDs = 0;
pNullFr->FC.ToDs = 1;
#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT)
if ((pEntry != NULL) && (IS_ENTRY_TDLS(pEntry)))
{
pNullFr->FC.FrDs = 0;
pNullFr->FC.ToDs = 0;
COPY_MAC_ADDR(pNullFr->Addr1, pAddr);
COPY_MAC_ADDR(pNullFr->Addr2, pAd->CurrentAddress);
COPY_MAC_ADDR(pNullFr->Addr3, pAd->CommonCfg.Bssid);
}
#endif /* DOT11Z_TDLS_SUPPORT */
}
#endif /* CONFIG_STA_SUPPORT */
body:
pNullFr->FC.Type = FC_TYPE_DATA;
if (bQosNull)
{
UCHAR *qos_p = ((UCHAR *)pNullFr) + frm_len;
pNullFr->FC.SubType = SUBTYPE_QOS_NULL;
/* copy QOS control bytes */
qos_p[0] = ((bEOSP) ? (1 << 4) : 0) | OldUP;
qos_p[1] = 0;
frm_len += 2;
} else
pNullFr->FC.SubType = SUBTYPE_DATA_NULL;
/* since TxRate may change, we have to change Duration each time */
pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, frm_len);
DBGPRINT(RT_DEBUG_INFO, ("send NULL Frame @%d Mbps to AID#%d...\n", RateIdToMbps[TxRate], AID & 0x3f));
MiniportMMRequest(pAd, WMM_UP2AC_MAP[7], (PUCHAR)pNullFr, frm_len);
MlmeFreeMemory(pAd, pFrame);
}
}
#ifdef CONFIG_AP_SUPPORT
#ifdef APCLI_SUPPORT
VOID ApCliRTMPSendNullFrame(
IN PRTMP_ADAPTER pAd,
IN UCHAR TxRate,
IN BOOLEAN bQosNull,
IN PMAC_TABLE_ENTRY pMacEntry,
IN USHORT PwrMgmt)
{
UCHAR NullFrame[48];
ULONG Length;
HEADER_802_11 *wifi_hdr;
STA_TR_ENTRY *tr_entry;
PAPCLI_STRUCT pApCliEntry = NULL;
struct wifi_dev *wdev;
pApCliEntry = &pAd->ApCfg.ApCliTab[pMacEntry->func_tb_idx];
tr_entry = &pAd->MacTab.tr_entry[pMacEntry->wcid];
wdev = &pApCliEntry->wdev;
/* WPA 802.1x secured port control */
// TODO: shiang-usw, check [wdev/tr_entry]->PortSecured!
if ((wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED) ||
(tr_entry->PortSecured == WPA_802_1X_PORT_NOT_SECURED))
return;
NdisZeroMemory(NullFrame, 48);
Length = sizeof(HEADER_802_11);
wifi_hdr = (HEADER_802_11 *)NullFrame;
wifi_hdr->FC.Type = FC_TYPE_DATA;
wifi_hdr->FC.SubType = SUBTYPE_DATA_NULL;
wifi_hdr->FC.ToDs = 1;
COPY_MAC_ADDR(wifi_hdr->Addr1, pMacEntry->Addr);
#ifdef MAC_REPEATER_SUPPORT
if (pMacEntry && (pMacEntry->bReptCli == TRUE))
COPY_MAC_ADDR(wifi_hdr->Addr2, pMacEntry->ReptCliAddr);
else
#endif /* MAC_REPEATER_SUPPORT */
COPY_MAC_ADDR(wifi_hdr->Addr2, pApCliEntry->wdev.if_addr);
COPY_MAC_ADDR(wifi_hdr->Addr3, pMacEntry->Addr);
if (pAd->CommonCfg.bAPSDForcePowerSave)
wifi_hdr->FC.PwrMgmt = PWR_SAVE;
else
wifi_hdr->FC.PwrMgmt = PwrMgmt;
wifi_hdr->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
/* sequence is increased in MlmeHardTx */
wifi_hdr->Sequence = pAd->Sequence;
pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */
/* Prepare QosNull function frame */
if (bQosNull) {
wifi_hdr->FC.SubType = SUBTYPE_QOS_NULL;
/* copy QOS control bytes */
NullFrame[Length] = 0;
NullFrame[Length + 1] = 0;
Length += 2; /* if pad with 2 bytes for alignment, APSD will fail */
}
HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
}
#endif/*APCLI_SUPPORT*/
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
VOID LowPowerDebug(
IN PRTMP_ADAPTER pAd)
{
DBGPRINT(RT_DEBUG_TRACE, ("\n************ Previous Setting **************************\n"));
DBGPRINT(RT_DEBUG_TRACE, ("%s::pAd->StaCfg.WindowsBatteryPowerMode(%lu)\n", __FUNCTION__, pAd->StaCfg.WindowsBatteryPowerMode));
DBGPRINT(RT_DEBUG_TRACE, ("%s::pAd->StaCfg.WindowsPowerMode(%lu)\n", __FUNCTION__, pAd->StaCfg.WindowsPowerMode));
DBGPRINT(RT_DEBUG_TRACE, ("%s::pAd->CommonCfg.bAPSDForcePowerSave(%d)\n", __FUNCTION__, pAd->CommonCfg.bAPSDForcePowerSave));
DBGPRINT(RT_DEBUG_TRACE, ("%s::fOP_STATUS_DOZE(%d)\n", __FUNCTION__, OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)));
DBGPRINT(RT_DEBUG_TRACE, ("%s::fpAd->StaCfg.PwrMgmt.psm(%d)\n", __FUNCTION__, pAd->StaCfg.PwrMgmt.Psm));
DBGPRINT(RT_DEBUG_TRACE, ("*****************************************************\n\n"));
}
VOID RTMPSendNullFrame(
IN PRTMP_ADAPTER pAd,
IN UCHAR TxRate,
IN BOOLEAN bQosNull,
IN USHORT PwrMgmt)
{
UCHAR NullFrame[48];
ULONG Length;
HEADER_802_11 *wifi_hdr;
//STA_TR_ENTRY *tr_entry;
struct wifi_dev *wdev;
#ifdef CONFIG_ATE
if (ATE_ON(pAd))
return;
#endif /* CONFIG_ATE */
wdev = &pAd->StaCfg.wdev;
/* WPA 802.1x secured port control */
if (wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED)
return;
NdisZeroMemory(NullFrame, 48);
Length = sizeof(HEADER_802_11);
wifi_hdr = (HEADER_802_11 *)NullFrame;
wifi_hdr->FC.Type = FC_TYPE_DATA;
wifi_hdr->FC.SubType = SUBTYPE_DATA_NULL;
wifi_hdr->FC.ToDs = 1;
COPY_MAC_ADDR(wifi_hdr->Addr1, pAd->CommonCfg.Bssid);
COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->CurrentAddress);
COPY_MAC_ADDR(wifi_hdr->Addr3, pAd->CommonCfg.Bssid);
if (pAd->CommonCfg.bAPSDForcePowerSave) {
wifi_hdr->FC.PwrMgmt = PWR_SAVE;
} else {
BOOLEAN FlgCanPmBitSet = TRUE;
#ifdef DOT11Z_TDLS_SUPPORT
/* check TDLS condition */
if (pAd->StaCfg.TdlsInfo.TdlsFlgIsKeepingActiveCountDown == TRUE)
FlgCanPmBitSet = FALSE;
#endif /* DOT11Z_TDLS_SUPPORT */
if (FlgCanPmBitSet == TRUE)
wifi_hdr->FC.PwrMgmt = PwrMgmt;
else
wifi_hdr->FC.PwrMgmt = PWR_ACTIVE;
}
wifi_hdr->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
/* sequence is increased in MlmeHardTx */
wifi_hdr->Sequence = pAd->Sequence;
pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */
/* Prepare QosNull function frame */
if (bQosNull) {
wifi_hdr->FC.SubType = SUBTYPE_QOS_NULL;
/* copy QOS control bytes */
NullFrame[Length] = 0;
NullFrame[Length + 1] = 0;
Length += 2; /* if pad with 2 bytes for alignment, APSD will fail */
}
HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
}
INT32 RTMPSendNullFrameAndWaitStatus(
IN PRTMP_ADAPTER pAd,
IN USHORT PwrMgmt)
{
pAd->cfg80211_ctrl.TxSAcked = 0;
pAd->cfg80211_ctrl.TxStatusInUsed = TRUE;
RTMP_OS_INIT_COMPLETION(&pAd->cfg80211_ctrl.fw_event_done);
RTMPSendNullFrame(pAd,
pAd->CommonCfg.TxRate,
(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE),
PwrMgmt);
return RTMPWaitNullFrameTxDone(pAd);
}
VOID RTMPOffloadPm(RTMP_ADAPTER *pAd, UINT8 ucWlanIdx, UINT8 ucPmNumber, UINT8 ucPmState)
{
//STA_TR_ENTRY *ptr_entry = &pAd->MacTab.tr_entry[ucWlanIdx];
//struct wifi_dev *wdev = &pAd->StaCfg.wdev;
ULONG u4Now;
DBGPRINT(RT_DEBUG_TRACE, ("%s(%d)\n", __FUNCTION__, __LINE__));
LowPowerDebug(pAd);
DBGPRINT(RT_DEBUG_TRACE, ("%s--->::Current setting, ucWlanIdx(%d), ucPmNumber(%d), ucPmState(%d)\n", __FUNCTION__, ucWlanIdx, ucPmNumber, ucPmState));
if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) && (ucPmState == ENTER_PM_STATE))
{
/* H/W enter PM4 offlaod here */
DBGPRINT(RT_DEBUG_TRACE, ("%s::***** H/W Enter PM4 *****\n", __FUNCTION__));
//CmdExtPwrMgtBitWifi(pAd, ucWlanIdx, PWR_SAVE);
CmdExtPmStateCtrl(pAd, ucWlanIdx, ucPmNumber, ucPmState);
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
}
else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) && (ucPmState == EXIT_PM_STATE))
{
/* H/W exit PM4 offlaod here */
DBGPRINT(RT_DEBUG_TRACE, ("%s::***** H/W Exit PM4 *****\n", __FUNCTION__));
NdisGetSystemUpTime(&u4Now);
#ifdef CONFIG_STA_SUPPORT
pAd->StaCfg.LastBeaconRxTime= u4Now;
#endif
//CmdExtPwrMgtBitWifi(pAd, ucWlanIdx, PWR_ACTIVE);
CmdExtPmStateCtrl(pAd, ucWlanIdx, ucPmNumber, ucPmState);
OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
#ifdef RTMP_MAC_USB
/* For USB data Tx path, we use CMD thread to wake up H/W, data might be kicked out before H/W wake up,
we use fOP_STATUS_DOZE to return Tx and resume Tx after clearing flag fOP_STATUS_DOZE*/
RTUSBKickBulkOut(pAd);
#endif /* RTMP_MAC_USB */
DBGPRINT(RT_DEBUG_TRACE, ("%s::Update Beacon time virtually\n", __FUNCTION__));
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):: ***** No Need to handle this. *****\n", __FUNCTION__, __LINE__));
}
DBGPRINT(RT_DEBUG_TRACE, ("%s<---\n", __FUNCTION__));
}
#endif /* CONFIG_STA_SUPPORT */
VOID RtmpPrepareHwNullFrame(
IN PRTMP_ADAPTER pAd,
IN PMAC_TABLE_ENTRY pEntry,
IN BOOLEAN bQosNull,
IN BOOLEAN bEOSP,
IN UCHAR OldUP,
IN UCHAR OpMode,
IN UCHAR PwrMgmt,
IN BOOLEAN bWaitACK,
IN CHAR Index)
{
#if defined(MT7603) || defined(MT7628)
/* nothing to handle */
#else
UINT8 TXWISize = pAd->chipCap.TXWISize;
UCHAR *pNullFrame, *tmac_info = (UCHAR *)&pAd->NullTxWI;
NDIS_STATUS NState;
HEADER_802_11 *pNullFr;
ULONG Length;
UCHAR *ptr;
UINT i;
UINT32 longValue;
#ifdef P2P_SUPPORT
PAPCLI_STRUCT pApCliEntry = NULL;
#endif /* P2P_SUPPORT */
MAC_TX_INFO mac_info;
NState = MlmeAllocateMemory(pAd, (PUCHAR *)&pNullFrame);
NdisZeroMemory(pNullFrame, 48);
NdisZeroMemory(tmac_info, TXWISize);
if (NState == NDIS_STATUS_SUCCESS)
{
pNullFr = (PHEADER_802_11) pNullFrame;
Length = sizeof(HEADER_802_11);
pNullFr->FC.Type = FC_TYPE_DATA;
pNullFr->FC.SubType = SUBTYPE_DATA_NULL;
if (Index == 1)
pNullFr->FC.ToDs = 0;
else
pNullFr->FC.ToDs = 1;
pNullFr->FC.FrDs = 0;
COPY_MAC_ADDR(pNullFr->Addr1, pEntry->Addr);
#ifdef P2P_SUPPORT
if (IS_ENTRY_APCLI(pEntry))
{
pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->func_tb_idx];
COPY_MAC_ADDR(pNullFr->Addr2, pApCliEntry->wdev.if_addr);
COPY_MAC_ADDR(pNullFr->Addr3, pApCliEntry->CfgApCliBssid);
}
else
#endif /* P2P_SUPPORT */
{
COPY_MAC_ADDR(pNullFr->Addr2, pAd->CurrentAddress);
COPY_MAC_ADDR(pNullFr->Addr3, pAd->CommonCfg.Bssid);
}
pNullFr->FC.PwrMgmt = PwrMgmt;
pNullFr->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, pAd->CommonCfg.TxRate, 14);
/* sequence is increased in MlmeHardTx */
pNullFr->Sequence = pAd->Sequence;
pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */
if (bQosNull)
{
UCHAR *qos_p = ((UCHAR *)pNullFr) + Length;
pNullFr->FC.SubType = SUBTYPE_QOS_NULL;
/* copy QOS control bytes */
qos_p[0] = ((bEOSP) ? (1 << 4) : 0) | OldUP;
qos_p[1] = 0;
Length += 2;
}
NdisZeroMemory((UCHAR *)&mac_info, sizeof(mac_info));
mac_info.FRAG = FALSE;
mac_info.CFACK = FALSE;
mac_info.InsTimestamp = FALSE;
mac_info.AMPDU = FALSE;
mac_info.BM = IS_BM_MAC_ADDR(pNullFr->Addr1);
mac_info.Ack = TRUE;
mac_info.NSeq = TRUE;
mac_info.BASize = 0;
mac_info.WCID = (UCHAR)(pEntry->Aid);
mac_info.Length = Length;
mac_info.TID = 0;
mac_info.Txopmode = IFS_HTTXOP;
mac_info.Preamble = LONG_PREAMBLE;
mac_info.SpeEn = 1;
if (Index == 1)
{
HTTRANSMIT_SETTING Transmit;
Transmit.word = pEntry->MaxHTPhyMode.word;
Transmit.field.BW = 0;
if (Transmit.field.MCS > 7)
Transmit.field.MCS = 7;
mac_info.PID = (UCHAR)Transmit.field.MCS;
mac_info.TxRate = (UCHAR)Transmit.field.MCS;
write_tmac_info(pAd, tmac_info, &mac_info, &Transmit);
}
else
{
mac_info.PID = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS;
mac_info.TxRate = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS;
write_tmac_info(pAd, tmac_info, &mac_info,
&pAd->CommonCfg.MlmeTransmit);
}
if (bWaitACK) {
#ifdef RTMP_MAC
if (pAd->chipCap.hif_type == HIF_RTMP) {
TXWI_STRUC *pTxWI = (TXWI_STRUC *)tmac_info;
pTxWI->TXWI_O.TXRPT = 1;
}
#endif /* RTMP_MAC */
#ifdef RLT_MAC
// TODO: shiang, how about RT65xx series??
#ifdef MT7601
if ((pAd->chipCap.hif_type == HIF_RLT) && (IS_MT7601(pAd))) {
TXWI_STRUC *pTxWI = (TXWI_STRUC *)tmac_info;
pTxWI->TXWI_X.TXRPT = 1;
}
#endif /* MT7601 */
#endif /* RLT_MAC */
}
ptr = (PUCHAR)&pAd->NullTxWI;
#ifdef RT_BIG_ENDIAN
RTMPWIEndianChange(pAd, ptr, TYPE_TXWI);
#endif /* RT_BIG_ENDIAN */
for (i=0; i < TXWISize; i+=4)
{
longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24);
if (Index == 0)
RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[0] + i, longValue);
else if (Index == 1)
RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[1] + i, longValue);
ptr += 4;
}
ptr = pNullFrame;
#ifdef RT_BIG_ENDIAN
RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE);
#endif /* RT_BIG_ENDIAN */
for (i= 0; i< Length; i+=4)
{
longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24);
if (Index == 0) //for ra0
RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[0] + TXWISize+ i, longValue);
else if (Index == 1) //for p2p0
RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[1] + TXWISize+ i, longValue);
ptr += 4;
}
}
if (pNullFrame)
MlmeFreeMemory(pAd, pNullFrame);
#endif /* defined(MT7603) || defined(MT7628) */
}
/*
==========================================================================
Description:
main loop of the MLME
Pre:
Mlme has to be initialized, and there are something inside the queue
Note:
This function is invoked from MPSetInformation and MPReceive;
This task guarantee only one FSM will run.
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID MlmeHandler(RTMP_ADAPTER *pAd)
{
MLME_QUEUE_ELEM *Elem = NULL;
#ifdef APCLI_SUPPORT
SHORT apcliIfIndex;
#endif /* APCLI_SUPPORT */
/* Only accept MLME and Frame from peer side, no other (control/data) frame should*/
/* get into this state machine*/
NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
if(pAd->Mlme.bRunning)
{
NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
return;
}
else
{
pAd->Mlme.bRunning = TRUE;
}
NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
{
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) ||
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_SUSPEND))
{
DBGPRINT(RT_DEBUG_TRACE, ("System halted, removed or MlmeRest, exit MlmeTask!(QNum = %ld)\n",
pAd->Mlme.Queue.Num));
break;
}
#ifdef CONFIG_ATE
if(ATE_ON(pAd))
{
DBGPRINT(RT_DEBUG_INFO, ("%s(): Driver is in ATE mode\n", __FUNCTION__));
break;
}
#endif /* CONFIG_ATE */
/*From message type, determine which state machine I should drive*/
if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
{
#ifdef RTMP_MAC_USB
if (Elem->MsgType == MT2_RESET_CONF)
{
DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
#ifdef RT_CFG80211_SUPPORT
if(pAd->cfg80211_ctrl.FlgCfg80211Scanning)
pAd->cfg80211_ctrl.FlgCfg80211Scanning = 0;
CFG80211OS_ScanEnd(pAd->pCfg80211_CB, TRUE);
#endif /* RT_CFG80211_SUPPORT */
MlmeRestartStateMachine(pAd);
Elem->Occupied = FALSE;
Elem->MsgLen = 0;
continue;
}
#endif /* RTMP_MAC_USB */
#if 1 //fix mic error when EAPOL enqueue before linkup
if (Elem->Machine == WPA_STATE_MACHINE && Elem->MsgType == MT2_EAPOLKey)
{
if (((!OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) &&
( !OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)))
#ifdef MESH_SUPPORT
&& !MESH_ON(pAd)
#endif /* MESH_SUPPORT */
#ifdef P2P_SUPPORT
&& !(P2P_GO_ON(pAd) || P2P_CLI_ON(pAd))
#endif /* P2P_SUPPORT */
#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE
&& !(RTMP_CFG80211_VIF_P2P_GO_ON(pAd) || RTMP_CFG80211_VIF_P2P_CLI_ON(pAd))
#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */
)
{
MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
ULONG Tail;
NdisAcquireSpinLock(&(Queue->Lock));
Tail = Queue->Tail;
Queue->Tail++;
Queue->Num++;
if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
Queue->Tail = 0;
Queue->Entry[Tail].Wcid = RESERVED_WCID;
Queue->Entry[Tail].Occupied = TRUE;
Queue->Entry[Tail].Machine = Elem->Machine;
Queue->Entry[Tail].MsgType = Elem->MsgType;
Queue->Entry[Tail].MsgLen = Elem->MsgLen;
Queue->Entry[Tail].Priv = Elem->Priv;
NdisZeroMemory(Queue->Entry[Tail].Msg, MGMT_DMA_BUFFER_SIZE);
if (Elem->Msg != NULL)
{
NdisMoveMemory(Queue->Entry[Tail].Msg, Elem->Msg, Elem->MsgLen);
}
NdisReleaseSpinLock(&(Queue->Lock));
Elem->Occupied = FALSE;
Elem->MsgLen = 0;
continue;
}
}
#endif
/* if dequeue success*/
switch (Elem->Machine)
{
/* STA state machines*/
#ifdef CONFIG_STA_SUPPORT
case ASSOC_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine,
Elem, pAd->Mlme.AssocMachine.CurrState);
break;
case AUTH_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine,
Elem, pAd->Mlme.AuthMachine.CurrState);
break;
case AUTH_RSP_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine,
Elem, pAd->Mlme.AuthRspMachine.CurrState);
break;
case SYNC_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine,
Elem, pAd->Mlme.SyncMachine.CurrState);
break;
case MLME_CNTL_STATE_MACHINE:
MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
break;
case WPA_PSK_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine,
Elem, pAd->Mlme.WpaPskMachine.CurrState);
break;
#ifdef QOS_DLS_SUPPORT
case DLS_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine,
Elem, pAd->Mlme.DlsMachine.CurrState);
break;
#endif /* QOS_DLS_SUPPORT */
#ifdef DOT11R_FT_SUPPORT
case FT_OTA_AUTH_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.FtOtaAuthMachine,
Elem, pAd->Mlme.FtOtaAuthMachine.CurrState);
break;
case FT_OTD_ACT_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.FtOtdActMachine,
Elem, pAd->Mlme.FtOtdActMachine.CurrState);
break;
#endif /* DOT11R_FT_SUPPORT */
#ifdef DOT11Z_TDLS_SUPPORT
case TDLS_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.TdlsMachine,
Elem, pAd->Mlme.TdlsMachine.CurrState);
break;
#endif /* DOT11Z_TDLS_SUPPORT */
#ifdef STA_EASY_CONFIG_SETUP
case AUTO_PROVISION_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.AutoProvisionMachine,
Elem, pAd->Mlme.AutoProvisionMachine.CurrState);
break;
#endif /* STA_EASY_CONFIG_SETUP */
#endif /* CONFIG_STA_SUPPORT */
case ACTION_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine,
Elem, pAd->Mlme.ActMachine.CurrState);
break;
#ifdef CONFIG_AP_SUPPORT
/* AP state amchines*/
case AP_ASSOC_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.ApAssocMachine,
Elem, pAd->Mlme.ApAssocMachine.CurrState);
break;
case AP_AUTH_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.ApAuthMachine,
Elem, pAd->Mlme.ApAuthMachine.CurrState);
break;
case AP_SYNC_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.ApSyncMachine,
Elem, pAd->Mlme.ApSyncMachine.CurrState);
break;
#ifdef APCLI_SUPPORT
case APCLI_AUTH_STATE_MACHINE:
apcliIfIndex = (SHORT)Elem->Priv;
#ifdef MAC_REPEATER_SUPPORT
if (apcliIfIndex >= 64)
apcliIfIndex = ((apcliIfIndex - 64) / 16);
#endif /* MAC_REPEATER_SUPPORT */
if(isValidApCliIf(apcliIfIndex))
{
ULONG AuthCurrState;
#ifdef MAC_REPEATER_SUPPORT
UCHAR CliIdx = 0;
apcliIfIndex = (SHORT)Elem->Priv;
if (apcliIfIndex >= 64)
{
CliIdx = ((apcliIfIndex - 64) % 16);
apcliIfIndex = ((apcliIfIndex - 64) / 16);
AuthCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].RepeaterCli[CliIdx].AuthCurrState;
}
else
#endif /* MAC_REPEATER_SUPPORT */
AuthCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].AuthCurrState;
StateMachinePerformAction(pAd, &pAd->Mlme.ApCliAuthMachine,
Elem, AuthCurrState);
}
break;
case APCLI_ASSOC_STATE_MACHINE:
apcliIfIndex = (SHORT)Elem->Priv;
#ifdef MAC_REPEATER_SUPPORT
if (apcliIfIndex >= 64)
apcliIfIndex = ((apcliIfIndex - 64) / 16);
#endif /* MAC_REPEATER_SUPPORT */
if(isValidApCliIf(apcliIfIndex))
{
ULONG AssocCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].AssocCurrState;
#ifdef MAC_REPEATER_SUPPORT
UCHAR CliIdx = 0;
apcliIfIndex = (SHORT)Elem->Priv;
if (apcliIfIndex >= 64)
{
CliIdx = ((apcliIfIndex - 64) % 16);
apcliIfIndex = ((apcliIfIndex - 64) / 16);
AssocCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].RepeaterCli[CliIdx].AssocCurrState;
}
#endif /* MAC_REPEATER_SUPPORT */
StateMachinePerformAction(pAd, &pAd->Mlme.ApCliAssocMachine,
Elem, AssocCurrState);
}
break;
case APCLI_SYNC_STATE_MACHINE:
apcliIfIndex = (SHORT)Elem->Priv;
if(isValidApCliIf(apcliIfIndex))
StateMachinePerformAction(pAd, &pAd->Mlme.ApCliSyncMachine, Elem,
(pAd->ApCfg.ApCliTab[apcliIfIndex].SyncCurrState));
break;
case APCLI_CTRL_STATE_MACHINE:
apcliIfIndex = (SHORT)Elem->Priv;
#ifdef MAC_REPEATER_SUPPORT
if (apcliIfIndex >= 64)
apcliIfIndex = ((apcliIfIndex - 64) / 16);
#endif /* MAC_REPEATER_SUPPORT */
if(isValidApCliIf(apcliIfIndex))
{
ULONG CtrlCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].CtrlCurrState;
#ifdef MAC_REPEATER_SUPPORT
UCHAR CliIdx = 0;
apcliIfIndex = (SHORT)Elem->Priv;
if (apcliIfIndex >= 64)
{
CliIdx = ((apcliIfIndex - 64) % 16);
apcliIfIndex = ((apcliIfIndex - 64) / 16);
CtrlCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].RepeaterCli[CliIdx].CtrlCurrState;
}
#endif /* MAC_REPEATER_SUPPORT */
StateMachinePerformAction(pAd, &pAd->Mlme.ApCliCtrlMachine, Elem, CtrlCurrState);
}
break;
#endif /* APCLI_SUPPORT */
#endif /* CONFIG_AP_SUPPORT */
case WPA_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.WpaMachine, Elem, pAd->Mlme.WpaMachine.CurrState);
break;
#ifdef WSC_INCLUDED
case WSC_STATE_MACHINE:
#if 1
if (pAd->pWscElme)
{
RTMP_SEM_LOCK(&pAd->WscElmeLock);
NdisMoveMemory(pAd->pWscElme, Elem, sizeof(MLME_QUEUE_ELEM));
RTMP_SEM_UNLOCK(&pAd->WscElmeLock);
RtmpOsTaskWakeUp(&(pAd->wscTask));
}
#else
WpsSmProcess(pAd, Elem);
#endif
break;
#ifdef IWSC_SUPPORT
case IWSC_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.IWscMachine, Elem, pAd->Mlme.IWscMachine.CurrState);
break;
#endif /* IWSC_SUPPORT */
#endif /* WSC_INCLUDED */
#ifdef MESH_SUPPORT
case MESH_CTRL_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.MeshCtrlMachine, Elem,
pAd->MeshTab.CtrlCurrentState);
break;
case MESH_LINK_MNG_STATE_MACHINE:
if (VALID_MESH_LINK_ID(Elem->Priv))
StateMachinePerformAction(pAd, &pAd->Mlme.MeshLinkMngMachine, Elem,
pAd->MeshTab.MeshLink[Elem->Priv].CurrentState);
break;
#endif /* MESH_SUPPORT */
#ifdef P2P_SUPPORT
case P2P_CTRL_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->P2pCfg.P2PCtrlMachine, Elem,
pAd->P2pCfg.CtrlCurrentState);
break;
case P2P_DISC_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->P2pCfg.P2PDiscMachine, Elem,
pAd->P2pCfg.DiscCurrentState);
break;
case P2P_GO_FORM_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->P2pCfg.P2PGoFormMachine, Elem,
pAd->P2pCfg.GoFormCurrentState);
break;
case P2P_ACTION_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->P2pCfg.P2PActionMachine, Elem,
pAd->P2pCfg.ActionState);
break;
#endif /* P2P_SUPPORT */
#ifdef CONFIG_HOTSPOT
case HSCTRL_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.HSCtrlMachine, Elem,
HSCtrlCurrentState(pAd, Elem));
break;
#endif
#ifdef CONFIG_DOT11U_INTERWORKING
case GAS_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.GASMachine, Elem,
GASPeerCurrentState(pAd, Elem));
break;
#endif
#ifdef CONFIG_DOT11V_WNM
case BTM_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.BTMMachine, Elem,
BTMPeerCurrentState(pAd, Elem));
break;
#ifdef CONFIG_HOTSPOT_R2
case WNM_NOTIFY_STATE_MACHINE:
StateMachinePerformAction(pAd, &pAd->Mlme.WNMNotifyMachine, Elem,
WNMNotifyPeerCurrentState(pAd, Elem));
break;
#endif
#endif
default:
DBGPRINT(RT_DEBUG_TRACE, ("%s(): Illegal SM %ld\n",
__FUNCTION__, Elem->Machine));
break;
} /* end of switch*/
/* free MLME element*/
Elem->Occupied = FALSE;
Elem->MsgLen = 0;
}
else {
DBGPRINT_ERR(("%s(): MlmeQ empty\n", __FUNCTION__));
}
}
NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
pAd->Mlme.bRunning = FALSE;
NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
}
/*
========================================================================
Routine Description:
MLME kernel thread.
Arguments:
Context the pAd, driver control block pointer
Return Value:
0 close the thread
Note:
========================================================================
*/
static INT MlmeThread(ULONG Context)
{
RTMP_ADAPTER *pAd;
RTMP_OS_TASK *pTask;
int status;
status = 0;
pTask = (RTMP_OS_TASK *)Context;
pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask);
if (pAd == NULL)
goto LabelExit;
RtmpOSTaskCustomize(pTask);
while (!RTMP_OS_TASK_IS_KILLED(pTask))
{
if (RtmpOSTaskWait(pAd, pTask, &status) == FALSE)
{
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
break;
}
/* lock the device pointers , need to check if required*/
/*down(&(pAd->usbdev_semaphore)); */
if (!pAd->PM_FlgSuspend)
MlmeHandler(pAd);
}
/* notify the exit routine that we're actually exiting now
*
* complete()/wait_for_completion() is similar to up()/down(),
* except that complete() is safe in the case where the structure
* is getting deleted in a parallel mode of execution (i.e. just
* after the down() -- that's necessary for the thread-shutdown
* case.
*
* complete_and_exit() goes even further than this -- it is safe in
* the case that the thread of the caller is going away (not just
* the structure) -- this is necessary for the module-remove case.
* This is important in preemption kernels, which transfer the flow
* of execution immediately upon a complete().
*/
LabelExit:
DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__));
RtmpOSTaskNotifyToExit(pTask);
return 0;
}
#ifdef CONFIG_AP_SUPPORT
#ifdef APCLI_SUPPORT
static VOID ApCliMlmeInit(RTMP_ADAPTER *pAd)
{
/* init apcli state machines*/
ASSERT(APCLI_AUTH_FUNC_SIZE == APCLI_MAX_AUTH_MSG * APCLI_MAX_AUTH_STATE);
ApCliAuthStateMachineInit(pAd, &pAd->Mlme.ApCliAuthMachine, pAd->Mlme.ApCliAuthFunc);
ASSERT(APCLI_ASSOC_FUNC_SIZE == APCLI_MAX_ASSOC_MSG * APCLI_MAX_ASSOC_STATE);
ApCliAssocStateMachineInit(pAd, &pAd->Mlme.ApCliAssocMachine, pAd->Mlme.ApCliAssocFunc);
ASSERT(APCLI_SYNC_FUNC_SIZE == APCLI_MAX_SYNC_MSG * APCLI_MAX_SYNC_STATE);
ApCliSyncStateMachineInit(pAd, &pAd->Mlme.ApCliSyncMachine, pAd->Mlme.ApCliSyncFunc);
ASSERT(APCLI_CTRL_FUNC_SIZE == APCLI_MAX_CTRL_MSG * APCLI_MAX_CTRL_STATE);
ApCliCtrlStateMachineInit(pAd, &pAd->Mlme.ApCliCtrlMachine, pAd->Mlme.ApCliCtrlFunc);
}
#endif /* APCLI_SUPPORT */
static VOID ApMlmeInit(RTMP_ADAPTER *pAd)
{
/* init AP state machines*/
APAssocStateMachineInit(pAd, &pAd->Mlme.ApAssocMachine, pAd->Mlme.ApAssocFunc);
APAuthStateMachineInit(pAd, &pAd->Mlme.ApAuthMachine, pAd->Mlme.ApAuthFunc);
APSyncStateMachineInit(pAd, &pAd->Mlme.ApSyncMachine, pAd->Mlme.ApSyncFunc);
}
#endif /* CONFIG_AP_SUPPORT */
/*
==========================================================================
Description:
initialize the MLME task and its data structure (queue, spinlock,
timer, state machines).
IRQL = PASSIVE_LEVEL
Return:
always return NDIS_STATUS_SUCCESS
==========================================================================
*/
NDIS_STATUS MlmeInit(RTMP_ADAPTER *pAd)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
do
{
Status = MlmeQueueInit(pAd, &pAd->Mlme.Queue);
if(Status != NDIS_STATUS_SUCCESS)
break;
pAd->Mlme.bRunning = FALSE;
NdisAllocateSpinLock(pAd, &pAd->Mlme.TaskLock);
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
BssTableInit(&pAd->ScanTab);
/* init STA state machines*/
AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
#ifdef QOS_DLS_SUPPORT
DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc);
#endif /* QOS_DLS_SUPPORT */
#ifdef DOT11Z_TDLS_SUPPORT
TDLS_StateMachineInit(pAd, &pAd->Mlme.TdlsMachine, pAd->Mlme.TdlsFunc);
#endif /* DOT11Z_TDLS_SUPPORT */
#ifdef WSC_STA_SUPPORT
#ifdef IWSC_SUPPORT
IWSC_StateMachineInit(pAd, &pAd->Mlme.IWscMachine, pAd->Mlme.IWscFunc);
#endif /* IWSC_SUPPORT */
#endif /* WSC_STA_SUPPORT */
#ifdef DOT11R_FT_SUPPORT
FT_OTA_AuthStateMachineInit(pAd, &pAd->Mlme.FtOtaAuthMachine, pAd->Mlme.FtOtaAuthFunc);
FT_OTD_StateMachineInit(pAd, &pAd->Mlme.FtOtdActMachine, pAd->Mlme.FtOtdActFunc);
#endif /* DOT11R_FT_SUPPORT */
#ifdef STA_EASY_CONFIG_SETUP
AutoProvisionStateMachineInit(pAd, &pAd->Mlme.AutoProvisionMachine, pAd->Mlme.AutoProvisionFunc);
#endif /* STA_EASY_CONFIG_SETUP */
/* Since we are using switch/case to implement it, the init is different from the above */
/* state machine init*/
MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
#ifdef PCIE_PS_SUPPORT
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
{
/* only PCIe cards need these two timers*/
RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
}
#endif /* PCIE_PS_SUPPORT */
RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer, GET_TIMER_FUNCTION(LinkDownExec), pAd, FALSE);
RTMPInitTimer(pAd, &pAd->StaCfg.StaQuickResponeForRateUpTimer, GET_TIMER_FUNCTION(StaQuickResponeForRateUpExec), pAd, FALSE);
pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
RTMPInitTimer(pAd, &pAd->StaCfg.WpaDisassocAndBlockAssocTimer, GET_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc), pAd, FALSE);
#ifdef RTMP_MAC_USB
RTMPInitTimer(pAd, &pAd->Mlme.AutoWakeupTimer, GET_TIMER_FUNCTION(RtmpUsbStaAsicForceWakeupTimeout), pAd, FALSE);
pAd->Mlme.AutoWakeupTimerRunning = FALSE;
#endif /* RTMP_MAC_USB */
#ifdef STA_EASY_CONFIG_SETUP
RTMPInitTimer(pAd,
&pAd->StaCfg.EasyConfigInfo.ScanTimer,
GET_TIMER_FUNCTION(AutoProvisionScanTimeOutAction),
pAd,
FALSE);
RTMPInitTimer(pAd,
&pAd->StaCfg.EasyConfigInfo.InfraConnTimer,
GET_TIMER_FUNCTION(InfraConnectionTimeout),
pAd,
FALSE);
RTMPInitTimer(pAd,
&pAd->StaCfg.EasyConfigInfo.AdhocConnTimer,
GET_TIMER_FUNCTION(AdhocConnectionTimeout),
pAd,
FALSE);
#endif /* STA_EASY_CONFIG_SETUP */
}
#endif /* CONFIG_STA_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
ApMlmeInit(pAd);
#ifdef APCLI_SUPPORT
ApCliMlmeInit(pAd);
#endif /* APCLI_SUPPORT */
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef WSC_INCLUDED
/* Init Wsc state machine */
ASSERT(WSC_FUNC_SIZE == MAX_WSC_MSG * MAX_WSC_STATE);
WscStateMachineInit(pAd, &pAd->Mlme.WscMachine, pAd->Mlme.WscFunc);
#endif /* WSC_INCLUDED */
WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine, pAd->Mlme.WpaFunc);
#ifdef CONFIG_HOTSPOT
HSCtrlStateMachineInit(pAd, &pAd->Mlme.HSCtrlMachine, pAd->Mlme.HSCtrlFunc);
GASStateMachineInit(pAd, &pAd->Mlme.GASMachine, pAd->Mlme.GASFunc);
#endif
#ifdef CONFIG_DOT11V_WNM
WNMCtrlInit(pAd);
BTMStateMachineInit(pAd, &pAd->Mlme.BTMMachine, pAd->Mlme.BTMFunc);
#ifdef CONFIG_HOTSPOT_R2
WNMNotifyStateMachineInit(pAd, &pAd->Mlme.WNMNotifyMachine, pAd->Mlme.WNMNotifyFunc);
#endif
#endif
#ifdef MESH_SUPPORT
ASSERT(MESH_CTRL_FUNC_SIZE == MESH_CTRL_MAX_EVENTS * MESH_CTRL_MAX_STATES);
MeshCtrlStateMachineInit(pAd, &pAd->Mlme.MeshCtrlMachine, pAd->Mlme.MeshCtrlFunc);
ASSERT(MESH_LINK_MNG_FUNC_SIZE == MESH_LINK_MNG_MAX_EVENTS * MESH_LINK_MNG_MAX_STATES);
MeshLinkMngStateMachineInit(pAd, &pAd->Mlme.MeshLinkMngMachine, pAd->Mlme.MeshLinkMngFunc);
#endif /* MESH_SUPPORT */
ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
/* Init mlme periodic timer*/
RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExecTimer), pAd, TRUE);
/* Set mlme periodic timer*/
RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
/* software-based RX Antenna diversity*/
RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
/* Init APSD periodic timer*/
RTMPInitTimer(pAd, &pAd->Mlme.APSDPeriodicTimer, GET_TIMER_FUNCTION(APSDPeriodicExec), pAd, TRUE);
RTMPSetTimer(&pAd->Mlme.APSDPeriodicTimer, 50);
/* Init APQuickResponseForRateUp timer.*/
RTMPInitTimer(pAd, &pAd->ApCfg.ApQuickResponeForRateUpTimer, GET_TIMER_FUNCTION(APQuickResponeForRateUpExec), pAd, FALSE);
pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = FALSE;
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef P2P_SUPPORT
/* P2P Ctrl State Machine */
ASSERT(P2P_CTRL_FUNC_SIZE == P2P_CTRL_MAX_EVENTS * P2P_CTRL_MAX_STATES);
P2PCtrlStateMachineInit(pAd, &pAd->P2pCfg.P2PCtrlMachine, pAd->P2pCfg.P2PCtrlFunc);
/* P2P Discovery State Machine */
ASSERT(P2P_DISC_FUNC_SIZE == P2P_DISC_MAX_EVENTS * P2P_DISC_MAX_STATES);
P2PDiscoveryStateMachineInit(pAd, &pAd->P2pCfg.P2PDiscMachine, pAd->P2pCfg.P2PDiscFunc);
/* P2P Group Formation State Machine */
ASSERT(P2P_GO_FORM_FUNC_SIZE == P2P_GO_NEGO_MAX_EVENTS * P2P_GO_FORM_MAX_STATES);
P2PGoFormationStateMachineInit(pAd, &pAd->P2pCfg.P2PGoFormMachine, pAd->P2pCfg.P2PGoFormFunc);
/* P2P Action Frame State Machine */
ASSERT(P2P_ACTION_FUNC_SIZE == MAX_P2P_MSG * MAX_P2P_STATE);
P2PStateMachineInit(pAd, &pAd->P2pCfg.P2PActionMachine, pAd->P2pCfg.P2PActionFunc);
/* P2P CTWindows timer */
RTMPInitTimer(pAd, &pAd->P2pCfg.P2pCTWindowTimer, GET_TIMER_FUNCTION(P2PCTWindowTimer), pAd, FALSE);
/* P2P SwNOA timer */
RTMPInitTimer(pAd, &pAd->P2pCfg.P2pSwNoATimer, GET_TIMER_FUNCTION(P2pSwNoATimeOut), pAd, FALSE);
/* P2P Presence Absent timer */
RTMPInitTimer(pAd, &pAd->P2pCfg.P2pPreAbsenTimer, GET_TIMER_FUNCTION(P2pPreAbsenTimeOut), pAd, FALSE);
/* P2P WSC Timer */
RTMPInitTimer(pAd, &pAd->P2pCfg.P2pWscTimer, GET_TIMER_FUNCTION(P2pWscTimeOut), pAd, FALSE);
/* P2P Re-Transmit Action Frame Timer */
RTMPInitTimer(pAd, &pAd->P2pCfg.P2pReSendTimer, GET_TIMER_FUNCTION(P2pReSendTimeOut), pAd, FALSE);
/* P2P CLIENT Re-Connect Timer */
RTMPInitTimer(pAd, &pAd->P2pCfg.P2pCliReConnectTimer, GET_TIMER_FUNCTION(P2pCliReConnectTimeOut), pAd, FALSE);
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
ApMlmeInit(pAd);
#ifdef APCLI_SUPPORT
ApCliMlmeInit(pAd);
#endif /* APCLI_SUPPORT */
/* Init APSD periodic timer */
RTMPInitTimer(pAd, &pAd->Mlme.APSDPeriodicTimer, GET_TIMER_FUNCTION(APSDPeriodicExec), pAd, TRUE);
RTMPSetTimer(&pAd->Mlme.APSDPeriodicTimer, 50);
}
#endif /* CONFIG_STA_SUPPORT */
#endif /* P2P_SUPPORT */
#if defined(RT_CFG80211_P2P_SUPPORT) || defined(CFG80211_MULTI_STA)
/*CFG_TODO*/
ApMlmeInit(pAd);
#if defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) || defined(CFG80211_MULTI_STA)
ApCliMlmeInit(pAd);
#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE || CFG80211_MULTI_STA */
#endif /* RT_CFG80211_P2P_SUPPORT || CFG80211_MULTI_STA */
} while (FALSE);
{
RTMP_OS_TASK *pTask;
/* Creat MLME Thread */
pTask = &pAd->mlmeTask;
RTMP_OS_TASK_INIT(pTask, "RtmpMlmeTask", pAd);
Status = RtmpOSTaskAttach(pTask, MlmeThread, (ULONG)pTask);
if (Status == NDIS_STATUS_FAILURE) {
DBGPRINT (RT_DEBUG_ERROR, ("%s: unable to start MlmeThread\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev)));
}
}
DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
return Status;
}
/*
==========================================================================
Description:
Destructor of MLME (Destroy queue, state machine, spin lock and timer)
Parameters:
Adapter - NIC Adapter pointer
Post:
The MLME task will no longer work properly
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID MlmeHalt(RTMP_ADAPTER *pAd)
{
BOOLEAN Cancelled;
RTMP_OS_TASK *pTask;
DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
/* Terminate Mlme Thread */
pTask = &pAd->mlmeTask;
if (RtmpOSTaskKill(pTask) == NDIS_STATUS_FAILURE) {
DBGPRINT(RT_DEBUG_ERROR, ("kill mlme task failed!\n"));
}
#if (defined(MT_WOW_SUPPORT) && defined(WOW_IFDOWN_SUPPORT))
if (!((pAd->WOW_Cfg.bEnable == TRUE) && INFRA_ON(pAd)))
#endif
if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
{
/* disable BEACON generation and other BEACON related hardware timers*/
AsicDisableSync(pAd);
}
#ifdef MT76XX_BTCOEX_SUPPORT
if (IS_MT76XXBTCOMBO(pAd))
{
BtAFHCtl(pAd, pAd->CommonCfg.BBPCurrentBW, pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel, TRUE);
SendAndesAFH(pAd, pAd->CommonCfg.BBPCurrentBW, pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel, TRUE, 0);
}
#endif /*MT76XX_BTCOEX_SUPPORT*/
RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
#ifdef QOS_DLS_SUPPORT
UCHAR i;
#endif /* QOS_DLS_SUPPORT */
/* Cancel pending timers*/
RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
#ifdef DOT11R_FT_SUPPORT
RTMPCancelTimer(&pAd->MlmeAux.FtOtaAuthTimer, &Cancelled);
RTMPCancelTimer(&pAd->MlmeAux.FtOtdActTimer, &Cancelled);
#endif /* DOT11R_FT_SUPPORT */
#ifdef PCIE_PS_SUPPORT
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)
&&(pAd->StaCfg.PSControl.field.EnableNewPS == TRUE))
{
RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
}
#endif /* PCIE_PS_SUPPORT */
#ifdef QOS_DLS_SUPPORT
for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
{
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
}
#endif /* QOS_DLS_SUPPORT */
RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled);
#ifdef RTMP_MAC_USB
if (pAd->Mlme.AutoWakeupTimerRunning)
{
RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Cancelled);
pAd->Mlme.AutoWakeupTimerRunning = FALSE;
}
#endif /* RTMP_MAC_USB */
#ifdef WSC_STA_SUPPORT
if (pAd->StaCfg.WscControl.WscProfileRetryTimerRunning)
{
pAd->StaCfg.WscControl.WscProfileRetryTimerRunning = FALSE;
RTMPCancelTimer(&pAd->StaCfg.WscControl.WscProfileRetryTimer, &Cancelled);
}
#endif /* WSC_STA_SUPPORT */
#ifdef STA_EASY_CONFIG_SETUP
RTMPCancelTimer(&pAd->StaCfg.EasyConfigInfo.InfraConnTimer, &Cancelled);
RTMPCancelTimer(&pAd->StaCfg.EasyConfigInfo.AdhocConnTimer, &Cancelled);
RTMPCancelTimer(&pAd->StaCfg.EasyConfigInfo.ScanTimer, &Cancelled);
#endif /* STA_EASY_CONFIG_SETUP */
if (pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
{
RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, &Cancelled);
pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
}
RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, &Cancelled);
#ifdef IWSC_SUPPORT
RTMPCancelTimer(&pAd->StaCfg.IWscInfo.IWscT1Timer, &Cancelled);
RTMPCancelTimer(&pAd->StaCfg.IWscInfo.IWscT2Timer, &Cancelled);
#endif /* IWSC_SUPPORT */
}
#endif /* CONFIG_STA_SUPPORT */
RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
#ifdef BT_COEXISTENCE_SUPPORT
if ((pAd->bHWCoexistenceInit == TRUE) && IS_ENABLE_MISC_TIMER(pAd))
{
RTMPCancelTimer(&pAd->Mlme.MiscDetectTimer,&Cancelled);
}
#endif /* BT_COEXISTENCE_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
#ifdef APCLI_SUPPORT
UCHAR idx = 0;
#endif /* APCLI_SUPPORT */
RTMPCancelTimer(&pAd->Mlme.APSDPeriodicTimer, &Cancelled);
if (pAd->ApCfg.ApQuickResponeForRateUpTimerRunning == TRUE)
RTMPCancelTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, &Cancelled);
#ifdef APCLI_SUPPORT
for (idx = 0; idx < MAX_APCLI_NUM; idx++)
{
PAPCLI_STRUCT pApCliEntry = &pAd->ApCfg.ApCliTab[idx];
RTMPCancelTimer(&pApCliEntry->MlmeAux.ProbeTimer, &Cancelled);
RTMPCancelTimer(&pApCliEntry->MlmeAux.ApCliAssocTimer, &Cancelled);
RTMPCancelTimer(&pApCliEntry->MlmeAux.ApCliAuthTimer, &Cancelled);
#ifdef WSC_AP_SUPPORT
if (pApCliEntry->WscControl.WscProfileRetryTimerRunning)
{
pApCliEntry->WscControl.WscProfileRetryTimerRunning = FALSE;
RTMPCancelTimer(&pApCliEntry->WscControl.WscProfileRetryTimer, &Cancelled);
}
#endif /* WSC_AP_SUPPORT */
}
#endif /* APCLI_SUPPORT */
RTMPCancelTimer(&pAd->ScanCtrl.APScanTimer, &Cancelled);
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef MESH_SUPPORT
MeshHalt(pAd);
#endif /* MESH_SUPPORT */
#ifdef CONFIG_HOTSPOT
HSCtrlHalt(pAd);
HSCtrlExit(pAd);
#endif
#ifdef CONFIG_DOT11U_INTERWORKING
GASCtrlExit(pAd);
#endif
#ifdef CONFIG_DOT11V_WNM
WNMCtrlExit(pAd);
#endif
#ifdef P2P_SUPPORT
/* P2P CTWindows timer */
RTMPCancelTimer(&pAd->P2pCfg.P2pCTWindowTimer, &Cancelled);
/* P2P SwNOA timer */
RTMPCancelTimer(&pAd->P2pCfg.P2pSwNoATimer, &Cancelled);
/* P2P Presence Absent timer */
RTMPCancelTimer(&pAd->P2pCfg.P2pPreAbsenTimer, &Cancelled);
if (pAd->P2pCfg.bP2pCliReConnectTimerRunning)
{
pAd->P2pCfg.bP2pCliReConnectTimerRunning = FALSE;
RTMPCancelTimer(&pAd->P2pCfg.P2pCliReConnectTimer, &Cancelled);
}
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
RTMPCancelTimer(&pAd->Mlme.APSDPeriodicTimer, &Cancelled);
RTMPCancelTimer(&pAd->ApCfg.ApCliTab[0].MlmeAux.ProbeTimer, &Cancelled);
RTMPCancelTimer(&pAd->ApCfg.ApCliTab[0].MlmeAux.ApCliAssocTimer, &Cancelled);
RTMPCancelTimer(&pAd->ApCfg.ApCliTab[0].MlmeAux.ApCliAuthTimer, &Cancelled);
#ifdef WSC_AP_SUPPORT
if (pAd->ApCfg.ApCliTab[BSS0].WscControl.WscProfileRetryTimerRunning)
{
pAd->ApCfg.ApCliTab[BSS0].WscControl.WscProfileRetryTimerRunning = FALSE;
RTMPCancelTimer(&pAd->ApCfg.ApCliTab[BSS0].WscControl.WscProfileRetryTimer, &Cancelled);
}
#endif /* WSC_AP_SUPPORT */
RTMPCancelTimer(&pAd->ScanCtrl.APScanTimer, &Cancelled);
}
#endif /* P2P_SUPPORT */
if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
{
RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
#ifdef LED_CONTROL_SUPPORT
/* Set LED*/
RTMPSetLED(pAd, LED_HALT);
RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, firmware is not done it.*/
#ifdef RTMP_MAC_USB
#ifdef RLT_MAC
// TODO: shiang-7603
if (pAd->chipCap.hif_type != HIF_MT)
{
LED_CFG_STRUC LedCfg;
RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
LedCfg.field.LedPolar = 0;
LedCfg.field.RLedMode = 0;
LedCfg.field.GLedMode = 0;
LedCfg.field.YLedMode = 0;
RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
}
#endif
#endif /* RTMP_MAC_USB */
#endif /* LED_CONTROL_SUPPORT */
#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(MT_WOW_SUPPORT)
if (!(pAd->WOW_Cfg.bEnable == TRUE) && INFRA_ON(pAd))
#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(MT_WOW_SUPPORT)*/
if (pChipOps->AsicHaltAction)
pChipOps->AsicHaltAction(pAd);
}
RtmpusecDelay(5000); /* 5 msec to gurantee Ant Diversity timer canceled*/
MlmeQueueDestroy(&pAd->Mlme.Queue);
NdisFreeSpinLock(&pAd->Mlme.TaskLock);
DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
}
VOID MlmeResetRalinkCounters(RTMP_ADAPTER *pAd)
{
pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
#ifdef CONFIG_ATE
if (!ATE_ON(pAd))
#endif /* CONFIG_ATE */
/* for performace enchanement */
NdisZeroMemory(&pAd->RalinkCounters,
((ULONG)&pAd->RalinkCounters.OneSecEnd -
(ULONG)&pAd->RalinkCounters.OneSecStart));
return;
}
/*
==========================================================================
Description:
This routine is executed periodically to -
1. Decide if it's a right time to turn on PwrMgmt bit of all
outgoiing frames
2. Calculate ChannelQuality based on statistics of the last
period, so that TX rate won't toggling very frequently between a
successful TX and a failed TX.
3. If the calculated ChannelQuality indicated current connection not
healthy, then a ROAMing attempt is tried here.
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID MlmePeriodicExecTimer(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
RTEnqueueInternalCmd(pAd, CMDTHREAD_MLME_PERIOIDC_EXEC, NULL, 0);
}
NTSTATUS MlmePeriodicExec(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
{
ULONG TxTotalCnt;
ULONG TxTotalByteCnt = 0, RxTotalByteCnt = 0;
//RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
#ifdef ANT_DIVERSITY_SUPPORT
SHORT realavgrssi;
#endif /* ANT_DIVERSITY_SUPPORT */
/* No More 0x84 MCU CMD from v.30 FW*/
#if 0
#ifdef RTMP_MAC_PCI
#ifdef CONFIG_STA_SUPPORT
#ifdef RT30xx
/* not for USB device!*/
/* FWv.18 and after needs the timer tick command every 200 ms*/
/* LedMode = 0 : Slow Blink, Fast blink, light all normal. So need to set 0x84 software timer command.*/
if ((IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3593(pAd)) &&
(pAd->Mlme.PeriodicRound % 2 == 0) &&
(pAd->StaCfg.PSControl.field.LedMode == 0) &&
(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
{
AsicSendCommandToMcu(pAd, 0x84, 0xff, 0xff, 0xff, FALSE);
}
#endif /* RT30xx */
#endif /* CONFIG_STA_SUPPORT */
#endif /* RTMP_MAC_PCI */
#endif /* 0 */
//CFG
#if 0
if(!pAd->cfg80211_ctrl.isMccOn)
{
BOOLEAN Mcc_side1 = FALSE, Mcc_side2 = FALSE;
if(INFRA_ON(pAd) && (pAd->StaCfg.wdev.PortSecured == WPA_802_1X_PORT_SECURED))
{
//printk("INFRA SIDE: ==================================> on \n");
Mcc_side1 = TRUE;
}
if((pAd->ApCfg.ApCliTab[0].CtrlCurrState == APCLI_CTRL_CONNECTED) &&
(pAd->ApCfg.ApCliTab[0].wdev.PortSecured == WPA_802_1X_PORT_SECURED))
{
//printk("P2P_GC SIDE: ==================================> on \n");
Mcc_side2 = TRUE;
}
if (Mcc_side1 && Mcc_side2 && (!pAd->cfg80211_ctrl.isMccOn))
{
printk("MCC: ==================================> on \n");
CMD_MCC_START_PARM mccStartParm;
mccStartParm.channel_1st=pAd->CommonCfg.Channel;
mccStartParm.channel_2nd=pAd->ApCfg.ApCliTab[0].MlmeAux.Channel;
pAd->cfg80211_ctrl.isMccOn = TRUE;
CmdMccStart(pAd, &mccStartParm);
}
}
#endif
#ifdef MICROWAVE_OVEN_SUPPORT
/* update False CCA count to an array */
NICUpdateRxStatusCnt1(pAd, pAd->Mlme.PeriodicRound%10);
if (pAd->CommonCfg.MO_Cfg.bEnable)
{
UINT8 stage = pAd->Mlme.PeriodicRound%10;
if (stage == MO_MEAS_PERIOD)
{
ASIC_MEASURE_FALSE_CCA(pAd);
pAd->CommonCfg.MO_Cfg.nPeriod_Cnt = 0;
}
else if (stage == MO_IDLE_PERIOD)
{
UINT16 Idx;
for (Idx = MO_MEAS_PERIOD + 1; Idx < MO_IDLE_PERIOD + 1; Idx++)
pAd->CommonCfg.MO_Cfg.nFalseCCACnt += pAd->RalinkCounters.FalseCCACnt_100MS[Idx];
//printk("%s: fales cca1 %d\n", __FUNCTION__, pAd->CommonCfg.MO_Cfg.nFalseCCACnt);
if (pAd->CommonCfg.MO_Cfg.nFalseCCACnt > pAd->CommonCfg.MO_Cfg.nFalseCCATh)
ASIC_MITIGATE_MICROWAVE(pAd);
}
}
#endif /* MICROWAVE_OVEN_SUPPORT */
#ifdef INF_AMAZON_SE
#ifdef RTMP_MAC_USB
SoftwareFlowControl(pAd);
#endif /* RTMP_MAC_USB */
#endif /* INF_AMAZON_SE */
#ifdef CONFIG_STA_SUPPORT
#ifdef RTMP_MAC_PCI
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
/* If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.*/
/* Move code to here, because following code will return when radio is off*/
if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
/* (pAd->StaCfg.bHardwareRadio == TRUE) &&*/
((IDLE_ON(pAd)) || (pAd->StaCfg.PwrMgmt.Psm == PWR_ACTIVE)) &&
(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
((pAd->StaCfg.bHardwareRadio == TRUE))
/* || (pAd->StaCfg.WscControl.CheckHWPBCState == HWPBCState_GUI)))*/
/*&&(pAd->bPCIclkOff == FALSE)*/)
{
UINT32 data = 0;
#if defined(RT30xx) || defined(RT5390) || defined(RT5392)
/* If in power save state, force wake up to configure register, AsicRadioOff will be called later n STAMlmePeriodicExec*/
if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
|| (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
|| RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
&& (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3593(pAd) || IS_RT5390(pAd) || IS_RT5392(pAd))
&& (pAd->StaCfg.bRadio == TRUE))
{
RT28xxPciAsicRadioOn(pAd, GUI_IDLE_POWER_SAVE);
}
#endif /* defined(RT30xx) || defined(RT5390) || defined(RT5392) */
/* Read GPIO pin2 as Hardware controlled radio state*/
/*#ifndef RT3090*/
/*RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);*/
/*#endif RT3090 */
// TODO: shiang-7603
if (pAd->chipCap.hif_type == HIF_MT) {
DBGPRINT(RT_DEBUG_OFF, ("%s(): Not support for HIF_MT yet!\n",
__FUNCTION__));
}
else
#ifdef RT3290
// TODO: shiang, what's the purpose of these code segments??
if (IS_RT3290(pAd))
{
if ((pAd->StaCfg.bHardwareRadio == TRUE) ||
(pAd->NicConfig2.field.EnableWPSPBC &&
(pAd->StaCfg.bRadio == TRUE) &&
(pAd->LedCntl.MCULedCntl.field.LedMode != LED_MODE_SIGNAL_STREGTH)
)
)
{
RTMP_IO_FORCE_READ32(pAd, WLAN_FUN_CTRL, &data);
DBGPRINT(RT_DEBUG_TRACE,(" RT3290: Read GPIO as Hardware controlled radio state\n"));
}
}
else
#endif /* RT3290 */
/*KH(PCIE PS):Added based on Jane<--*/
#ifdef PCIE_PS_SUPPORT
/* Read GPIO pin2 as Hardware controlled radio state*/
/* We need to Read GPIO if HW said so no mater what advance power saving*/
if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
&& (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
&& (pAd->StaCfg.PSControl.field.EnablePSinIdle == TRUE))
{
/* Want to make sure device goes to L0 state before reading register.*/
RTMPPCIeLinkCtrlValueRestore(pAd, 0);
RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
RTMPPCIeLinkCtrlSetting(pAd, 3);
}
else
RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
#else
RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
#endif /* defined(RT3090) || defined(RT3592) || defined(RT3390) */
/*KH(PCIE PS):Added based on Jane-->*/
/* Update Radio state from GPIO*/
if (pAd->StaCfg.bHardwareRadio == TRUE)
{
#ifdef RT3290
if (IS_RT3290(pAd))
pAd->StaCfg.bHwRadio = (data & 0x100) ? TRUE : FALSE;
else
#endif /* RT3290 */
{
if (data & 0x04)
pAd->StaCfg.bHwRadio = TRUE;
else
pAd->StaCfg.bHwRadio = FALSE;
}
#ifdef RT_CFG80211_SUPPORT
#ifdef RFKILL_HW_SUPPORT
RT_CFG80211_RFKILL_STATUS_UPDATE(pAd, pAd->StaCfg.bHwRadio);
#endif // RFKILL_HW_SUPPORT //
#endif /* RT_CFG80211_SUPPORT */
}
/* Always read HW radio configuration.*/
if (pAd->StaCfg.bHardwareRadio == TRUE)
{
if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
{
pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
if (pAd->StaCfg.bRadio == TRUE)
{
MlmeRadioOn(pAd);
pAd->ExtraInfo = EXTRA_INFO_CLEAR;
}
else
{
MlmeRadioOff(pAd);
pAd->ExtraInfo = HW_RADIO_OFF;
}
}
}
}
}
#endif /* RTMP_MAC_PCI */
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
RTMP_MLME_PRE_SANITY_CHECK(pAd);
}
#ifdef STA_LP_PHASE_1_SUPPORT
if (pAd->CountDowntoPsm > 0)
pAd->CountDowntoPsm--;
#else
#ifdef RTMP_MAC_USB
/*
We go to sleep mode only when count down to zero.
Count down counter is set after link up. So within 10 seconds after link up, we never go to sleep.
10 seconds period, we can get IP, finish 802.1x authenticaion. and some critical , timing protocol.
*/
if (pAd->CountDowntoPsm > 0)
pAd->CountDowntoPsm--;
#endif /* RTMP_MAC_USB */
#endif
#endif /* CONFIG_STA_SUPPORT */
/* Do nothing if the driver is starting halt state.*/
/* This might happen when timer already been fired before cancel timer with mlmehalt*/
if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
fRTMP_ADAPTER_RADIO_OFF |
fRTMP_ADAPTER_RADIO_MEASUREMENT |
fRTMP_ADAPTER_RESET_IN_PROGRESS |
fRTMP_ADAPTER_NIC_NOT_EXIST))))
return NDIS_STATUS_SUCCESS;
if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
return NDIS_STATUS_SUCCESS;
#ifdef CONFIG_FPGA_MODE
#ifdef CAPTURE_MODE
cap_status_chk_and_get(pAd);
#endif /* CAPTURE_MODE */
#endif /* CONFIG_FPGA_MODE */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
/* Do nothing if monitor mode is on*/
if (MONITOR_ON(pAd))
return NDIS_STATUS_SUCCESS;
#ifdef RTMP_MAC
if (pAd->chipCap.hif_type == HIF_RTMP) {
if ((pAd->Mlme.PeriodicRound & 0x1) &&
(STA_TGN_WIFI_ON(pAd)) &&
((pAd->MACVersion & 0xffff) == 0x0101))
{
UINT32 txop_cfg;
/* This is the fix for wifi 11n extension channel overlapping test case. for 2860D*/
if (pAd->CommonCfg.IOTestParm.bToggle == FALSE)
{
txop_cfg = 0x24BF;
pAd->CommonCfg.IOTestParm.bToggle = TRUE;
}
else
{
txop_cfg = 0x243f;
pAd->CommonCfg.IOTestParm.bToggle = FALSE;
}
RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, txop_cfg);
}
}
#endif /* RTMP_MAC */
}
#endif /* CONFIG_STA_SUPPORT */
pAd->bUpdateBcnCntDone = FALSE;
/* RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);*/
pAd->Mlme.PeriodicRound ++;
pAd->Mlme.GPIORound++;
#ifndef WFA_VHT_PF
#ifdef RT8592
if (IS_RT8592(pAd))
rt85592_cca_adjust(pAd);
#endif /* RT8592 */
#endif /* WFA_VHT_PF */
#if defined(MT_MAC) && defined(CONFIG_STA_SUPPORT)
if((pAd->Mlme.PeriodicRound % 10) == 0)
{
periodic_monitor_ac_counter(pAd,QID_AC_VI);
}
#endif
#ifdef MT_MAC
if ((pAd->Mlme.PeriodicRound % 1) == 0)
{
#ifdef RTMP_MAC_PCI
if (pAd->PDMAWatchDogEn)
{
PDMAWatchDog(pAd);
}
if (pAd->PSEWatchDogEn)
{
PSEWatchDog(pAd);
}
#endif
}
/* Following is the TxOP scenario, monitor traffic in every minutes */
if ((pAd->Mlme.PeriodicRound % 10) == 0)
{
TxTotalByteCnt = pAd->TxTotalByteCnt;
RxTotalByteCnt = pAd->RxTotalByteCnt;
//DBGPRINT(RT_DEBUG_TRACE, ("lala_1: [Tx Total Byte Count] = %lu\n", pAd->TxTotalByteCnt));
//DBGPRINT(RT_DEBUG_TRACE, ("lala_1: [Rx Total Byte Count] = %lu\n", pAd->RxTotalByteCnt));
if ((TxTotalByteCnt == 0) || (RxTotalByteCnt == 0))
{
/* Avoid to divide 0, when doing the traffic calculating */
// DBGPRINT(RT_DEBUG_TRACE, ("Not expected one of them is 0, TxTotalByteCnt = %lu, RxTotalByteCnt = %lu\n", TxTotalByteCnt, RxTotalByteCnt));
}
else if ((pAd->MacTab.Size == 1)
&& (pAd->CommonCfg.ManualTxop == 0)
&& pAd->CommonCfg.bEnableTxBurst
)
{
if ((((TxTotalByteCnt + RxTotalByteCnt) << 3) >> 20) > pAd->CommonCfg.ManualTxopThreshold)
{ /* TxopThreshold unit is Mbps */
if (TxTotalByteCnt > RxTotalByteCnt)
{
if ((TxTotalByteCnt/RxTotalByteCnt) >= pAd->CommonCfg.ManualTxopUpBound)
{ /* Boundary unit is Ratio */
DBGPRINT(RT_DEBUG_TRACE, ("(Ratio: %lu >= %d) Should be enable TxOP to 0x60\n",
TxTotalByteCnt/RxTotalByteCnt, pAd->CommonCfg.ManualTxopUpBound));
AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x60);
}
else if ((TxTotalByteCnt/RxTotalByteCnt) <= pAd->CommonCfg.ManualTxopLowBound)
{
if (pAd->chipCap.BiTxOpOn)
{
AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x60);
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("(Ratio: %lu <= %d) Should be disable TxOP to 0x0\n",
TxTotalByteCnt/RxTotalByteCnt, pAd->CommonCfg.ManualTxopLowBound));
AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x0);
}
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("(Ratio: %d < %lu < %d) Keep the last TxOP setting\n",
pAd->CommonCfg.ManualTxopLowBound, TxTotalByteCnt/RxTotalByteCnt, pAd->CommonCfg.ManualTxopUpBound));
}
}
else
{
if ((RxTotalByteCnt/TxTotalByteCnt) >= pAd->CommonCfg.ManualTxopUpBound)
{ /* Boundary unit is Ratio */
DBGPRINT(RT_DEBUG_TRACE, ("(Ratio: %lu >= %d) Should be enable TxOP to 0x60\n",
RxTotalByteCnt/TxTotalByteCnt, pAd->CommonCfg.ManualTxopUpBound));
AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x60);
}
else if ((RxTotalByteCnt/TxTotalByteCnt) <= pAd->CommonCfg.ManualTxopLowBound)
{
if (pAd->chipCap.BiTxOpOn)
{
AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x60);
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("(Ratio: %lu <= %d) Should be disable TxOP to 0x0\n",
RxTotalByteCnt/TxTotalByteCnt, pAd->CommonCfg.ManualTxopLowBound));
AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x0);
}
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("(Ratio: %d < %lu < %d) Keep the last TxOP setting\n", pAd->CommonCfg.ManualTxopLowBound, RxTotalByteCnt/TxTotalByteCnt, pAd->CommonCfg.ManualTxopUpBound));
}
}
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("Current TP=%lu < Threshold(%lu), turn-off TxOP\n",
(((TxTotalByteCnt + RxTotalByteCnt) << 3) >> 20), pAd->CommonCfg.ManualTxopThreshold));
if (!pAd->bLink11b)
AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x0);
}
}
else if (pAd->MacTab.Size > 1)
{
DBGPRINT(RT_DEBUG_TRACE, ("Multi STA turn-off TxOP\n"));
AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x0);
}
pAd->TxTotalByteCnt = 0;
pAd->RxTotalByteCnt = 0;
}
#endif /* MT_MAC */
#ifdef RTMP_MAC_USB
/* execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.*/
NICUpdateFifoStaCounters(pAd);
#ifdef CONFIG_AP_SUPPORT
#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT
if (pAd->CommonCfg.CarrierDetect.Enable)
CarrierDetectionPeriodicStateCtrl(pAd);
#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */
#endif /* CONFIG_AP_SUPPORT */
#endif /* RTMP_MAC_USB */
/* by default, execute every 500ms */
if ((pAd->ra_interval) &&
((pAd->Mlme.PeriodicRound % (pAd->ra_interval / 100)) == 0))
{
#ifdef MT_MAC
if (pAd->chipCap.hif_type == HIF_MT) {
//AsicRssiUpdate(pAd);
//AsicTxCntUpdate(pAd, 0);
}
#endif /* MT_MAC */
if (RTMPAutoRateSwitchCheck(pAd) == TRUE )
{
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
APMlmeDynamicTxRateSwitching(pAd);
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
/* perform dynamic tx rate switching based on past TX history*/
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
#ifdef MESH_SUPPORT
|| MESH_ON(pAd)
#endif /* MESH_SUPPORT */
#ifdef P2P_SUPPORT
|| P2P_GO_ON(pAd) || P2P_CLI_ON(pAd)
#endif /* P2P_SUPPORT */
#ifdef RT_CFG80211_SUPPORT
|| (pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP)
#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE
|| RTMP_CFG80211_VIF_P2P_CLI_ON(pAd)
#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */
#endif /* RT_CFG80211_SUPPORT */
)
&& (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
MlmeDynamicTxRateSwitching(pAd);
}
#endif /* CONFIG_STA_SUPPORT */
}else {
#ifdef MT_MAC
if (pAd->chipCap.hif_type == HIF_MT) {
MAC_TABLE_ENTRY *pEntry;
MT_TX_COUNTER TxInfo;
UINT16 i;
for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
{
/* point to information of the individual station */
pEntry = &pAd->MacTab.Content[i];
if (IS_ENTRY_NONE(pEntry))
continue;
if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst != SST_ASSOC))
continue;
#ifdef APCLI_SUPPORT
if (IS_ENTRY_APCLI(pEntry) && (pEntry->Sst != SST_ASSOC))
continue;
#endif /* APCLI_SUPPORT */
#ifdef WDS_SUPPORT
if (IS_ENTRY_WDS(pEntry) && !WDS_IF_UP_CHECK(pAd, pEntry->func_tb_idx))
continue;
#endif /* WDS_SUPPORT */
#ifdef MESH_SUPPORT
if (IS_ENTRY_MESH(pEntry) && !MESH_ON(pAd))
continue;
#endif /* MESH_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE,("%s(line=%d), Hanmin debug\n", __FUNCTION__, __LINE__));
AsicTxCntUpdate(pAd, pEntry, &TxInfo);
}
}
#endif /* MT_MAC */
}
}
#ifdef DFS_SUPPORT
#ifdef CONFIG_AP_SUPPORT
#ifdef RTMP_MAC_USB
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
if ((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == TRUE))
NewUsbTimerCB_Radar(pAd);
}
#endif /* RTMP_MAC_USB */
#endif /* CONFIG_AP_SUPPORT */
#endif /* DFS_SUPPORT */
#ifdef SMART_ANTENNA
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
if ((pAd->ra_interval) &&
((pAd->Mlme.PeriodicRound % (pAd->ra_interval / 100)) == 0) &&
RTMP_SA_WORK_ON(pAd))
{
if(RTMPAutoRateSwitchCheck(pAd) == FALSE)
{
TX_STA_CNT1_STRUC StaTx1;
TX_STA_CNT0_STRUC TxStaCnt0;
RTMP_SA_TRAINING_PARAM *pTrainEntry = &pAd->pSAParam->trainEntry[0];
/* Update statistic counter */
NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1);
if (pTrainEntry->pMacEntry && (pTrainEntry->trainStage != SA_INVALID_STAGE))
pTrainEntry->mcsStableCnt++;
}
/* Check if need to run antenna adaptation */
RtmpSAChkAndGo(pAd);
}
}
#endif /* SMART_ANTENNA */
#ifdef RTMP_FREQ_CALIBRATION_SUPPORT
#ifdef CONFIG_STA_SUPPORT
if (pAd->chipCap.FreqCalibrationSupport)
{
if ((pAd->FreqCalibrationCtrl.bEnableFrequencyCalibration == TRUE) &&
(INFRA_ON(pAd)))
FrequencyCalibration(pAd);
}
#endif /* CONFIG_STA_SUPPORT */
#endif /* RTMP_FREQ_CALIBRATION_SUPPORT */
/* Normal 1 second Mlme PeriodicExec.*/
if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
{
pAd->Mlme.OneSecPeriodicRound ++;
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
dynamic_tune_be_tx_op(pAd, 50); /* change form 100 to 50 for WMM WiFi test @20070504*/
#endif /* CONFIG_AP_SUPPORT */
NdisGetSystemUpTime(&pAd->Mlme.Now32);
/* add the most up-to-date h/w raw counters into software variable, so that*/
/* the dynamic tuning mechanism below are based on most up-to-date information*/
/* Hint: throughput impact is very serious in the function */
#ifndef RTMP_SDIO_SUPPORT
NicUpdatFalseCCACounters(pAd);
NICUpdateRawCounters(pAd);
#endif /*leonardo mark it for FPGA debug*/
RTMP_SECOND_CCA_DETECTION(pAd);
#ifdef DYNAMIC_VGA_SUPPORT
dynamic_vga_adjust(pAd);
#endif /* DYNAMIC_VGA_SUPPORT */
#ifdef RTMP_MAC_USB
#ifndef INF_AMAZON_SE
//RTUSBWatchDog(pAd);
#endif /* INF_AMAZON_SE */
#endif /* RTMP_MAC_USB */
#ifdef DOT11_N_SUPPORT
/* Need statistics after read counter. So put after NICUpdateRawCounters*/
ORIBATimerTimeout(pAd);
#endif /* DOT11_N_SUPPORT */
#ifdef CONFIG_WIFI_TEST
if (pAd->Mlme.OneSecPeriodicRound % 1 == 0)
{
#ifdef RTMP_PCI_SUPPORT
MonitorTxRing(pAd);
MonitorTxRing(pAd);
MonitorTxRing(pAd);
MonitorTxRing(pAd);
#endif
}
#endif
#ifdef DYNAMIC_VGA_SUPPORT
#ifdef CONFIG_AP_SUPPORT
#ifdef MT76x2
if (IS_MT76x2(pAd)) {
IF_DEV_CONFIG_OPMODE_ON_AP(pAd) {
if (pAd->Mlme.OneSecPeriodicRound % 1 == 0)
periodic_monitor_false_cca_adjust_vga(pAd);
}
}
#endif
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
#ifdef MT76x2
if (IS_MT76x2(pAd)) {
if (INFRA_ON(pAd)) {
if (pAd->Mlme.OneSecPeriodicRound % 1 == 0)
periodic_monitor_rssi_adjust_vga(pAd);
/* only g band need to check if disable channel smoothing */
#if 1
//if (pAd->CommonCfg.Channel <= 14)
//periodic_check_channel_smoothing(pAd);
#endif
}
}
#endif
#endif
#endif /* DYNAMIC_VGA_SUPPORT */
#ifdef RELEASE_EXCLUDE
/*
If MGMT RING is full more than twice within 1 second, we consider there's
a hardware problem stucking the TX path. In this case, try a hardware reset
to recover the system
*/
#endif /* RELEASE_EXCLUDE */
/*
if (pAd->RalinkCounters.MgmtRingFullCount >= 2)
RTMP_SET_FLAG(pAd, fRTMP_HW_ERR);
else
pAd->RalinkCounters.MgmtRingFullCount = 0;
*/
/* The time period for checking antenna is according to traffic*/
#ifdef ANT_DIVERSITY_SUPPORT
if ((pAd->CommonCfg.bSWRxAntDiversity)
&& (pAd->CommonCfg.RxAntDiversityCfg == ANT_SW_DIVERSITY_ENABLE) &&
(!pAd->EepromAccess))
AsicAntennaSelect(pAd, pAd->MlmeAux.Channel);
else if(pAd->CommonCfg.RxAntDiversityCfg == ANT_FIX_ANT0 || pAd->CommonCfg.RxAntDiversityCfg == ANT_FIX_ANT1)
{
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
APAsicAntennaAvg(pAd, pAd->RxAnt.Pair1PrimaryRxAnt, &realavgrssi);
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
realavgrssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
#endif /* CONFIG_STA_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
}
else
#endif /* ANT_DIVERSITY_SUPPORT */
{
if (pAd->Mlme.bEnableAutoAntennaCheck)
{
TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
pAd->RalinkCounters.OneSecTxRetryOkCount +
pAd->RalinkCounters.OneSecTxFailCount;
/* dynamic adjust antenna evaluation period according to the traffic*/
if (TxTotalCnt > 50)
{
if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
AsicEvaluateRxAnt(pAd);
}
else
{
if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
AsicEvaluateRxAnt(pAd);
}
}
}
#ifdef VIDEO_TURBINE_SUPPORT
/*
VideoTurbineUpdate(pAd);
VideoTurbineDynamicTune(pAd);
*/
#endif /* VIDEO_TURBINE_SUPPORT */
#ifdef MT76x0_TSSI_CAL_COMPENSATION
if (IS_MT76x0(pAd) &&
(pAd->chipCap.bInternalTxALC) &&
(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET) == FALSE))
{
if ((pAd->Mlme.OneSecPeriodicRound % 1) == 0)
{
/* TSSI compensation */
MT76x0_IntTxAlcProcess(pAd);
}
}
#endif /* MT76x0_TSSI_CAL_COMPENSATION */
#ifdef MT76x2
if (IS_MT76x2(pAd) &&
(pAd->chipCap.tssi_enable) &&
(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET) == FALSE)) {
if ((pAd->Mlme.OneSecPeriodicRound % 1) == 0) {
#ifdef CONFIG_AP_SUPPORT
mt76x2_tssi_compensation(pAd, pAd->hw_cfg.cent_ch);
#endif
#ifdef CONFIG_STA_SUPPORT
if (INFRA_ON(pAd))
mt76x2_tssi_compensation(pAd, pAd->hw_cfg.cent_ch);
#endif
}
}
#endif /* MT76x2 */
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET) == FALSE)
{
if ((pAd->Mlme.OneSecPeriodicRound % 10) == 0)
{
#ifdef MT76x0
if (IS_MT76x0(pAd)) {
if (pAd->chipCap.temp_sensor_enable)
mt76x0_temp_trigger_cal(pAd);
else
mt76x0_vco_calibration(pAd, pAd->hw_cfg.cent_ch);
}
else
#endif /* MT76x0 */
{
#ifdef VCORECAL_SUPPORT
AsicVCORecalibration(pAd);
#endif /* VCORECAL_SUPPORT */
}
}
}
#ifdef DOT11_N_SUPPORT
#ifdef MT_MAC
if (pAd->chipCap.hif_type == HIF_MT)
{
/* Not RDG, update the TxOP else keep the default RDG's TxOP */
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE) == FALSE)
{
#if 0
if ((pAd->MacTab.Size == 1)
&& (pAd->CommonCfg.bEnableTxBurst))
{ /* Only update TxOP for racing */
AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x80);
}
else
{
AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x0);
}
#endif
}
}
#endif /* MT_MAC */
#endif /* DOT11_N_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
APMlmePeriodicExec(pAd);
#ifdef RELEASE_EXCLUDE
/*
The watchdog will prevent the hardware MAC into a deadlock condition
1. No beacon frame sent within 2 seconds and
2. No site-survey processing
3. AP has started up
4. WDS isn't bridge mode
5. No Carrier signal exist.
*/
#endif /* RELEASE_EXCLUDE */
if ((pAd->RalinkCounters.OneSecBeaconSentCnt == 0)
&& (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
&& (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
&& ((pAd->CommonCfg.bIEEE80211H != 1)
|| (pAd->Dot11_H.RDMode != RD_SILENCE_MODE))
#ifdef WDS_SUPPORT
&& (pAd->WdsTab.Mode != WDS_BRIDGE_MODE)
#endif /* WDS_SUPPORT */
#ifdef CARRIER_DETECTION_SUPPORT
&& (isCarrierDetectExist(pAd) == FALSE)
#endif /* CARRIER_DETECTION_SUPPORT */
)
pAd->macwd ++;
else
pAd->macwd = 0;
#ifdef RELEASE_EXCLUDE
/*
When the beacon deadlock occurred over 2 seconds, reset MAC/BBP
When the below message is appeared, it indicates
the MAC seems to occur deadlock.
So, driver will reset MAC to attempt recover the whole system.
This is ASIC/Max's suggestion.
*/
#endif /* RELEASE_EXCLUDE */
if (pAd->macwd > 1)
{
DBGPRINT(RT_DEBUG_WARN, ("MAC specific condition \n"));
AsicSetMacWD(pAd);
#ifdef AP_QLOAD_SUPPORT
Show_QoSLoad_Proc(pAd, NULL);
#endif /* AP_QLOAD_SUPPORT */
}
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT)
RtmpPsActiveExtendCheck(pAd);
#ifdef TDLS_AUTOLINK_SUPPORT
/* TDLS discovery link maintenance */
if (IS_TDLS_SUPPORT(pAd) && (pAd->StaCfg.TdlsInfo.TdlsAutoLink))
{
TDLS_MaintainDiscoveryEntryList(pAd);
}
#endif /* TDLS_AUTOLINK_SUPPORT */
#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */
STAMlmePeriodicExec(pAd);
}
#endif /* CONFIG_STA_SUPPORT */
#ifdef SMART_CARRIER_SENSE_SUPPORT
#if 0 /* move to MtCmdNICUpdateRawCounters*/
pAd->SCSCtrl.PdCount = PDCnt;
pAd->SCSCtrl.MdrdyCount = MDRDYCnt;
pAd->SCSCtrl.FalseCCA = pAd->RalinkCounters.FalseCCACnt;
#endif
if (pAd->SCSCtrl.SCSEnable == SCS_ENABLE)
MTSmartCarrierSense(pAd);
#endif/*SMART_CARRIER_SENSE_SUPPORT */
#if defined(RT5370) || defined(RT5372) || defined(RT5390) || defined(RT5392)
if (IS_RT5392(pAd) && ((pAd->MACVersion & 0x0000FFFF) < 0x0223))
{
if(pAd->BbpResetFlag ==1)
{
pAd->BbpResetFlagCount ++;
if(pAd->BbpResetFlagCount > pAd->BbpResetFlagCountVale)
{
pAd->BbpResetFlagCount = 0;
pAd->BbpResetFlag = 0;
}
}
AsicCheckForHwRecovery(pAd);
}
#endif /* defined(RT5370) || defined(RT5372) || defined(RT5390) || defined(RT5392) */
RTMP_SECOND_CCA_DETECTION(pAd);
MlmeResetRalinkCounters(pAd);
#if defined(RTMP_MAC) || defined(RLT_MAC)
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
if (pAd->chipCap.hif_type == HIF_RTMP ||
pAd->chipCap.hif_type == HIF_RLT)
{
#ifdef RTMP_MAC_PCI
if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
#endif /* RTMP_MAC_PCI */
#ifdef RTMP_MAC_PCI
if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) &&
!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
#endif /* RTMP_MAC_PCI */
#ifdef RTMP_MAC_USB
if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
#endif /* RTMP_MAC_USB */
{
#ifdef RELEASE_EXCLUDE
/*
When Adhoc beacon is enabled and RTS/CTS is enabled, there is
a chance that hardware MAC FSM will run into a deadlock and
sending CTS-to-self over and over.
Software Patch Solution:
1. Polling debug state register 0x10F4 every one second.
2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR
((bit29==1) && (bit5==1)),
it means the deadlock has occurred.
3. If the deadlock occurred, reset MAC/BBP by setting 0x1004
to 0x0001 for a while then setting it back to 0x000C again.
*/
#endif /* RELEASE_EXCLUDE */
UINT32 MacReg = 0;
RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
{
RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
RtmpusecDelay(1);
MacReg = 0;
#ifdef HW_COEXISTENCE_SUPPORT
if (pAd->bHWCoexistenceInit)
{
#ifdef BT_COEXISTENCE_SUPPORT
if (pAd->bHWCoexistenceInit==TRUE && (!IS_RT5390BC8(pAd)) && (!IS_RT3592BC8(pAd)))
{
if(IS_ENABLE_BT_WIFI_ACTIVE_PULL_HIGH_BY_TIMER(pAd) && (pAd->BT_BC_PERMIT_RXWIFI_ACTIVE==TRUE))
MacReg = 0x224c;
else if(IS_ENABLE_WIFI_ACTIVE_PULL_LOW_BY_FORCE(pAd))
MacReg = WLAN_WIFI_ACT_PULL_LOW;
}
else
#endif /* BT_COEXISTENCE_SUPPORT */
MacReg = WLAN_WIFI_ACT_PULL_HIGH;
}
else
#endif /* HW_COEXISTENCE_SUPPORT */
{
MacReg = 0xc;
}
if (MacReg)
RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacReg);
DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
}
}
}
}
#endif /* CONFIG_STA_SUPPORT */
#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */
RTMP_MLME_HANDLER(pAd);
}
#ifdef RT6352
if (IS_RT6352(pAd)) {
if (pAd->CommonCfg.bEnTemperatureTrack == TRUE)
{
#ifdef RTMP_INTERNAL_TX_ALC
if (pAd->TxPowerCtrl.bInternalTxALC)
{
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_TRACE, ("Track Power Compensation !!!\n"));
#endif /* RELEASE_EXCLUDE */
if (RT635xCheckTssiCompensation(pAd))
{
#ifdef RTMP_TEMPERATURE_CALIBRATION
RT6352_TemperatureCalibration(pAd);
#endif /* RTMP_TEMPERATURE_CALIBRATION */
DoDPDCalibration(pAd);
}
}
else
#endif /* RTMP_INTERNAL_TX_ALC */
#ifdef RTMP_TEMPERATURE_COMPENSATION
if (pAd->bAutoTxAgcG)
{
if (RT6352_TemperatureCompensation(pAd, FALSE) == TRUE)
{
INT32 TemperatureDiff = 0;
pAd->CommonCfg.bEnTemperatureTrack = FALSE;
TemperatureDiff = ((pAd->CurrTemperature - pAd->TemperatureRef25C) * 19) - pAd->DoCalibrationTemperature;
#ifdef RT6352_EP_SUPPORT
if ((TemperatureDiff >= 400) || (TemperatureDiff <= -400))
{
RT6352_ReCalibration(pAd);
pAd->DoCalibrationTemperature = (pAd->CurrTemperature - pAd->TemperatureRef25C) * 19;
}
#endif /* RT6352_EP_SUPPORT */
}
}
else
#endif /* RTMP_TEMPERATURE_COMPENSATION */
{
#ifdef RTMP_TEMPERATURE_CALIBRATION
UCHAR bbpval;
CHAR BBPR49;
INT32 TemperatureDiff = 0;
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &bbpval);
if ((bbpval & 0x10) == 0)
{
bbpval &= 0xf8;
bbpval |= 0x04;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, bbpval);
/* save temperature */
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BBPR49);
pAd->CurrTemperature = (INT32) BBPR49;
DBGPRINT(RT_DEBUG_INFO, ("Current Temperature from BBP_R49=0x%x\n", pAd->CurrTemperature));
RT6352_TemperatureCalibration(pAd);
pAd->CommonCfg.bEnTemperatureTrack = FALSE;
TemperatureDiff = ((pAd->CurrTemperature - pAd->TemperatureRef25C) * 19) - pAd->DoCalibrationTemperature;
#ifdef RT6352_EP_SUPPORT
if ((TemperatureDiff >= 400) || (TemperatureDiff <= -400))
{
RT6352_ReCalibration(pAd);
pAd->DoCalibrationTemperature = (pAd->CurrTemperature - pAd->TemperatureRef25C) * 19;
}
#endif /* RT6352_EP_SUPPORT */
}
#endif /* RTMP_TEMPERATURE_CALIBRATION */
}
}
}
#endif /* RT6352 */
#ifdef WSC_INCLUDED
WSC_HDR_BTN_MR_HANDLE(pAd);
#endif /* WSC_INCLUDED */
#ifdef __ECOS /* Polling restore button in APSOC */
#ifdef PLATFORM_BUTTON_SUPPORT
if (pAd->CommonCfg.RestoreHdrBtnFlag)
Restore_button_CheckHandler(pAd);
#endif /* PLATFORM_BUTTON_SUPPORT */
#endif /* __ECOS */
#ifdef P2P_SUPPORT
if (P2P_INF_ON(pAd))
P2pPeriodicExec(SystemSpecific1, FunctionContext, SystemSpecific2, SystemSpecific3);
#endif /* P2P_SUPPORT */
/*add for hook function on Mlme timer interrupt*/
RTMP_OS_TXRXHOOK_CALL(WLAN_TX_MLME_PERIOD,NULL,1,pAd);
pAd->bUpdateBcnCntDone = FALSE;
return NDIS_STATUS_SUCCESS;
}
/*
==========================================================================
Validate SSID for connection try and rescan purpose
Valid SSID will have visible chars only.
The valid length is from 0 to 32.
IRQL = DISPATCH_LEVEL
==========================================================================
*/
BOOLEAN MlmeValidateSSID(UCHAR *pSsid, UCHAR SsidLen)
{
int index;
if (SsidLen > MAX_LEN_OF_SSID)
return (FALSE);
/* Check each character value*/
for (index = 0; index < SsidLen; index++)
{
if (pSsid[index] < 0x20)
return (FALSE);
}
/* All checked*/
return (TRUE);
}
#ifdef CONFIG_STA_SUPPORT
VOID STAMlmePeriodicExec(RTMP_ADAPTER *pAd)
{
ULONG TxTotalCnt;
BOOLEAN bCheckBeaconLost = TRUE;
#ifdef WPA3_SUPPORT
BOOLEAN Status = TRUE;
#endif
#ifdef P2P_SUPPORT
WSC_CTRL *pWscControl;
if (P2P_CLI_ON(pAd))
pWscControl = &pAd->ApCfg.ApCliTab[0].WscControl;
else
pWscControl = &pAd->ApCfg.MBSSID[0].WscControl;
#endif /* P2P_SUPPORT */
#ifdef RELEASE_EXCLUDE
/*
high-power issue:
request by Brian, If our 2070/3070/305x AP/Station is too close to receive the stations/APs signal,
we will dynamically tune the RF power(controlled by RF_R27).
The tuning rules are
1. If the connecting devices is too close, we will attenuate the RF power to 0V.
2. Otherwise, recover the RF power to original level (0.15V)
*/
#endif /* RELEASE_EXCLUDE */
RTMP_CHIP_HIGH_POWER_TUNING(pAd, &pAd->StaCfg.RssiSample);
#ifdef WPA_SUPPLICANT_SUPPORT
if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
#endif /* WPA_SUPPLICANT_SUPPORT */
{
/* WPA MIC error should block association attempt for 60 seconds*/
if (pAd->StaCfg.bBlockAssoc &&
RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastMicErrorTime + (60*OS_HZ)))
pAd->StaCfg.bBlockAssoc = FALSE;
}
#ifdef RTMP_MAC_USB
/* If station is idle, go to sleep*/
if ( 1
/* && (pAd->StaCfg.PSControl.field.EnablePSinIdle == TRUE)*/
&& (pAd->StaCfg.WindowsPowerMode > 0)
&& (pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
&& (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
&& (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
&& (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
#ifdef WSC_STA_SUPPORT
&& (pAd->StaCfg.WscControl.WscState == WSC_STATE_OFF)
#endif /* WSC_STA_SUPPORT */
#ifdef P2P_SUPPORT
&& (!P2P_INF_ON(pAd))
#endif /* P2P_SUPPORT */
)
{
ASIC_RADIO_OFF(pAd, MLME_RADIO_OFF);
#ifdef CONFIG_PM
#ifdef USB_SUPPORT_SELECTIVE_SUSPEND
{
POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
if(!RTMP_Usb_AutoPM_Put_Interface(pObj->pUsb_Dev,pObj->intf))
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_SUSPEND);
}
#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */
#endif /* CONFIG_PM */
DBGPRINT(RT_DEBUG_TRACE, ("PSM - Issue Sleep command)\n"));
}
#endif /* RTMP_MAC_USB */
#ifdef ETH_CONVERT_SUPPORT
if ((pAd->EthConvert.ECMode & ETH_CONVERT_MODE_CLONE)
&& (pAd->EthConvert.CloneMacVaild == TRUE)
&& (NdisEqualMemory(pAd->CurrentAddress, pAd->EthConvert.EthCloneMac, MAC_ADDR_LEN) == FALSE))
{
MAC_DW0_STRUC csr2;
MAC_DW1_STRUC csr3;
/* Link down first */
if (INFRA_ON(pAd))
{
if (pAd->MlmeAux.SsidLen) {
NdisZeroMemory(pAd->EthConvert.SSIDStr, MAX_LEN_OF_SSID);
NdisMoveMemory(pAd->EthConvert.SSIDStr, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
pAd->EthConvert.SSIDStrLen = pAd->MlmeAux.SsidLen;
}
pAd->MlmeAux.CurrReqIsFromNdis = TRUE;
if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
{
RTMP_MLME_RESET_STATE_MACHINE(pAd);
DBGPRINT(RT_DEBUG_TRACE, ("!!! MLME busy, reset MLME state machine !!!\n"));
}
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
OID_802_11_DISASSOCIATE,
0,
NULL, 0);
}
else if (ADHOC_ON(pAd))
{
MakeIbssBeacon(pAd); /* re-build BEACON frame*/
AsicEnableIbssSync(pAd); /* copy to on-chip memory*/
LinkDown(pAd, FALSE);
}
else
{
/* Copy the new Mac address to ASIC and start to re-connect to AP.*/
NdisMoveMemory(&pAd->CurrentAddress[0], &pAd->EthConvert.EthCloneMac[0], MAC_ADDR_LEN);
AsicSetDevMac(pAd, pAd->CurrentAddress, 0x0);
DBGPRINT_RAW(RT_DEBUG_TRACE,("Write EthCloneMac to ASIC: =%02x:%02x:%02x:%02x:%02x:%02x\n",
PRINT_MAC(pAd->CurrentAddress)));
if(pAd->EthConvert.SSIDStrLen != 0)
{
/*DBGPRINT_RAW(RT_DEBUG_TRACE, ("copy MlmeAux.Ssid to AutoReconnect!\n"));*/
NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid,
pAd->EthConvert.SSIDStr,
pAd->EthConvert.SSIDStrLen);
pAd->MlmeAux.AutoReconnectSsidLen = pAd->EthConvert.SSIDStrLen;
NdisMoveMemory(pAd->MlmeAux.Ssid, pAd->EthConvert.SSIDStr, pAd->EthConvert.SSIDStrLen);
pAd->MlmeAux.SsidLen= pAd->EthConvert.SSIDStrLen;
}
}
}
#endif /* ETH_CONVERT_SUPPORT */
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO,("MMCHK - CommonCfg.Ssid[%d]=%c%c%c%c... MlmeAux.Ssid[%d]=%c%c%c%c...\n",
pAd->CommonCfg.SsidLen,
pAd->CommonCfg.Ssid[0], pAd->CommonCfg.Ssid[1],
pAd->CommonCfg.Ssid[2], pAd->CommonCfg.Ssid[3],
pAd->MlmeAux.SsidLen,
pAd->MlmeAux.Ssid[0], pAd->MlmeAux.Ssid[1],
pAd->MlmeAux.Ssid[2], pAd->MlmeAux.Ssid[3]));
#endif /* RELEASE_EXCLUDE */
if (ADHOC_ON(pAd))
{
}
else
{
AsicStaBbpTuning(pAd);
}
TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
pAd->RalinkCounters.OneSecTxRetryOkCount +
pAd->RalinkCounters.OneSecTxFailCount;
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)))
{
/* update channel quality for Roaming/Fast-Roaming and UI LinkQuality display*/
/* bImprovedScan True means scan is not completed */
if (pAd->StaCfg.bImprovedScan)
bCheckBeaconLost = FALSE;
#ifdef P2P_SUPPORT
if (NdisEqualMemory(ZERO_MAC_ADDR, pAd->P2pCfg.ConnectingMAC, MAC_ADDR_LEN) == FALSE)
{
UCHAR p2pindex;
p2pindex = P2pGroupTabSearch(pAd, pAd->P2pCfg.ConnectingMAC);
if (p2pindex != P2P_NOT_FOUND)
{
if (pAd->P2pTable.Client[p2pindex].P2pClientState > P2PSTATE_DISCOVERY_UNKNOWN)
bCheckBeaconLost = FALSE;
}
}
#endif /* P2P_SUPPORT */
#ifdef CONFIG_WIFI_TEST
if (pAd->chipCap.pbf_loopback)
bCheckBeaconLost = FALSE;
#endif /* CONFIG_WIFI_TEST */
if (bCheckBeaconLost)
{
/* The NIC may lost beacons during scaning operation.*/
MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
MlmeCalculateChannelQuality(pAd, pEntry, pAd->Mlme.Now32);
}
}
/* must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if*/
/* Radio is currently in noisy environment*/
if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
{
RTMP_CHIP_ASIC_ADJUST_TX_POWER(pAd);
RTMP_CHIP_ASIC_TEMPERATURE_COMPENSATION(pAd);
}
#ifdef MT76XX_BTCOEX_SUPPORT
#ifdef RTMP_PCI_SUPPORT
if(pAd->bPCIclkOff == FALSE && IS_MT76XXBTCOMBO(pAd))
#endif /*RTMP_PCI_SUPPORT*/
#ifdef RTMP_USB_SUPPORT
if(IS_MT76XXBTCOMBO(pAd))
#endif /*RTMP_PCI_SUPPORT*/
{
CoexistencePeriodicRoutine(pAd);
#if 0
//temporary status checking for coex
WLAN_FUN_CTRL_STRUC wlanFunInfo = {.word = 0};
RTMP_IO_READ32(pAd, WLAN_FUN_INFO, &wlanFunInfo.word);
//COEX periodic checking
DBGPRINT(RT_DEBUG_TRACE,("COEX: StaCfg.AvgRssi[0] = %d\n",pAd->StaCfg.RssiSample.AvgRssi[0]));
DBGPRINT(RT_DEBUG_TRACE,("COEX:CoexMode = %d\n",pAd->CoexMode.CurrentMode));
if ((IS_MT7650(pAd) || IS_MT7630(pAd)) && (wlanFunInfo.field.COEX_MODE & 0x4))
{
if (pAd->CoexMode.CurrentMode == COEX_MODE_FDD)
{
TDDFDDCoexBACapability(pAd, COEX_MODE_FDD);
} else if (pAd->CoexMode.CurrentMode == COEX_MODE_TDD)
{
TDDFDDCoexBACapability(pAd, COEX_MODE_TDD);
}
else
{
DBGPRINT(RT_DEBUG_TRACE,("COEX:Strange CoexMode = %d\n",pAd->CoexMode.CurrentMode));
}
}
else if (IS_MT7650(pAd) || IS_MT7630(pAd))
{
TDDFDDCoexBACapability(pAd, COEX_MODE_RESET);
}
if (pAd->CoexMode.TDDRequest == FALSE)
{
SendAndesTFSWITCH(pAd, COEX_MODE_TDD);
}
if ((IS_MT7650(pAd) || IS_MT7630(pAd)) && INFRA_ON(pAd))
{
DBGPRINT(RT_DEBUG_TRACE,("COEX: pAd->CoexMode.CoexTDDRSSITreshold = %d\n",pAd->CoexMode.CoexTDDRSSITreshold));
DBGPRINT(RT_DEBUG_TRACE,("COEX: pAd->CoexMode.CoexFDDRSSITreshold = %d\n",pAd->CoexMode.CoexFDDRSSITreshold));
//MT76xx coex RX LNA gain adjustment
if (pAd->CoexMode.CurrentMode == COEX_MODE_FDD)
{
if (pAd->StaCfg.RssiSample.AvgRssi[0] < (pAd->CoexMode.CoexTDDRSSITreshold) )
{
if (pAd->CoexMode.TDDRequest == FALSE)
{
SendAndesTFSWITCH(pAd, COEX_MODE_TDD);
}
}
if (pAd->StaCfg.RssiSample.AvgRssi[0] > (pAd->CoexMode.CoexFDDRSSITreshold) )
{
if (pAd->CoexMode.FDDRequest == FALSE)
{
SendAndesTFSWITCH(pAd, COEX_MODE_FDD);
}
}
CoexFDDRXAGCGain(pAd, pAd->StaCfg.RssiSample.AvgRssi[0]);
}
else if (pAd->CoexMode.CurrentMode == COEX_MODE_TDD)
{
if (pAd->StaCfg.RssiSample.AvgRssi[0] > (pAd->CoexMode.CoexFDDRSSITreshold) )
{
if (pAd->CoexMode.FDDRequest == FALSE)
{
SendAndesTFSWITCH(pAd, COEX_MODE_FDD);
}
}
if (pAd->StaCfg.RssiSample.AvgRssi[0] < (pAd->CoexMode.CoexTDDRSSITreshold) )
{
if (pAd->CoexMode.TDDRequest == FALSE)
{
SendAndesTFSWITCH(pAd, COEX_MODE_TDD);
}
}
CoexTDDRXAGCGain(pAd);
}
}
#endif
}
#endif /*MT76XX_BTCOEX_SUPPORT*/
/*
Driver needs to up date value of LastOneSecTotalTxCount here;
otherwise UI couldn't do scanning sometimes when STA doesn't connect to AP or peer Ad-Hoc.
*/
pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
#ifdef RT3290
// TODO: shiang, what's this and how about in AP mode??
// Need to enable PCIE_APP0_CLK_REQ for HT40 throughput
if (IS_RT3290(pAd) && (pAd->CommonCfg.BBPCurrentBW == BW_40))
{
WLAN_FUN_CTRL_STRUC WlanFunCtrl = {.word = 0};
if ((pAd->RalinkCounters.LastOneSecTotalTxCount + pAd->RalinkCounters.LastOneSecRxOkDataCnt) >= 2000)
{
RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &WlanFunCtrl.word);
if ((WlanFunCtrl.field.WLAN_EN == TRUE) && (WlanFunCtrl.field.PCIE_APP0_CLK_REQ == FALSE))
{
WlanFunCtrl.field.PCIE_APP0_CLK_REQ = TRUE;
RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, WlanFunCtrl.word);
}
}
else if ((pAd->RalinkCounters.LastOneSecTotalTxCount + pAd->RalinkCounters.LastOneSecRxOkDataCnt) <= 500)
{
RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &WlanFunCtrl.word);
if ((WlanFunCtrl.field.WLAN_EN == TRUE) && (WlanFunCtrl.field.PCIE_APP0_CLK_REQ == TRUE))
{
WlanFunCtrl.field.PCIE_APP0_CLK_REQ = FALSE;
RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, WlanFunCtrl.word);
}
}
}
//HWAntennaSwitch
if (IS_RT3290(pAd) &&
((pAd->NicConfig3.word != 0xFFFF) && (pAd->NicConfig3.field.CoexAnt == TRUE)) &&
((pAd->Mlme.OneSecPeriodicRound % 5) == 4))
{
WLAN_FUN_CTRL_STRUC WlanFunCtrl = {.word = 0};
ULONG MacRegValue;
DBGPRINT(RT_DEBUG_INFO, ("!!! BBP_R150 = %d, BT_EN = %d\n",pAd->BbpWriteLatch[BBP_R150], pAd->BtFunCtrl.field.BT_EN));
//Check BT_EN
if ((((pAd->WlanFunInfo.field.COEX_MODE&0x1E) == 0) || (pAd->BtFunCtrl.field.BT_EN == 0)) && (pAd->BbpWriteLatch[BBP_R150] != 0xc0))
{
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
|| (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
|| RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
AsicForceWakeup(pAd, DOT11POWERSAVE);
//Enable RX antenna switch
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R150, 0xc0);
DBGPRINT(RT_DEBUG_TRACE, ("!!! EN BBP_R150 = %d\n",pAd->BbpWriteLatch[BBP_R150]));
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R151, 0xb0);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R152, 0x23);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R153, 0x34);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R154, 0x10);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R155, 0x3b);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R253, 0x05);
//Disable FIX_WL_ANT_SEL
RTMP_IO_READ32(pAd, COEXCFG0, &MacRegValue);
MacRegValue &= ~(0x00000004);
RTMP_IO_WRITE32(pAd, COEXCFG0, MacRegValue);
// Fixed to Main Antenna
RTMP_SEM_LOCK(&pAd->WlanEnLock);
RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &WlanFunCtrl.word);
if (WlanFunCtrl.field.WLAN_EN == TRUE)
{
if (WlanFunCtrl.field.INV_TR_SW0)
{
WlanFunCtrl.field.INV_TR_SW0 = 0;
RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, WlanFunCtrl.word);
}
DBGPRINT(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
pAd->WlanFunCtrl.word = WlanFunCtrl.word;
}
RTMP_SEM_UNLOCK(&pAd->WlanEnLock);
//Disable SW antanna selection
pAd->NicConfig2.field.AntDiversity = FALSE;
}
else if(((pAd->WlanFunInfo.field.COEX_MODE&0x1E) != 0) && (pAd->BbpWriteLatch[BBP_R150] != 0x00))
{
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
|| (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
|| RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
AsicForceWakeup(pAd, DOT11POWERSAVE);
//Disable RX antenna switch
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R150, 0x00);
DBGPRINT(RT_DEBUG_TRACE, ("!!! DISABLE BBP_R150 = %d\n",pAd->BbpWriteLatch[BBP_R150]));
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R151, 0x00);
//Enable FIX_WL_ANT_SEL
RTMP_IO_READ32(pAd, COEXCFG0, &MacRegValue);
MacRegValue |= 0x00000004;
RTMP_IO_WRITE32(pAd, COEXCFG0, MacRegValue);
//Enable SW antanna selection
pAd->NicConfig2.word = pAd->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET];
}
}
#endif /* RT3290 */
#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT)
/* MAC table maintenance */
if ((pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) &&
#ifdef RT_CFG80211_P2P_SUPPORT
(pAd->cfg80211_ctrl.isCfgInApMode == RT_CMD_80211_IFTYPE_AP)
#else
P2P_GO_ON(pAd)
#endif /* RT_CFG80211_P2P_SUPPORT */
)
{
/* one second timer */
#ifdef RT_CFG80211_P2P_SUPPORT
MacTableMaintenance(pAd);
#else
P2PMacTableMaintenance(pAd);
#endif /* RT_CFG80211_P2P_SUPPORT */
#ifdef DOT11_N_SUPPORT
if (pAd->CommonCfg.bHTProtect)
{
APUpdateOperationMode(pAd);
if (pAd->CommonCfg.IOTestParm.bRTSLongProtOn == FALSE)
{
AsicUpdateProtect(pAd, (USHORT)pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode,
ALLN_SETPROTECT, FALSE, pAd->MacTab.fAnyStationNonGF);
}
}
#endif /* DOT11_N_SUPPORT */
}
#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */
/* resume Improved Scanning*/
if ((pAd->StaCfg.bImprovedScan) &&
(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
(pAd->Mlme.SyncMachine.CurrState == SCAN_PENDING))
{
MLME_SCAN_REQ_STRUCT ScanReq;
pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, BSS_ANY, pAd->MlmeAux.ScanType);
MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0);
DBGPRINT(RT_DEBUG_WARN, ("bImprovedScan ............. Resume for bImprovedScan, SCAN_PENDING .............. \n"));
}
if (INFRA_ON(pAd))
{
#ifdef QOS_DLS_SUPPORT
/* Check DLS time out, then tear down those session*/
RTMPCheckDLSTimeOut(pAd);
#endif /* QOS_DLS_SUPPORT */
#ifdef DOT11Z_TDLS_SUPPORT
/* TDLS link maintenance*/
if (IS_TDLS_SUPPORT(pAd))
{
if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0)
TDLS_LinkMaintenance(pAd);
}
#endif /* DOT11Z_TDLS_SUPPORT */
/* Is PSM bit consistent with user power management policy?*/
/* This is the only place that will set PSM bit ON.*/
if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
/*
When we are connected and do the scan progress, it's very possible we cannot receive
the beacon of the AP. So, here we simulate that we received the beacon.
*/
if ((bCheckBeaconLost == FALSE) &&
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) &&
(RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastBeaconRxTime + (1*OS_HZ))))
{
ULONG BPtoJiffies;
LONG timeDiff;
BPtoJiffies = (((pAd->CommonCfg.BeaconPeriod * 1024 / 1000) * OS_HZ) / 1000);
timeDiff = (pAd->Mlme.Now32 - pAd->StaCfg.LastBeaconRxTime) / BPtoJiffies;
if (timeDiff > 0)
pAd->StaCfg.LastBeaconRxTime += (timeDiff * BPtoJiffies);
if (RTMP_TIME_AFTER(pAd->StaCfg.LastBeaconRxTime, pAd->Mlme.Now32))
{
DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - BeaconRxTime adjust wrong(BeaconRx=0x%lx, Now=0x%lx)\n",
pAd->StaCfg.LastBeaconRxTime, pAd->Mlme.Now32));
}
}
#ifdef MT7628_FPGA
if ((RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastBeaconRxTime + (350 *OS_HZ))) &&
(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
(pAd->StaCfg.bImprovedScan == FALSE) &&
((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) < 600))
#else
if ((RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastBeaconRxTime + (1*OS_HZ))) &&
(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
(pAd->StaCfg.bImprovedScan == FALSE) &&
((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) < 600))
#endif /* MT7628_FPGA */
{
#if defined(MT7636) || defined(MT7603)
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) == 0)
#endif
{
RTMPSetAGCInitValue(pAd, BW_20);
DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + pAd->hw_cfg.lan_gain)));
}
}
#ifdef RTMP_MAC_USB
#if defined(RTMP_MAC) || defined(RLT_MAC)
#ifdef DOT11_N_SUPPORT
if (pAd->chipCap.hif_type != HIF_MT)
{
#ifdef RELEASE_EXCLUDE
/*
For 1X1 STA pass 11n wifi wmm, need to change txop per case;
1x1 device for 802.11n WMM Test.
New chip may not need this for TGn WMM test.
*/
#endif /* RELEASE_EXCLUDE */
sta_wmm_adjust(pAd);
}
#endif /* DOT11_N_SUPPORT */
#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */
/* TODO: for debug only. to be removed*/
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
pAd->RalinkCounters.OneSecTxDoneCount = 0;
pAd->RalinkCounters.OneSecTxARalinkCnt = 0;
pAd->RalinkCounters.OneSecRxARalinkCnt = 0;
#endif /* RTMP_MAC_USB */
#ifdef WMM_ACM_SUPPORT
/* WMM ACM fix: we are AP and we can send any packet even no TSPEC */
/* if the ACM of all AC are enabled, we can not send any packet without
following any TSPEC */
/* if (ACMP_IsAllACEnabled(pAd) != ACM_RTN_OK)*/
#endif /* WMM_ACM_SUPPORT */
/*if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&*/
/* (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))*/
if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
&& (pAd->cfg80211_ctrl.IsInListenProgress == FALSE)) /*if in listen progress, no need to send Null Data*/
{
if (pAd->StaCfg.wdev.UapsdInfo.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
{
/* When APSD is enabled, the period changes as 20 sec*/
if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
{
/* In 7603, it doesn't support redirect feature, driver needs to wakup h/w firstly before send keep alive null */
/* In 7636, it supports redirect feature, driver needs not to wakup h/w firstly before send keep alive null */
#ifdef STA_LP_PHASE_1_SUPPORT
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
{
AsicForceWakeup(pAd, TRUE);
}
#endif /* STA_LP_PHASE_1_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE, ("%s(line=%d)\n", __FUNCTION__, __LINE__));
RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.PwrMgmt.Psm);
}
}
else
{
/* Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)*/
if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
{
DBGPRINT(RT_DEBUG_TRACE, ("%s::keep alive Null (%d, %d)\n", __FUNCTION__, pAd->CommonCfg.bAPSDForcePowerSave, pAd->StaCfg.PwrMgmt.Psm));
/* In 7603, it doesn't support redirect feature, driver needs to wakup h/w firstly before send keep alive null */
/* In 7636, it supports redirect feature, driver needs not to wakup h/w firstly before send keep alive null */
#ifdef STA_LP_PHASE_1_SUPPORT
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
{
AsicForceWakeup(pAd, TRUE);
DBGPRINT(RT_DEBUG_TRACE, ("%s::keep alive Null, wait H/W wakeup\n", __FUNCTION__));
}
#endif /* STA_LP_PHASE_1_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE, ("%s(line=%d)\n", __FUNCTION__, __LINE__));
RTMPSendNullFrame(pAd,
pAd->CommonCfg.TxRate,
(pAd->CommonCfg.bWmmCapable & pAd->CommonCfg.APEdcaParm.bValid),
pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.PwrMgmt.Psm);
}
#ifdef MT7601
// TODO: shiang-usw, what's the purpose to set this here?
else
{
pAd->Mlme.bSendNullFrameAfterWareUp = TRUE;
}
#endif /* MT7601 */
}
}
if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
{
#if defined(STA_LP_PHASE_1_SUPPORT) || defined(STA_LP_PHASE_2_SUPPORT)
pAd->StaCfg.PwrMgmt.bBeaconLost = FALSE;
#endif
DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n",
pAd->RalinkCounters.BadCQIAutoRecoveryCount));
if (pAd->StaCfg.bAutoConnectByBssid)
pAd->StaCfg.bAutoConnectByBssid = FALSE;
#ifdef WPA_SUPPLICANT_SUPPORT
if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) &&
(pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWPA2))
pAd->StaCfg.wpa_supplicant_info.bLostAp = TRUE;
#endif /* WPA_SUPPLICANT_SUPPORT */
pAd->MlmeAux.CurrReqIsFromNdis = FALSE;
/* Lost AP, send disconnect & link down event*/
#ifdef WPA3_SUPPORT
/* Compose a DEAUTH to inform AP & supplicant */
Status = SendDeauthFrame(pAd);
if (Status == FALSE)
DBGPRINT(RT_DEBUG_ERROR, ("%s: failed to send Deauth\n", __func__));
#endif
LinkDown(pAd, FALSE);
#ifdef STA_EASY_CONFIG_SETUP
pAd->Mlme.AutoProvisionMachine.CurrState = INFRA_AUTO_PROVISION;
MlmeEnqueue(pAd, AUTO_PROVISION_STATE_MACHINE, MT2_CONN_AP, 0, NULL, 0);
RTMP_MLME_HANDLER(pAd);
#endif /* STA_EASY_CONFIG_SETUP */
/* should mark this two function, because link down alse will call this function */
#if 0
#ifdef WPA_SUPPLICANT_SUPPORT
#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
/*send disassociate event to wpa_supplicant*/
if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP)
{
RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_DISASSOC_EVENT_FLAG, NULL, NULL, 0);
}
#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */
#endif /* WPA_SUPPLICANT_SUPPORT */
#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CGIWAP, -1, NULL, NULL, 0);
#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */
#endif
/* RTMPPatchMacBbpBug(pAd);*/
#ifdef WPA_SUPPLICANT_SUPPORT
if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
#endif /* WPA_SUPPLICANT_SUPPORT */
MlmeAutoReconnectLastSSID(pAd);
}
else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
{
pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n",
pAd->RalinkCounters.BadCQIAutoRecoveryCount));
MlmeAutoReconnectLastSSID(pAd);
}
if (pAd->StaCfg.bAutoRoaming)
{
BOOLEAN rv = FALSE;
CHAR dBmToRoam = pAd->StaCfg.dBmToRoam;
CHAR MaxRssi = RTMPMaxRssi(pAd,
pAd->StaCfg.RssiSample.LastRssi[0],
pAd->StaCfg.RssiSample.LastRssi[1],
pAd->StaCfg.RssiSample.LastRssi[2]);
if (pAd->StaCfg.bAutoConnectByBssid)
pAd->StaCfg.bAutoConnectByBssid = FALSE;
/* Scanning, ignore Roaming*/
if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) &&
(pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
(MaxRssi <= dBmToRoam))
{
DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", MaxRssi, (CHAR)dBmToRoam));
#ifdef DOT11R_FT_SUPPORT
if (pAd->StaCfg.Dot11RCommInfo.bFtSupport &&
pAd->StaCfg.Dot11RCommInfo.bInMobilityDomain)
rv = FT_CheckForRoaming(pAd);
#endif /* DOT11R_FT_SUPPORT */
/* Add auto seamless roaming*/
if (rv == FALSE)
rv = MlmeCheckForFastRoaming(pAd);
if (rv == FALSE)
{
if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
{
DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
MlmeAutoScan(pAd);
}
}
}
}
}
else if (ADHOC_ON(pAd))
{
Adhoc_checkPeerBeaconLost(pAd);
}
else /* no INFRA nor ADHOC connection*/
{
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("STAMlmePeriodicExec, no association so far\n"));
#endif /* RELEASE_EXCLUDE */
#ifdef MESH_SUPPORT
if (MESH_ON(pAd))
goto SKIP_AUTO_SCAN_CONN;
#endif /* MESH_SUPPORT */
#ifdef P2P_SUPPORT
if (P2P_GO_ON(pAd) || P2P_CLI_ON(pAd))
goto SKIP_AUTO_SCAN_CONN;
#endif /* P2P_SUPPORT */
#ifdef WPA_SUPPLICANT_SUPPORT
if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & WPA_SUPPLICANT_ENABLE_WPS)
goto SKIP_AUTO_SCAN_CONN;
#endif /* WPA_SUPPLICANT_SUPPORT */
if (pAd->StaCfg.bSkipAutoScanConn &&
RTMP_TIME_BEFORE(pAd->Mlme.Now32, pAd->StaCfg.LastScanTime + (30 * OS_HZ)))
goto SKIP_AUTO_SCAN_CONN;
else
pAd->StaCfg.bSkipAutoScanConn = FALSE;
if ((pAd->StaCfg.bAutoReconnect == TRUE)
&& RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
&& (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE) && (pAd->CommonCfg.Channel != 0))
{
if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
#ifdef WIDI_SUPPORT /* This was giving trouble by turning off passive scanning */
&& (pAd->StaCfg.bWIDI == FALSE)
#endif /* WIDI_SUPPORT */
)
{
MLME_SCAN_REQ_STRUCT ScanReq;
if (RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastScanTime + (10 * OS_HZ))
||(pAd->StaCfg.bNotFirstScan == FALSE))
{
DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
if (pAd->StaCfg.BssType == BSS_ADHOC)
pAd->StaCfg.bNotFirstScan = TRUE;
ScanParmFill(pAd, &ScanReq, (RTMP_STRING *) pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0);
pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
/* Reset Missed scan number*/
pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
}
else
MlmeAutoReconnectLastSSID(pAd);
}
else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE
#ifdef DPA_S
/* Reduce the scan interval in Samsung TV, due to some flash disk can't be recognized */
&&
(RTMP_TIME_AFTER(pAd->Mlme.Now32, pAd->StaCfg.LastScanTime + (10 * OS_HZ))
#ifdef WIDI_SUPPORT
/* Reduce scan interval will impact the discoveribility of ra0 L2SD based sink; if we turn on ra0's widi, we can't reduce the scan interval!*/
||( pAd->StaCfg.bWIDI = TRUE)
#endif /* WIDI_SUPPORT */
)
#endif /* DPA_S */
)
{
#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier*/
if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
{
if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1)
MlmeAutoReconnectLastSSID(pAd);
}
else
#endif /* CARRIER_DETECTION_SUPPORT */
{
#ifdef WPA_SUPPLICANT_SUPPORT
if(pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE)
#endif // WPA_SUPPLICANT_SUPPORT //
MlmeAutoReconnectLastSSID(pAd);
}
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("pAd->StaCfg.bAutoReconnect is TRUE\n"));
#endif /* RELEASE_EXCLUDE */
}
}
}
SKIP_AUTO_SCAN_CONN:
#ifdef DOT11_N_SUPPORT
if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE)
&& (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
{
pAd->MacTab.fAnyBASession = TRUE;
AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
}
else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE)
&& (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
{
pAd->MacTab.fAnyBASession = FALSE;
AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
}
#endif /* DOT11_N_SUPPORT */
#ifdef MESH_SUPPORT
if(MESH_ON(pAd))
{
LONG idx;
/* period update Neighbor table.*/
NeighborTableUpdate(pAd);
/* update Mesh Link*/
MeshLinkTableMaintenace(pAd);
/* update Mesh multipath entry.*/
for (idx = 0; idx < MAX_MESH_LINKS; idx ++)
{
if (PeerLinkValidCheck(pAd, idx))
MultipathEntryMaintain(pAd, idx);
}
}
#endif /* MESH_SUPPORT */
//YF_TODO
#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) || defined(CFG80211_MULTI_STA)
#ifdef P2P_SUPPORT
if (P2P_CLI_ON(pAd))
#else
#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE
if (RTMP_CFG80211_VIF_P2P_CLI_ON(pAd))
#else
if ( RTMP_CFG80211_MULTI_STA_ON(pAd, pAd->cfg80211_ctrl.multi_sta_net_dev))
#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */
#endif /* P2P_SUPPORT */
{
if (pAd->Mlme.OneSecPeriodicRound % 2 == 0)
ApCliIfMonitor(pAd);
if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
ApCliIfUp(pAd);
ApCliSimulateRecvBeacon(pAd);
}
#endif /* P2P_SUPPORT || RT_CFG80211_P2P_CONCURRENT_DEVICE */
#ifdef DOT11_N_SUPPORT
#ifdef DOT11N_DRAFT3
/* Perform 20/40 BSS COEX scan every Dot11BssWidthTriggerScanInt */
if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040)) &&
(pAd->CommonCfg.Dot11BssWidthTriggerScanInt != 0) &&
((pAd->Mlme.OneSecPeriodicRound % pAd->CommonCfg.Dot11BssWidthTriggerScanInt) == (pAd->CommonCfg.Dot11BssWidthTriggerScanInt-1))
#if defined(MT7603_FPGA) || defined(MT7628_FPGA)
// TODO: shiang-MT7603, remove me after verification done!!
&& (pAd->fpga_ctl.fpga_on == 0)
#endif /* MT7603_FPGA */
)
{
DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - LastOneSecTotalTxCount/LastOneSecRxOkDataCnt = %d/%d \n",
pAd->RalinkCounters.LastOneSecTotalTxCount,
pAd->RalinkCounters.LastOneSecRxOkDataCnt));
/*
Check last scan time at least 30 seconds from now.
Check traffic is less than about 1.5~2Mbps.
it might cause data lost if we enqueue scanning.
This criteria needs to be considered
*/
if ((pAd->RalinkCounters.LastOneSecTotalTxCount < 70) && (pAd->RalinkCounters.LastOneSecRxOkDataCnt < 70))
{
MLME_SCAN_REQ_STRUCT ScanReq;
/* Fill out stuff for scan request and kick to scan*/
ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_2040_BSS_COEXIST);
MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0);
pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
/* Set InfoReq = 1, So after scan , alwats sebd 20/40 Coexistence frame to AP*/
pAd->CommonCfg.BSSCoexist2040.field.InfoReq = 1;
RTMP_MLME_HANDLER(pAd);
}
DBGPRINT(RT_DEBUG_TRACE, (" LastOneSecTotalTxCount/LastOneSecRxOkDataCnt = %d/%d \n",
pAd->RalinkCounters.LastOneSecTotalTxCount,
pAd->RalinkCounters.LastOneSecRxOkDataCnt));
}
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
return;
}
/* Link down report*/
VOID LinkDownExec(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
if (pAd != NULL)
{
MLME_DISASSOC_REQ_STRUCT DisassocReq;
if ((pAd->StaCfg.wdev.PortSecured == WPA_802_1X_PORT_NOT_SECURED) &&
(INFRA_ON(pAd)))
{
DBGPRINT(RT_DEBUG_TRACE, ("LinkDownExec(): disassociate with current AP...\n"));
DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq, 0);
pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected);
pAd->ExtraInfo = GENERAL_LINK_DOWN;
}
}
}
VOID MlmeAutoScan(RTMP_ADAPTER *pAd)
{
if (pAd->MlmeAux.AutoReconnectSsidLen > MAX_LEN_OF_SSID) {
DBGPRINT(RT_DEBUG_ERROR,
("%s(): invalid SsidLen(%d)\n",
__func__, pAd->MlmeAux.AutoReconnectSsidLen));
return;
}
/* check CntlMachine.CurrState to avoid collision with NDIS SetOID request*/
if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
{
DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
OID_802_11_BSSID_LIST_SCAN,
pAd->MlmeAux.AutoReconnectSsidLen,
pAd->MlmeAux.AutoReconnectSsid, 0);
RTMP_MLME_HANDLER(pAd);
}
}
VOID MlmeAutoReconnectLastSSID(RTMP_ADAPTER *pAd)
{
#ifdef WSC_STA_SUPPORT
WSC_CTRL *pWscControl = &pAd->StaCfg.WscControl;
if ((pWscControl->WscConfMode != WSC_DISABLE) &&
(pWscControl->bWscTrigger) &&
(pWscControl->WscMode == WSC_PBC_MODE) &&
(pWscControl->WscPBCBssCount != 1))
return;
if ((pWscControl->WscConfMode != WSC_DISABLE) &&
(pWscControl->WscState >= WSC_STATE_START))
{
ULONG ApIdx = 0;
ApIdx = WscSearchWpsApBySSID(pAd,
pWscControl->WscSsid.Ssid,
pWscControl->WscSsid.SsidLength,
pWscControl->WscMode);
if ((ApIdx != BSS_NOT_FOUND) &&
(pAd->StaCfg.BssType == BSS_INFRA))
{
NdisMoveMemory(pWscControl->WscBssid, pAd->ScanTab.BssEntry[ApIdx].Bssid, MAC_ADDR_LEN);
pAd->MlmeAux.Channel = pAd->ScanTab.BssEntry[ApIdx].Channel;
}
CntlWscIterate(pAd);
}
else
#endif /* WSC_STA_SUPPORT */
if (pAd->StaCfg.bAutoConnectByBssid)
{
DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_BSSID setting - %02X:%02X:%02X:%02X:%02X:%02X\n",
PRINT_MAC(pAd->MlmeAux.Bssid)));
pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
OID_802_11_BSSID,
MAC_ADDR_LEN,
pAd->MlmeAux.Bssid, 0);
pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
RTMP_MLME_HANDLER(pAd);
}
/* check CntlMachine.CurrState to avoid collision with NDIS SetOID request*/
else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
(MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
{
NDIS_802_11_SSID OidSsid;
OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n",
pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
OID_802_11_SSID,
sizeof(NDIS_802_11_SSID),
&OidSsid, 0);
RTMP_MLME_HANDLER(pAd);
}
}
/*
==========================================================================
Description:
This routine checks if there're other APs out there capable for
roaming. Caller should call this routine only when Link up in INFRA mode
and channel quality is below CQI_GOOD_THRESHOLD.
IRQL = DISPATCH_LEVEL
Output:
==========================================================================
*/
VOID MlmeCheckForRoaming(RTMP_ADAPTER *pAd, ULONG Now32)
{
USHORT i;
BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
BSS_ENTRY *pBss;
DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
/* put all roaming candidates into RoamTab, and sort in RSSI order*/
BssTableInit(pRoamTab);
for (i = 0; i < pAd->ScanTab.BssNr; i++)
{
pBss = &pAd->ScanTab.BssEntry[i];
if (RTMP_TIME_AFTER(Now32, pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime))
continue; /* AP disappear*/
if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
continue; /* RSSI too weak. forget it.*/
if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
continue; /* skip current AP*/
if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi[0] + RSSI_DELTA))
continue; /* only AP with stronger RSSI is eligible for roaming*/
/* AP passing all above rules is put into roaming candidate table */
NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
pRoamTab->BssNr += 1;
}
if (pRoamTab->BssNr > 0)
{
/* check CntlMachine.CurrState to avoid collision with NDIS SetOID request*/
if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
{
pAd->RalinkCounters.PoorCQIRoamingCount ++;
DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL, 0);
RTMP_MLME_HANDLER(pAd);
}
}
DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
}
/*
==========================================================================
Description:
This routine checks if there're other APs out there capable for
roaming. Caller should call this routine only when link up in INFRA mode
and channel quality is below CQI_GOOD_THRESHOLD.
IRQL = DISPATCH_LEVEL
Output:
==========================================================================
*/
BOOLEAN MlmeCheckForFastRoaming(RTMP_ADAPTER *pAd)
{
USHORT i;
BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
BSS_ENTRY *pBss;
CHAR max_rssi;
DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
/* put all roaming candidates into RoamTab, and sort in RSSI order*/
BssTableInit(pRoamTab);
for (i = 0; i < pAd->ScanTab.BssNr; i++)
{
pBss = &pAd->ScanTab.BssEntry[i];
if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
continue; /* RSSI too weak. forget it.*/
if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
continue; /* skip current AP*/
if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
continue; /* skip different SSID*/
max_rssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi[0], pAd->StaCfg.RssiSample.LastRssi[1], pAd->StaCfg.RssiSample.LastRssi[2]);
if (pBss->Rssi < (max_rssi + RSSI_DELTA))
continue; /* skip AP without better RSSI*/
DBGPRINT(RT_DEBUG_TRACE, ("max_rssi = %d, pBss->Rssi = %d\n", max_rssi, pBss->Rssi));
/* AP passing all above rules is put into roaming candidate table */
NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
pRoamTab->BssNr += 1;
}
DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
if (pRoamTab->BssNr > 0)
{
/* check CntlMachine.CurrState to avoid collision with NDIS SetOID request*/
if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
{
pAd->RalinkCounters.PoorCQIRoamingCount ++;
DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL, 0);
RTMP_MLME_HANDLER(pAd);
return TRUE;
}
}
return FALSE;
}
/*
==========================================================================
Description:
This routine is executed periodically inside MlmePeriodicExec() after
association with an AP.
It checks if StaCfg.PwrMgmt.Psm is consistent with user policy (recorded in
StaCfg.WindowsPowerMode). If not, enforce user policy. However,
there're some conditions to consider:
1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
the time when Mibss==TRUE
2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
if outgoing traffic available in TxRing or MgmtRing.
Output:
1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID MlmeCheckPsmChange(RTMP_ADAPTER *pAd, ULONG Now32)
{
ULONG PowerMode;
/*
condition -
1. Psm maybe ON only happen in INFRASTRUCTURE mode
2. user wants either MAX_PSP or FAST_PSP
3. but current psm is not in PWR_SAVE
4. CNTL state machine is not doing SCANning
5. no TX SUCCESS event for the past 1-sec period
*/
PowerMode = pAd->StaCfg.WindowsPowerMode;
if (PowerMode != Ndis802_11PowerModeCAM)
{
DBGPRINT(RT_DEBUG_TRACE, ("%s:: (%d, %d, %d, %d, %d)\n",
__FUNCTION__,
INFRA_ON(pAd),
(PowerMode != Ndis802_11PowerModeCAM),
(pAd->StaCfg.PwrMgmt.Psm),
(pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE),
(pAd->CountDowntoPsm == 0)));
}
if (INFRA_ON(pAd) &&
(PowerMode != Ndis802_11PowerModeCAM) &&
#ifdef STA_LP_PHASE_1_SUPPORT
/* In Legacy_PSP, Psm is always PWR_ACTIVE, if driver wakes up H/W and H/W needs to enter sleep mode,
driver needs to bypass this condition OR H/W can not enter sleep again */
#else
(pAd->StaCfg.PwrMgmt.Psm == PWR_ACTIVE) &&
#endif /* STA_LP_PHASE_1_SUPPORT */
/* (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))*/
(pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
#ifdef PCIE_PS_SUPPORT
&& RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)
#endif /* PCIE_PS_SUPPORT */
&& (pAd->CountDowntoPsm == 0)
/*&&
(pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
(pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
{
NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
pAd->RalinkCounters.RxCountSinceLastNULL = 0;
#ifdef CONFIG_PM_BIT_HW_MODE
//CmdExtPwrMgtBitWifi(pAd, BSSID_WCID, PWR_SAVE);
#endif /* CONFIG_PM_BIT_HW_MODE */
RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
#if 0
if (!(pAd->StaCfg.wdev.UapsdInfo.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
{
RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE), pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.PwrMgmt.Psm);
}
else
{
RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, pAd->CommonCfg.bAPSDForcePowerSave ? PWR_SAVE : pAd->StaCfg.PwrMgmt.Psm);
}
#else
DBGPRINT(RT_DEBUG_TRACE, ("%s:: This is enter PSM NULL\n", __FUNCTION__));
RTMPSetEnterPsmNullBit(&pAd->StaCfg.PwrMgmt);
DBGPRINT(RT_DEBUG_TRACE, ("%s::bEnterPsmNull(%d)\n", __FUNCTION__, pAd->StaCfg.PwrMgmt.bEnterPsmNull));
RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, PWR_SAVE);
#endif
#ifdef WMM_ACM_SUPPORT
/*
Can not limit retry count for PS mode;
Or in WMM ACM UAPSD test, test will fail if any packet is lost.
*/
ACMP_RetryCountCtrl(pAd);
#endif /* WMM_ACM_SUPPORT */
}
}
VOID MlmeSetPsmBit(RTMP_ADAPTER *pAd, USHORT psm)
{
#if 0
AUTO_RSP_CFG_STRUC csr4;
#endif
#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT)
USHORT PsmOld = pAd->StaCfg.PwrMgmt.Psm;
#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */
pAd->StaCfg.PwrMgmt.Psm = psm;
#ifdef DOT11Z_TDLS_SUPPORT
/* pAd->StaCfg.PwrMgmt.Psm must be updated before calling the function */
TDLS_UAPSDP_PsmModeChange(pAd, PsmOld, psm);
#endif /* DOT11Z_TDLS_SUPPORT */
#ifdef CFG_TDLS_SUPPORT
#ifdef UAPSD_SUPPORT
cfg_tdls_UAPSDP_PsmModeChange(pAd, PsmOld, psm);
#endif /*UAPSD_SUPPORT*/
#endif /* CFG_TDLS_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
}
#endif /* CONFIG_STA_SUPPORT */
VOID RTMPSetEnterPsmNullBit(PPWR_MGMT_STRUCT pPwrMgmt)
{
//pAd->StaCfg.PwrMgmt.bEnterPsmNull = TRUE;
pPwrMgmt->bEnterPsmNull = TRUE;
}
VOID RTMPClearEnterPsmNullBit(PPWR_MGMT_STRUCT pPwrMgmt)
{
//pAd->StaCfg.PwrMgmt.bEnterPsmNull = FALSE;
pPwrMgmt->bEnterPsmNull = FALSE;
}
BOOLEAN RTMPEnterPsmNullBitStatus(PPWR_MGMT_STRUCT pPwrMgmt)
{
//return (pAd->StaCfg.PwrMgmt.bEnterPsmNull);
return (pPwrMgmt->bEnterPsmNull);
}
/*
==========================================================================
Description:
This routine calculates TxPER, RxPER of the past N-sec period. And
according to the calculation result, ChannelQuality is calculated here
to decide if current AP is still doing the job.
If ChannelQuality is not good, a ROAMing attempt may be tried later.
Output:
StaCfg.ChannelQuality - 0..100
IRQL = DISPATCH_LEVEL
NOTE: This routine decide channle quality based on RX CRC error ratio.
Caller should make sure a function call to NICUpdateRawCounters(pAd)
is performed right before this routine, so that this routine can decide
channel quality based on the most up-to-date information
==========================================================================
*/
VOID MlmeCalculateChannelQuality(
IN PRTMP_ADAPTER pAd,
IN PMAC_TABLE_ENTRY pMacEntry,
IN ULONG Now32)
{
ULONG TxOkCnt, TxCnt/*, TxPER*/, TxPRR;
ULONG RxCnt, RxPER;
UCHAR NorRssi;
CHAR MaxRssi;
RSSI_SAMPLE *pRssiSample = NULL;
UINT32 OneSecTxNoRetryOkCount = 0;
UINT32 OneSecTxRetryOkCount = 0;
UINT32 OneSecTxFailCount = 0;
UINT32 OneSecRxOkCnt = 0;
UINT32 OneSecRxFcsErrCnt = 0;
ULONG ChannelQuality = 0; /* 0..100, Channel Quality Indication for Roaming*/
#ifdef CONFIG_STA_SUPPORT
ULONG LastBeaconRxTime = 0;
ULONG BeaconLostTime = pAd->StaCfg.BeaconLostTime;
#endif /* CONFIG_STA_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier*/
/* longer beacon lost time when carrier detection enabled*/
if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
{
BeaconLostTime = pAd->StaCfg.BeaconLostTime + (pAd->StaCfg.BeaconLostTime/2);
}
#endif /* CARRIER_DETECTION_SUPPORT */
#ifdef APCLI_SUPPORT
if (pMacEntry && IS_ENTRY_APCLI(pMacEntry) && (pMacEntry->func_tb_idx < MAX_APCLI_NUM))
LastBeaconRxTime = pAd->ApCfg.ApCliTab[pMacEntry->func_tb_idx].ApCliRcvBeaconTime;
else
#endif /*APCLI_SUPPORT*/
LastBeaconRxTime = pAd->StaCfg.LastBeaconRxTime;
#endif /* CONFIG_STA_SUPPORT */
if (pMacEntry != NULL)
{
pRssiSample = &pMacEntry->RssiSample;
OneSecTxNoRetryOkCount = pMacEntry->OneSecTxNoRetryOkCount;
OneSecTxRetryOkCount = pMacEntry->OneSecTxRetryOkCount;
OneSecTxFailCount = pMacEntry->OneSecTxFailCount;
OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
}
else
{
pRssiSample = &pAd->MacTab.Content[0].RssiSample;
OneSecTxNoRetryOkCount = pAd->RalinkCounters.OneSecTxNoRetryOkCount;
OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount;
OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount;
OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
}
if (pRssiSample == NULL)
return;
MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi[0],
pRssiSample->LastRssi[1],
pRssiSample->LastRssi[2]);
/*
calculate TX packet error ratio and TX retry ratio - if too few TX samples,
skip TX related statistics
*/
TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount;
TxCnt = TxOkCnt + OneSecTxFailCount;
if (TxCnt < 5)
{
//TxPER = 0;
TxPRR = 0;
}
else
{
//TxPER = (OneSecTxFailCount * 100) / TxCnt;
TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt;
}
/* calculate RX PER - don't take RxPER into consideration if too few sample*/
RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt;
if (RxCnt < 5)
RxPER = 0;
else
RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt;
#if (defined(STA_LP_PHASE_1_SUPPORT) || defined(STA_LP_PHASE_2_SUPPORT)) && defined(CONFIG_STA_SUPPORT)
if (INFRA_ON(pAd) && pMacEntry && (pMacEntry->wcid == BSSID_WCID) &&
(pAd->StaCfg.PwrMgmt.bBeaconLost) &&
OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
{
pAd->Mlme.ChannelQuality = 0;
DBGPRINT(RT_DEBUG_TRACE, ("%s::MT7636 BEACON lost meet\n", __FUNCTION__));
}
else
#endif
{
/* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER*/
#ifdef CONFIG_STA_SUPPORT
if ((pAd->OpMode == OPMODE_STA) &&
#if (defined(STA_LP_PHASE_1_SUPPORT) ||defined(STA_LP_PHASE_2_SUPPORT)) && defined(CONFIG_STA_SUPPORT)
(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) &&
#endif
INFRA_ON(pAd) &&
(OneSecTxNoRetryOkCount < 2) && /* no heavy traffic*/
RTMP_TIME_AFTER(Now32, LastBeaconRxTime + BeaconLostTime))
{
#ifdef RELEASE_EXCLUDE
/*
Bug history:
1. Samsung 2009/07/02
Sometimes beacon will lost and re-connect to the AP.
They use the channel 161 for RT3572 to do test.
Some channels are bad for RT3572.
*/
#endif /* RELEASE_EXCLUDE */
DBGPRINT(RT_DEBUG_OFF, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime * (1000 / OS_HZ) , TxOkCnt));
ChannelQuality = 0;
}
else
#endif /* CONFIG_STA_SUPPORT */
{
/* Normalize Rssi*/
if (MaxRssi > -40)
NorRssi = 100;
else if (MaxRssi < -90)
NorRssi = 0;
else
NorRssi = (MaxRssi + 90) * 2;
/* ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)*/
ChannelQuality = (RSSI_WEIGHTING * NorRssi +
TX_WEIGHTING * (100 - TxPRR) +
RX_WEIGHTING* (100 - RxPER)) / 100;
}
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("MMCHK - CQI= %ld (Tx Fail=%u/Retry=%u/Total=%lu, Rx Fail=%u/Total=%lu, RSSI=%d dbm)\n",
ChannelQuality,
OneSecTxFailCount,
OneSecTxRetryOkCount,
TxCnt,
OneSecRxFcsErrCnt,
RxCnt, MaxRssi));
#endif /* RELEASE_EXCLUDE */
}
#ifdef CONFIG_STA_SUPPORT
if (pAd->OpMode == OPMODE_STA)
pAd->Mlme.ChannelQuality = (ChannelQuality > 100) ? 100 : ChannelQuality;
#endif /* CONFIG_STA_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
if (pAd->OpMode == OPMODE_AP)
{
if (pMacEntry != NULL)
pMacEntry->ChannelQuality = (ChannelQuality > 100) ? 100 : ChannelQuality;
}
#endif /* CONFIG_AP_SUPPORT */
}
VOID MlmeSetTxPreamble(RTMP_ADAPTER *pAd, USHORT TxPreamble)
{
/* Always use Long preamble before verifiation short preamble functionality works well.*/
/* Todo: remove the following line if short preamble functionality works*/
if (TxPreamble == Rt802_11PreambleLong)
{
OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
}
else
{
/* NOTE: 1Mbps should always use long preamble*/
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
}
DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble = %s PREAMBLE\n",
((TxPreamble == Rt802_11PreambleLong) ? "LONG" : "SHORT")));
AsicSetTxPreamble(pAd, TxPreamble);
}
/*
==========================================================================
Description:
Update basic rate bitmap
==========================================================================
*/
VOID UpdateBasicRateBitmap(RTMP_ADAPTER *pAdapter)
{
INT i, j;
/* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
/* if A mode, always use fix BasicRateBitMap */
/*if (pAdapter->CommonCfg.Channel == WMODE_A)*/
if (pAdapter->CommonCfg.Channel > 14)
{
if (pAdapter->CommonCfg.BasicRateBitmap & 0xF)
{
/* no 11b rate in 5G band */
pAdapter->CommonCfg.BasicRateBitmapOld = \
pAdapter->CommonCfg.BasicRateBitmap;
pAdapter->CommonCfg.BasicRateBitmap &= (~0xF); /* no 11b */
}
/* force to 6,12,24M in a-band */
pAdapter->CommonCfg.BasicRateBitmap |= 0x150; /* 6, 12, 24M */
}
else
{
/* no need to modify in 2.4G (bg mixed) */
pAdapter->CommonCfg.BasicRateBitmap = \
pAdapter->CommonCfg.BasicRateBitmapOld;
}
if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
{
/* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
return;
}
for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
{
sup_p[i] &= 0x7f;
ext_p[i] &= 0x7f;
}
for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
{
if (bitmap & (1 << i))
{
for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
{
if (sup_p[j] == rate[i])
sup_p[j] |= 0x80;
}
for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
{
if (ext_p[j] == rate[i])
ext_p[j] |= 0x80;
}
}
}
}
/*
bLinkUp is to identify the inital link speed.
TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
*/
VOID MlmeUpdateTxRates(RTMP_ADAPTER *pAd, BOOLEAN bLinkUp, UCHAR apidx)
{
int i, num;
UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
UCHAR MinSupport = RATE_54;
ULONG BasicRateBitmap = 0;
UCHAR CurrBasicRate = RATE_1;
UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
HTTRANSMIT_SETTING *pHtPhy = NULL, *pMaxHtPhy = NULL, *pMinHtPhy = NULL;
BOOLEAN *auto_rate_cur_p;
UCHAR HtMcs = MCS_AUTO;
struct wifi_dev *wdev = NULL;
/* find max desired rate*/
UpdateBasicRateBitmap(pAd);
num = 0;
auto_rate_cur_p = NULL;
for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
{
switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
{
case 2: Rate = RATE_1; num++; break;
case 4: Rate = RATE_2; num++; break;
case 11: Rate = RATE_5_5; num++; break;
case 22: Rate = RATE_11; num++; break;
case 12: Rate = RATE_6; num++; break;
case 18: Rate = RATE_9; num++; break;
case 24: Rate = RATE_12; num++; break;
case 36: Rate = RATE_18; num++; break;
case 48: Rate = RATE_24; num++; break;
case 72: Rate = RATE_36; num++; break;
case 96: Rate = RATE_48; num++; break;
case 108: Rate = RATE_54; num++; break;
/*default: Rate = RATE_1; break;*/
}
if (MaxDesire < Rate) MaxDesire = Rate;
}
/*===========================================================================*/
do
{
#ifdef CONFIG_AP_SUPPORT
#ifdef RT_CFG80211_P2P_SUPPORT
if (apidx >= MIN_NET_DEVICE_FOR_CFG80211_VIF_P2P_GO)
{
DBGPRINT(RT_DEBUG_INFO, ("%s: Update for GO\n", __func__));
wdev = &pAd->ApCfg.MBSSID[CFG_GO_BSSID_IDX].wdev;
break;
}
#endif /* RT_CFG80211_P2P_SUPPORT */
#ifdef P2P_SUPPORT
if (apidx >= MIN_NET_DEVICE_FOR_P2P_GO)
{
UCHAR idx = apidx - MIN_NET_DEVICE_FOR_P2P_GO;
wdev = &pAd->ApCfg.MBSSID[idx].wdev;
break;
}
#endif /* P2P_SUPPORT */
#ifdef MESH_SUPPORT
if (apidx >= MIN_NET_DEVICE_FOR_MESH)
{
wdev = &pAd->MeshTab.wdev;
break;
}
#endif /* MESH_SUPPORT */
#ifdef APCLI_SUPPORT
if (apidx >= MIN_NET_DEVICE_FOR_APCLI)
{
UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI;
if (idx < MAX_APCLI_NUM)
{
wdev = &pAd->ApCfg.ApCliTab[idx].wdev;
break;
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid idx(%d)\n", __FUNCTION__, idx));
return;
}
}
#endif /* APCLI_SUPPORT */
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
#ifdef WDS_SUPPORT
if (apidx >= MIN_NET_DEVICE_FOR_WDS)
{
UCHAR idx = apidx - MIN_NET_DEVICE_FOR_WDS;
if (idx < MAX_WDS_ENTRY)
{
wdev = &pAd->WdsTab.WdsEntry[idx].wdev;
break;
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx));
return;
}
}
#endif /* WDS_SUPPORT */
if ((apidx < pAd->ApCfg.BssidNum) &&
(apidx < MAX_MBSSID_NUM(pAd)) &&
(apidx < HW_BEACON_MAX_NUM))
{
wdev = &pAd->ApCfg.MBSSID[apidx].wdev;
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx));
}
break;
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
wdev = &pAd->StaCfg.wdev;
if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B) &&
(MaxDesire > RATE_11))
{
MaxDesire = RATE_11;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO,("%s():. 2 MaxDesire = %d. OpMode=%d\n", __FUNCTION__, MaxDesire, pAd->OpMode));
#endif /* RELEASE_EXCLUDE */
}
break;
}
#endif /* CONFIG_STA_SUPPORT */
} while(FALSE);
if (wdev)
{
pHtPhy = &wdev->HTPhyMode;
pMaxHtPhy = &wdev->MaxHTPhyMode;
pMinHtPhy = &wdev->MinHTPhyMode;
auto_rate_cur_p = &wdev->bAutoTxRateSwitch;
HtMcs = (UCHAR)wdev->DesiredTransmitSetting.field.MCS;
}
pAd->CommonCfg.MaxDesiredRate = MaxDesire;
if (pMinHtPhy == NULL)
return;
pMinHtPhy->word = 0;
pMaxHtPhy->word = 0;
pHtPhy->word = 0;
/*
Auto rate switching is enabled only if more than one DESIRED RATES are
specified; otherwise disabled
*/
if (num <= 1)
*auto_rate_cur_p = FALSE;
else
*auto_rate_cur_p = TRUE;
if (HtMcs != MCS_AUTO)
*auto_rate_cur_p = FALSE;
else
*auto_rate_cur_p = TRUE;
#ifdef CONFIG_STA_SUPPORT
if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)
#ifdef P2P_SUPPORT
&& (apidx == MIN_NET_DEVICE_FOR_MBSSID)
#endif /* P2P_SUPPORT */
)
{
pSupRate = &pAd->StaActive.SupRate[0];
pExtRate = &pAd->StaActive.ExtRate[0];
SupRateLen = pAd->StaActive.SupRateLen;
ExtRateLen = pAd->StaActive.ExtRateLen;
}
else
#endif /* CONFIG_STA_SUPPORT */
{
pSupRate = &pAd->CommonCfg.SupRate[0];
pExtRate = &pAd->CommonCfg.ExtRate[0];
SupRateLen = pAd->CommonCfg.SupRateLen;
ExtRateLen = pAd->CommonCfg.ExtRateLen;
}
/* find max supported rate */
for (i=0; i<SupRateLen; i++)
{
switch (pSupRate[i] & 0x7f)
{
case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 0; break;
case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 1; break;
case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 2; break;
case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 3; break;
case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 1 << 4; break;
case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 5; break;
case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 1 << 6; break;
case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 7; break;
case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 1 << 8; break;
case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 9; break;
case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 10; break;
case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 11; break;
default: Rate = RATE_1; break;
}
if (MaxSupport < Rate)
MaxSupport = Rate;
if (MinSupport > Rate)
MinSupport = Rate;
}
for (i=0; i<ExtRateLen; i++)
{
switch (pExtRate[i] & 0x7f)
{
case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 0; break;
case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 1; break;
case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 2; break;
case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 3; break;
case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 1 << 4; break;
case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 5; break;
case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 1 << 6; break;
case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 7; break;
case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 1 << 8; break;
case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 9; break;
case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 10; break;
case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 11; break;
default: Rate = RATE_1;
break;
}
if (MaxSupport < Rate)
MaxSupport = Rate;
if (MinSupport > Rate)
MinSupport = Rate;
}
// TODO: shiang-7603, need to revise for MT7603!!
#if defined(MT7603) || defined(MT7628)
if (IS_MT7603(pAd) || IS_MT7628(pAd))
;
else
#endif /* MT7603 */
{
RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
}
#ifdef RELEASE_EXCLUDE
/* bug fix
pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap;
calculate the exptected ACK rate for each TX rate. This info is used to caculate
the DURATION field of outgoing unicast DATA/MGMT frame
*/
#endif /* RELEASE_EXCLUDE */
for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
{
if (BasicRateBitmap & (0x01 << i))
CurrBasicRate = (UCHAR)i;
pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO,("Exptected ACK rate[%d] = %d Mbps\n", RateIdToMbps[i], RateIdToMbps[CurrBasicRate]));
#endif /* RELEASE_EXCLUDE */
}
DBGPRINT(RT_DEBUG_TRACE,("%s():[MaxSupport = %d] = MaxDesire %d Mbps\n",
__FUNCTION__, RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
/* max tx rate = min {max desire rate, max supported rate}*/
if (MaxSupport < MaxDesire)
pAd->CommonCfg.MaxTxRate = MaxSupport;
else
pAd->CommonCfg.MaxTxRate = MaxDesire;
pAd->CommonCfg.MinTxRate = MinSupport;
/*
2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
on average RSSI
1. RSSI >= -70db, start at 54 Mbps (short distance)
2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
3. -75 > RSSI, start at 11 Mbps (long distance)
*/
if (*auto_rate_cur_p)
{
short dbm = 0;
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
dbm = pAd->StaCfg.RssiSample.AvgRssi[0] - pAd->BbpRssiToDbmDelta;
#endif /* CONFIG_STA_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
dbm =0;
#endif /* CONFIG_AP_SUPPORT */
if (bLinkUp == TRUE)
pAd->CommonCfg.TxRate = RATE_24;
else
pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
if (dbm < -75)
pAd->CommonCfg.TxRate = RATE_11;
else if (dbm < -70)
pAd->CommonCfg.TxRate = RATE_24;
/* should never exceed MaxTxRate (consider 11B-only mode)*/
if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
pAd->CommonCfg.TxRateIndex = 0;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_TRACE, (" %s(): (Rssi=%d, init TX rate = %d Mbps)\n",
__FUNCTION__, dbm, RateIdToMbps[pAd->CommonCfg.TxRate]));
#endif /* RELEASE_EXCLUDE */
#ifdef RT3593
/*Enable AutoFallback ; RT3593 support disable Tx auto fallback per packet*/
RT3593_AUTO_FALLBACK_ENABLE(pAd);
#endif /* RT3593 */
}
else
{
pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
/* Choose the Desire Tx MCS in CCK/OFDM mode */
if (num > RATE_6)
{
if (HtMcs <= MCS_7)
MaxDesire = RxwiMCSToOfdmRate[HtMcs];
else
MaxDesire = MinSupport;
}
else
{
if (HtMcs <= MCS_3)
MaxDesire = HtMcs;
else
MaxDesire = MinSupport;
}
pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
#ifdef RT3593
/*Disable AutoFallback; RT3593 support disable Tx auto fallback per packet*/
if (!IS_RT3593(pAd))
AsicSetAutoFallBack(pAd, FALSE);
#endif /* RT3593 */
}
if (pAd->CommonCfg.TxRate <= RATE_11)
{
pMaxHtPhy->field.MODE = MODE_CCK;
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
}
#endif /* CONFIG_STA_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
pMaxHtPhy->field.MCS = MaxDesire;
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef P2P_SUPPORT
if (apidx >= MIN_NET_DEVICE_FOR_APCLI)
pMaxHtPhy->field.MCS = MaxDesire;
#endif /* P2P_SUPPORT */
}
else
{
pMaxHtPhy->field.MODE = MODE_OFDM;
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];
else
pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
}
#endif /* CONFIG_STA_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[MaxDesire];
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef P2P_SUPPORT
if (apidx >= MIN_NET_DEVICE_FOR_APCLI)
pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[MaxDesire];
#endif /* P2P_SUPPORT */
}
pHtPhy->word = (pMaxHtPhy->word);
if (bLinkUp && (pAd->OpMode == OPMODE_STA))
{
pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
}
else
{
if (WMODE_CAP(pAd->CommonCfg.PhyMode, WMODE_B) &&
pAd->CommonCfg.Channel <= 14)
{
pAd->CommonCfg.MlmeRate = RATE_1;
pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
pAd->CommonCfg.RtsRate = RATE_11;
}
else
{
pAd->CommonCfg.MlmeRate = RATE_6;
pAd->CommonCfg.RtsRate = RATE_6;
pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
}
/* Keep Basic Mlme Rate.*/
pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
else
pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
#ifdef CONFIG_AP_SUPPORT
#ifdef MCAST_RATE_SPECIFIC
{
/* set default value if MCastPhyMode is not initialized */
HTTRANSMIT_SETTING tPhyMode;
memset(&tPhyMode, 0, sizeof(HTTRANSMIT_SETTING));
if (memcmp(&pAd->CommonCfg.MCastPhyMode, &tPhyMode, sizeof(HTTRANSMIT_SETTING)) == 0)
{
memmove(&pAd->CommonCfg.MCastPhyMode, &pAd->MacTab.Content[MCAST_WCID].HTPhyMode,
sizeof(HTTRANSMIT_SETTING));
}
}
#endif /* MCAST_RATE_SPECIFIC */
#endif /* CONFIG_AP_SUPPORT */
}
DBGPRINT(RT_DEBUG_TRACE, (" %s(): (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
__FUNCTION__, RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport],
RateIdToMbps[pAd->CommonCfg.MaxTxRate],
RateIdToMbps[pAd->CommonCfg.MinTxRate],
/*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
DBGPRINT(RT_DEBUG_TRACE, (" %s(): (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
__FUNCTION__, RateIdToMbps[pAd->CommonCfg.TxRate],
RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
DBGPRINT(RT_DEBUG_TRACE, ("%s(): (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
__FUNCTION__, pAd->CommonCfg.MlmeTransmit.word,
pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word,
pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word,
pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word ));
}
#ifdef DOT11_N_SUPPORT
/*
==========================================================================
Description:
This function update HT Rate setting.
Input Wcid value is valid for 2 case :
1. it's used for Station in infra mode that copy AP rate to Mactable.
2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID MlmeUpdateHtTxRates(RTMP_ADAPTER *pAd, UCHAR apidx)
{
//UCHAR StbcMcs;
RT_HT_CAPABILITY *pRtHtCap = NULL;
RT_PHY_INFO *pActiveHtPhy = NULL;
//ULONG BasicMCS;
RT_PHY_INFO *pDesireHtPhy = NULL;
PHTTRANSMIT_SETTING pHtPhy = NULL;
PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
PHTTRANSMIT_SETTING pMinHtPhy = NULL;
BOOLEAN *auto_rate_cur_p;
struct wifi_dev *wdev = NULL;
DBGPRINT(RT_DEBUG_TRACE,("%s()===> \n", __FUNCTION__));
auto_rate_cur_p = NULL;
do
{
#ifdef CONFIG_AP_SUPPORT
#ifdef P2P_SUPPORT
if (apidx >= MIN_NET_DEVICE_FOR_P2P_GO)
{
UCHAR idx = apidx - MIN_NET_DEVICE_FOR_P2P_GO;
wdev = &pAd->ApCfg.MBSSID[idx].wdev;
break;
}
#endif /* P2P_SUPPORT */
#ifdef MESH_SUPPORT
if (apidx >= MIN_NET_DEVICE_FOR_MESH)
{
wdev = &pAd->MeshTab.wdev;
break;
}
#endif /* MESH_SUPPORT */
#ifdef APCLI_SUPPORT
if (apidx >= MIN_NET_DEVICE_FOR_APCLI)
{
UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI;
if (idx < MAX_APCLI_NUM)
{
wdev = &pAd->ApCfg.ApCliTab[idx].wdev;
break;
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid idx(%d)\n", __FUNCTION__, idx));
return;
}
}
#endif /* APCLI_SUPPORT */
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
#ifdef WDS_SUPPORT
if (apidx >= MIN_NET_DEVICE_FOR_WDS)
{
UCHAR idx = apidx - MIN_NET_DEVICE_FOR_WDS;
if (idx < MAX_WDS_ENTRY)
{
wdev = &pAd->WdsTab.WdsEntry[idx].wdev;
break;
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx));
return;
}
}
#endif /* WDS_SUPPORT */
if ((apidx < pAd->ApCfg.BssidNum) && (apidx < HW_BEACON_MAX_NUM))
wdev = &pAd->ApCfg.MBSSID[apidx].wdev;
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx));
}
break;
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
wdev = &pAd->StaCfg.wdev;
break;
}
#endif /* CONFIG_STA_SUPPORT */
} while (FALSE);
if (wdev)
{
pDesireHtPhy = &wdev->DesiredHtPhyInfo;
pActiveHtPhy = &wdev->DesiredHtPhyInfo;
pHtPhy = &wdev->HTPhyMode;
pMaxHtPhy = &wdev->MaxHTPhyMode;
pMinHtPhy = &wdev->MinHTPhyMode;
auto_rate_cur_p = &wdev->bAutoTxRateSwitch;
}
#ifdef CONFIG_STA_SUPPORT
if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)
#ifdef P2P_SUPPORT
&& (apidx == BSS0)
#endif /* P2P_SUPPORT */
)
{
if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
return;
pRtHtCap = &pAd->StaActive.SupportedHtPhy;
pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
//StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
//BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
pMaxHtPhy->field.STBC = STBC_USE;
else
pMaxHtPhy->field.STBC = STBC_NONE;
}
else
#endif /* CONFIG_STA_SUPPORT */
{
if ((!pDesireHtPhy) || pDesireHtPhy->bHtEnable == FALSE)
return;
pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
//StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
//BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pAd->Antenna.field.TxPath >= 2))
pMaxHtPhy->field.STBC = STBC_USE;
else
pMaxHtPhy->field.STBC = STBC_NONE;
}
/* Decide MAX ht rate.*/
if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
else
pMaxHtPhy->field.MODE = MODE_HTMIX;
if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
pMaxHtPhy->field.BW = BW_40;
else
pMaxHtPhy->field.BW = BW_20;
if (pMaxHtPhy->field.BW == BW_20)
pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
else
pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
if (pDesireHtPhy->MCSSet[4] != 0)
{
pMaxHtPhy->field.MCS = 32;
}
pMaxHtPhy->field.MCS = (USHORT)get_ht_max_mcs(pAd, &pDesireHtPhy->MCSSet[0],
&pActiveHtPhy->MCSSet[0]);
/* Copy MIN ht rate. rt2860???*/
pMinHtPhy->field.BW = BW_20;
pMinHtPhy->field.MCS = 0;
pMinHtPhy->field.STBC = 0;
pMinHtPhy->field.ShortGI = 0;
/*If STA assigns fixed rate. update to fixed here.*/
#ifdef CONFIG_STA_SUPPORT
if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)
#ifdef P2P_SUPPORT
&& (apidx == BSS0)
#endif /* P2P_SUPPORT */
)
{
CHAR i;
UCHAR j, bitmask;
if (pDesireHtPhy->MCSSet[4] != 0)
{
pMaxHtPhy->field.MCS = 32;
pMinHtPhy->field.MCS = 32;
DBGPRINT(RT_DEBUG_TRACE,("%s():<=== Use Fixed MCS = %d\n",__FUNCTION__, pMinHtPhy->field.MCS));
}
for (i=23; (CHAR)i >= 0; i--)
{
j = i/8;
bitmask = (1<<(i-(j*8)));
if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
{
pMaxHtPhy->field.MCS = i;
pMinHtPhy->field.MCS = i;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO,("%s():<=== Use Fixed MCS = %d\n", __FUNCTION__, i));
#endif /* RELEASE_EXCLUDE */
break;
}
if (i==0)
break;
}
}
#endif /* CONFIG_STA_SUPPORT */
/* Decide ht rate*/
pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
pHtPhy->field.BW = pMaxHtPhy->field.BW;
pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
/* use default now. rt2860*/
if (pDesireHtPhy->MCSSet[0] != 0xff)
*auto_rate_cur_p = FALSE;
else
*auto_rate_cur_p = TRUE;
DBGPRINT(RT_DEBUG_TRACE, (" %s():<---.AMsduSize = %d \n", __FUNCTION__, pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
DBGPRINT(RT_DEBUG_TRACE,("%s():<=== \n", __FUNCTION__));
}
VOID BATableInit(RTMP_ADAPTER *pAd, BA_TABLE *Tab)
{
int i;
Tab->numAsOriginator = 0;
Tab->numAsRecipient = 0;
Tab->numDoneOriginator = 0;
NdisAllocateSpinLock(pAd, &pAd->BATabLock);
for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
{
Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
NdisAllocateSpinLock(pAd, &(Tab->BARecEntry[i].RxReRingLock));
}
for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
{
Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
}
}
VOID BATableExit(RTMP_ADAPTER *pAd)
{
int i;
for(i=0; i<MAX_LEN_OF_BA_REC_TABLE; i++)
{
NdisFreeSpinLock(&pAd->BATable.BARecEntry[i].RxReRingLock);
}
NdisFreeSpinLock(&pAd->BATabLock);
}
#endif /* DOT11_N_SUPPORT */
VOID MlmeRadioOff(RTMP_ADAPTER *pAd)
{
#ifdef LED_CONTROL_SUPPORT
RTMPSetLED(pAd, LED_RADIO_OFF);
#endif /* LED_CONTROL_SUPPORT */
#ifdef RTMP_MAC_PCI
if (IS_PCI_INF(pAd) || IS_RBUS_INF(pAd))
PciMlmeRadioOFF(pAd);
#endif /* RTMP_MAC_PCI */
#ifdef RTMP_MAC_USB
if (IS_USB_INF(pAd))
UsbMlmeRadioOFF(pAd);
#endif /* RTMP_MAC_USB */
}
VOID MlmeRadioOn(RTMP_ADAPTER *pAd)
{
#ifdef RTMP_MAC_PCI
if (IS_PCI_INF(pAd) || IS_RBUS_INF(pAd))
PciMlmeRadioOn(pAd);
#endif /* RTMP_MAC_PCI */
#ifdef RTMP_MAC_USB
if (IS_USB_INF(pAd))
UsbMlmeRadioOn(pAd);
#endif /* RTMP_MAC_USB */
#ifdef LED_CONTROL_SUPPORT
RTMPSetLED(pAd, LED_LINK_UP);
#endif /* LED_CONTROL_SUPPORT */
}
/*! \brief initialize BSS table
* \param p_tab pointer to the table
* \return none
* \pre
* \post
IRQL = PASSIVE_LEVEL
IRQL = DISPATCH_LEVEL
*/
VOID BssTableInit(BSS_TABLE *Tab)
{
int i;
Tab->BssNr = 0;
Tab->BssOverlapNr = 0;
for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
{
UCHAR *pOldAddr = Tab->BssEntry[i].pVarIeFromProbRsp;
NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
Tab->BssEntry[i].Rssi = -127; /* initial the rssi as a minimum value */
if (pOldAddr)
{
RTMPZeroMemory(pOldAddr, MAX_VIE_LEN);
Tab->BssEntry[i].pVarIeFromProbRsp = pOldAddr;
}
}
}
/*! \brief search the BSS table by SSID
* \param p_tab pointer to the bss table
* \param ssid SSID string
* \return index of the table, BSS_NOT_FOUND if not in the table
* \pre
* \post
* \note search by sequential search
IRQL = DISPATCH_LEVEL
*/
ULONG BssTableSearch(BSS_TABLE *Tab, UCHAR *pBssid, UCHAR Channel)
{
UCHAR i;
for (i = 0; i < Tab->BssNr; i++)
{
/*
Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
We should distinguish this case.
*/
if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)
#ifdef WPA3_SUPPORT
&& (Channel == Tab->BssEntry[i].Channel)
#endif
) {
return i;
}
}
return (ULONG)BSS_NOT_FOUND;
}
ULONG BssSsidTableSearch(
IN BSS_TABLE *Tab,
IN PUCHAR pBssid,
IN PUCHAR pSsid,
IN UCHAR SsidLen,
IN UCHAR Channel)
{
UCHAR i;
for (i = 0; i < Tab->BssNr; i++)
{
/* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.*/
/* We should distinguish this case.*/
/* */
if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen)) {
#ifdef WPA3_SUPPORT
if (Tab->BssEntry[i].Channel == Channel)
#endif
return i;
}
}
return (ULONG)BSS_NOT_FOUND;
}
ULONG BssTableSearchWithSSID(
IN BSS_TABLE *Tab,
IN PUCHAR Bssid,
IN PUCHAR pSsid,
IN UCHAR SsidLen,
IN UCHAR Channel)
{
UCHAR i;
for (i = 0; i < Tab->BssNr; i++)
{
if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
(SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
(NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
(NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
{
return i;
}
}
return (ULONG)BSS_NOT_FOUND;
}
ULONG BssSsidTableSearchBySSID(BSS_TABLE *Tab, UCHAR *pSsid, UCHAR SsidLen)
{
UCHAR i;
for (i = 0; i < Tab->BssNr; i++)
{
if (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
{
return i;
}
}
return (ULONG)BSS_NOT_FOUND;
}
ULONG BssTableSearchByBSSID(BSS_TABLE *Tab, UCHAR *pBssid)
{
UCHAR i;
for (i = 0; i < Tab->BssNr; i++)
if (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
return i;
return (ULONG) BSS_NOT_FOUND;
}
VOID BssTableDeleteEntry(BSS_TABLE *Tab, UCHAR *pBssid, UCHAR Channel)
{
UCHAR i, j;
for (i = 0; i < Tab->BssNr; i++)
{
if ((Tab->BssEntry[i].Channel == Channel) &&
(MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
{
UCHAR *pOldAddr = NULL;
for (j = i; j < Tab->BssNr - 1; j++)
{
pOldAddr = Tab->BssEntry[j].pVarIeFromProbRsp;
NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
if (pOldAddr)
{
RTMPZeroMemory(pOldAddr, MAX_VIE_LEN);
NdisMoveMemory(pOldAddr,
Tab->BssEntry[j + 1].pVarIeFromProbRsp,
Tab->BssEntry[j + 1].VarIeFromProbeRspLen);
Tab->BssEntry[j].pVarIeFromProbRsp = pOldAddr;
}
}
pOldAddr = Tab->BssEntry[Tab->BssNr - 1].pVarIeFromProbRsp;
NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
if (pOldAddr)
{
RTMPZeroMemory(pOldAddr, MAX_VIE_LEN);
Tab->BssEntry[Tab->BssNr - 1].pVarIeFromProbRsp = pOldAddr;
}
Tab->BssNr -= 1;
return;
}
}
}
/*! \brief
* \param
* \return
* \pre
* \post
*/
VOID BssEntrySet(
IN RTMP_ADAPTER *pAd,
OUT BSS_ENTRY *pBss,
IN BCN_IE_LIST *ie_list,
IN CHAR Rssi,
IN USHORT LengthVIE,
IN PNDIS_802_11_VARIABLE_IEs pVIE)
{
COPY_MAC_ADDR(pBss->Bssid, ie_list->Bssid);
/* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID*/
pBss->Hidden = 1;
if (ie_list->SsidLen > 0)
{
/* For hidden SSID AP, it might send beacon with SSID len equal to 0*/
/* Or send beacon /probe response with SSID len matching real SSID length,*/
/* but SSID is all zero. such as "00-00-00-00" with length 4.*/
/* We have to prevent this case overwrite correct table*/
if (NdisEqualMemory(ie_list->Ssid, ZeroSsid, ie_list->SsidLen) == 0)
{
NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
NdisMoveMemory(pBss->Ssid, ie_list->Ssid, ie_list->SsidLen);
pBss->SsidLen = ie_list->SsidLen;
pBss->Hidden = 0;
}
}
else
{
/* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
if (NdisEqualMemory(pBss->Ssid, ZeroSsid, pBss->SsidLen))
{
NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
pBss->SsidLen = 0;
}
}
pBss->BssType = ie_list->BssType;
pBss->BeaconPeriod = ie_list->BeaconPeriod;
if (ie_list->BssType == BSS_INFRA)
{
if (ie_list->CfParm.bValid)
{
pBss->CfpCount = ie_list->CfParm.CfpCount;
pBss->CfpPeriod = ie_list->CfParm.CfpPeriod;
pBss->CfpMaxDuration = ie_list->CfParm.CfpMaxDuration;
pBss->CfpDurRemaining = ie_list->CfParm.CfpDurRemaining;
}
}
else
{
pBss->AtimWin = ie_list->AtimWin;
}
NdisGetSystemUpTime(&pBss->LastBeaconRxTime);
pBss->CapabilityInfo = ie_list->CapabilityInfo;
/* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES*/
/* Combine with AuthMode, they will decide the connection methods.*/
pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
ASSERT(ie_list->SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
if (ie_list->SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
NdisMoveMemory(pBss->SupRate, ie_list->SupRate, ie_list->SupRateLen);
else
NdisMoveMemory(pBss->SupRate, ie_list->SupRate, MAX_LEN_OF_SUPPORTED_RATES);
pBss->SupRateLen = ie_list->SupRateLen;
ASSERT(ie_list->ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
if (ie_list->ExtRateLen > MAX_LEN_OF_SUPPORTED_RATES)
ie_list->ExtRateLen = MAX_LEN_OF_SUPPORTED_RATES;
NdisMoveMemory(pBss->ExtRate, ie_list->ExtRate, ie_list->ExtRateLen);
pBss->NewExtChanOffset = ie_list->NewExtChannelOffset;
pBss->ExtRateLen = ie_list->ExtRateLen;
pBss->Channel = ie_list->Channel;
pBss->CentralChannel = ie_list->Channel;
pBss->Rssi = Rssi;
/* Update CkipFlag. if not exists, the value is 0x0*/
pBss->CkipFlag = ie_list->CkipFlag;
/* New for microsoft Fixed IEs*/
NdisMoveMemory(pBss->FixIEs.Timestamp, &ie_list->TimeStamp, 8);
pBss->FixIEs.BeaconInterval = ie_list->BeaconPeriod;
pBss->FixIEs.Capabilities = ie_list->CapabilityInfo;
/* New for microsoft Variable IEs*/
if (LengthVIE != 0)
{
pBss->VarIELen = LengthVIE;
NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
}
else
{
pBss->VarIELen = 0;
}
pBss->AddHtInfoLen = 0;
pBss->HtCapabilityLen = 0;
#ifdef DOT11_N_SUPPORT
if (ie_list->HtCapabilityLen> 0)
{
pBss->HtCapabilityLen = ie_list->HtCapabilityLen;
NdisMoveMemory(&pBss->HtCapability, &ie_list->HtCapability, ie_list->HtCapabilityLen);
if (ie_list->AddHtInfoLen > 0)
{
pBss->AddHtInfoLen = ie_list->AddHtInfoLen;
NdisMoveMemory(&pBss->AddHtInfo, &ie_list->AddHtInfo, ie_list->AddHtInfoLen);
pBss->CentralChannel = get_cent_ch_by_htinfo(pAd, &ie_list->AddHtInfo,
&ie_list->HtCapability);
}
#ifdef DOT11_VHT_AC
if (ie_list->vht_cap_len) {
NdisMoveMemory(&pBss->vht_cap_ie, &ie_list->vht_cap_ie, ie_list->vht_cap_len);
pBss->vht_cap_len = ie_list->vht_cap_len;
}
if (ie_list->vht_op_len) {
VHT_OP_IE *vht_op;
NdisMoveMemory(&pBss->vht_op_ie, &ie_list->vht_op_ie, ie_list->vht_op_len);
pBss->vht_op_len = ie_list->vht_op_len;
vht_op = &ie_list->vht_op_ie;
if ((vht_op->vht_op_info.ch_width > 0) &&
(ie_list->AddHtInfo.AddHtInfo.ExtChanOffset != EXTCHA_NONE) &&
(ie_list->HtCapability.HtCapInfo.ChannelWidth == BW_40) &&
(pBss->CentralChannel != ie_list->AddHtInfo.ControlChan))
{
UCHAR cent_ch;
cent_ch = vht_cent_ch_freq(pAd, ie_list->AddHtInfo.ControlChan);
DBGPRINT(RT_DEBUG_TRACE, ("%s():VHT cent_ch=%d, vht_op_info->center_freq_1=%d, Bss->CentCh=%d, change from CentralChannel to cent_ch!\n",
__FUNCTION__, cent_ch, vht_op->vht_op_info.center_freq_1, pBss->CentralChannel));
pBss->CentralChannel = vht_op->vht_op_info.center_freq_1;
}
}
#endif /* DOT11_VHT_AC */
}
#endif /* DOT11_N_SUPPORT */
BssCipherParse(pBss);
/* new for QOS*/
if (ie_list->EdcaParm.bValid)
NdisMoveMemory(&pBss->EdcaParm, &ie_list->EdcaParm, sizeof(EDCA_PARM));
else
pBss->EdcaParm.bValid = FALSE;
if (ie_list->QosCapability.bValid)
NdisMoveMemory(&pBss->QosCapability, &ie_list->QosCapability, sizeof(QOS_CAPABILITY_PARM));
else
pBss->QosCapability.bValid = FALSE;
if (ie_list->QbssLoad.bValid)
NdisMoveMemory(&pBss->QbssLoad, &ie_list->QbssLoad, sizeof(QBSS_LOAD_PARM));
else
pBss->QbssLoad.bValid = FALSE;
{
PEID_STRUCT pEid;
USHORT Length = 0;
#ifdef WSC_INCLUDED
pBss->WpsAP = 0x00;
pBss->WscDPIDFromWpsAP = 0xFFFF;
#endif /* WSC_INCLUDED */
#ifdef CONFIG_STA_SUPPORT
NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
NdisZeroMemory(&pBss->WpsIE.IE[0], MAX_CUSTOM_LEN);
pBss->WpaIE.IELen = 0;
pBss->RsnIE.IELen = 0;
pBss->WpsIE.IELen = 0;
#ifdef WAPI_SUPPORT
NdisZeroMemory(&pBss->WapiIE.IE[0], MAX_CUSTOM_LEN);
pBss->WapiIE.IELen = 0;
#endif /* WAPI_SUPPORT */
#ifdef EXT_BUILD_CHANNEL_LIST
NdisZeroMemory(&pBss->CountryString[0], 3);
pBss->bHasCountryIE = FALSE;
#endif /* EXT_BUILD_CHANNEL_LIST */
#ifdef DOT11R_FT_SUPPORT
pBss->bHasMDIE = FALSE;
NdisZeroMemory(&pBss->FT_MDIE, sizeof(FT_MDIE));
#endif /* DOT11R_FT_SUPPORT */
#endif /* CONFIG_STA_SUPPORT */
pEid = (PEID_STRUCT) pVIE;
while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
{
#define WPS_AP 0x01
switch(pEid->Eid)
{
case IE_WPA:
#ifdef WAC_SUPPORT
#define WAC_AP 0x04
if (NdisEqualMemory(pEid->Octet, SAMSUNG_OUI, 3))
{
#define WAC_DEVICE_ADVERTISE_ID 0x00
#define WAC_DEVICE_INFORMATION_ID 0x03
UCHAR oui_type = 0;
BOOLEAN bWAC_Enable = FALSE;
CHAR device_info[5];
oui_type = pEid->Octet[3];
DBGPRINT(RT_DEBUG_WARN, ("%s: Samsung OUI Type = 0x%02X\n", __FUNCTION__, oui_type));
if (oui_type == SAMSUNG_OUI_TYPE)
{
WAC_ParseAttr(WAC_DEVICE_ADVERTISE_ID, pEid->Octet+4, pEid->Len-4, &bWAC_Enable, 1);
if (bWAC_Enable)
pBss->WpsAP |= WAC_AP;
}
#ifdef WAC_QOS_PRIORITY
pBss->DeviceType = 0xFF;
pBss->bForcePriority = FALSE;
if (WAC_ParseAttr(WAC_DEVICE_INFORMATION_ID, pEid->Octet+4, pEid->Len-4, &device_info[0], 5))
{
DBGPRINT(RT_DEBUG_TRACE, ("%s: WAC Device Information: %d, %d, %d, %d, %d\n",
__FUNCTION__, device_info[0], device_info[1], device_info[2],
device_info[3], device_info[4]));
pBss->DeviceType = (CHAR) device_info[3];
}
if (bWAC_Enable)
{
pBss->bForcePriority = TRUE;
}
#endif /* WAC_QOS_PRIORITY */
}
#endif /* WAC_SUPPORT */
if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4)
#ifdef IWSC_SUPPORT
|| NdisEqualMemory(pEid->Octet, IWSC_OUI, 4)
#endif /* IWSC_SUPPORT */
)
{
#ifdef WSC_INCLUDED
pBss->WpsAP |= WPS_AP;
WscCheckWpsIeFromWpsAP(pAd,
pEid,
#ifdef STA_EASY_CONFIG_SETUP
&pBss->WpsAP,
#endif /* STA_EASY_CONFIG_SETUP */
&pBss->WscDPIDFromWpsAP);
#endif /* WSC_INCLUDED */
#ifdef CONFIG_STA_SUPPORT
if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
{
pBss->WpsIE.IELen = 0;
break;
}
pBss->WpsIE.IELen = pEid->Len + 2;
NdisMoveMemory(pBss->WpsIE.IE, pEid, pBss->WpsIE.IELen);
#endif /* CONFIG_STA_SUPPORT */
break;
}
#ifdef CONFIG_STA_SUPPORT
if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
{
if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
{
pBss->WpaIE.IELen = 0;
break;
}
pBss->WpaIE.IELen = pEid->Len + 2;
NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
}
#endif /* CONFIG_STA_SUPPORT */
break;
#ifdef CONFIG_STA_SUPPORT
case IE_RSN:
if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
{
if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
{
pBss->RsnIE.IELen = 0;
break;
}
pBss->RsnIE.IELen = pEid->Len + 2;
NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
}
break;
#ifdef WAPI_SUPPORT
case IE_WAPI:
if (NdisEqualMemory(pEid->Octet + 4, WAPI_OUI, 3))
{
UCHAR idx;
snprintf((RTMP_STRING *) pBss->WapiIE.IE, sizeof(pBss->WapiIE.IE), "wapi_ie=%02x%02x", pEid->Eid, pEid->Len);
for (idx = 0; idx < pEid->Len; idx++)
{
snprintf((RTMP_STRING *) pBss->WapiIE.IE, sizeof(pBss->WapiIE.IE), "%s%02x", pBss->WapiIE.IE, (unsigned char)pEid->Octet[idx]);
}
pBss->WapiIE.IELen = (pEid->Len*2) + 8; /* 2: ID(1 byte), LEN (1 byte), 8: len of "wapi_ie="*/
}
break;
#endif /* WAPI_SUPPORT */
#ifdef EXT_BUILD_CHANNEL_LIST
case IE_COUNTRY:
NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
pBss->bHasCountryIE = TRUE;
break;
#endif /* EXT_BUILD_CHANNEL_LIST */
#ifdef DOT11R_FT_SUPPORT
case IE_FT_MDIE:
if (pEid->Len == sizeof(FT_MDIE))
{
pBss->bHasMDIE = TRUE;
NdisMoveMemory(&pBss->FT_MDIE, pEid->Octet, pEid->Len);
}
break;
#endif /* DOT11R_FT_SUPPORT */
#endif /* CONFIG_STA_SUPPORT */
}
Length = Length + 2 + (USHORT)pEid->Len; /* Eid[1] + Len[1]+ content[Len]*/
pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
}
}
}
/*!
* \brief insert an entry into the bss table
* \param p_tab The BSS table
* \param Bssid BSSID
* \param ssid SSID
* \param ssid_len Length of SSID
* \param bss_type
* \param beacon_period
* \param timestamp
* \param p_cf
* \param atim_win
* \param cap
* \param rates
* \param rates_len
* \param channel_idx
* \return none
* \pre
* \post
* \note If SSID is identical, the old entry will be replaced by the new one
IRQL = DISPATCH_LEVEL
*/
ULONG BssTableSetEntry(
IN PRTMP_ADAPTER pAd,
OUT BSS_TABLE *Tab,
IN BCN_IE_LIST *ie_list,
IN CHAR Rssi,
IN USHORT LengthVIE,
IN PNDIS_802_11_VARIABLE_IEs pVIE)
{
ULONG Idx;
#ifdef APCLI_SUPPORT
BOOLEAN bInsert = FALSE;
PAPCLI_STRUCT pApCliEntry = NULL;
UCHAR i;
#endif /* APCLI_SUPPORT */
Idx = BssTableSearch(Tab, ie_list->Bssid, ie_list->Channel);
if (Idx >= MAX_LEN_OF_BSS_TABLE && Idx != BSS_NOT_FOUND) {
DBGPRINT(RT_DEBUG_ERROR,
("%s(): invalid BSS Idx(%ld)\n", __func__, Idx));
return BSS_NOT_FOUND;
}
if (Idx == BSS_NOT_FOUND)
{
if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
{
/*
It may happen when BSS Table was full.
The desired AP will not be added into BSS Table
In this case, if we found the desired AP then overwrite BSS Table.
*/
#ifdef APCLI_SUPPORT
for (i = 0; i < pAd->ApCfg.ApCliNum; i++)
{
pApCliEntry = &pAd->ApCfg.ApCliTab[i];
if (MAC_ADDR_EQUAL(pApCliEntry->MlmeAux.Bssid, ie_list->Bssid)
|| SSID_EQUAL(pApCliEntry->MlmeAux.Ssid, pApCliEntry->MlmeAux.SsidLen, ie_list->Ssid, ie_list->SsidLen))
{
bInsert = TRUE;
break;
}
}
#endif /* APCLI_SUPPORT */
if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) ||
!OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED))
{
if (MAC_ADDR_EQUAL(pAd->ScanCtrl.Bssid, ie_list->Bssid) ||
SSID_EQUAL(pAd->ScanCtrl.Ssid, pAd->ScanCtrl.SsidLen, ie_list->Ssid, ie_list->SsidLen)
#ifdef APCLI_SUPPORT
|| bInsert
#endif /* APCLI_SUPPORT */
#ifdef RT_CFG80211_SUPPORT
/* YF: Driver ScanTable full but supplicant the SSID exist on supplicant */
|| SSID_EQUAL(pAd->cfg80211_ctrl.Cfg_pending_Ssid, pAd->cfg80211_ctrl.Cfg_pending_SsidLen, ie_list->Ssid, ie_list->SsidLen)
#endif /* RT_CFG80211_SUPPORT */
)
{
Idx = Tab->BssOverlapNr;
NdisZeroMemory(&(Tab->BssEntry[Idx]), sizeof(BSS_ENTRY));
BssEntrySet(pAd, &Tab->BssEntry[Idx], ie_list, Rssi, LengthVIE, pVIE);
Tab->BssOverlapNr += 1;
Tab->BssOverlapNr = Tab->BssOverlapNr % MAX_LEN_OF_BSS_TABLE;
#ifdef RT_CFG80211_SUPPORT
pAd->cfg80211_ctrl.Cfg_pending_SsidLen = 0;
NdisZeroMemory(pAd->cfg80211_ctrl.Cfg_pending_Ssid, MAX_LEN_OF_SSID+1);
#endif /* RT_CFG80211_SUPPORT */
}
return Idx;
}
else
{
return BSS_NOT_FOUND;
}
}
Idx = Tab->BssNr;
BssEntrySet(pAd, &Tab->BssEntry[Idx], ie_list, Rssi, LengthVIE, pVIE);
Tab->BssNr++;
}
else
{
BssEntrySet(pAd, &Tab->BssEntry[Idx], ie_list, Rssi, LengthVIE, pVIE);
}
return Idx;
}
#ifdef CONFIG_STA_SUPPORT
#ifdef DOT11_N_SUPPORT
#ifdef DOT11N_DRAFT3
VOID TriEventInit(RTMP_ADAPTER *pAd)
{
UCHAR i;
for (i = 0;i < MAX_TRIGGER_EVENT;i++)
pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
pAd->CommonCfg.TriggerEventTab.EventANo = 0;
pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
}
INT TriEventTableSetEntry(
IN RTMP_ADAPTER *pAd,
OUT TRIGGER_EVENT_TAB *Tab,
IN UCHAR *pBssid,
IN HT_CAPABILITY_IE *pHtCapability,
IN UCHAR HtCapabilityLen,
IN UCHAR RegClass,
IN UCHAR ChannelNo)
{
/* Event A, legacy AP exist.*/
if (HtCapabilityLen == 0)
{
UCHAR index;
/*
Check if we already set this entry in the Event Table.
*/
for (index = 0; index<MAX_TRIGGER_EVENT; index++)
{
if ((Tab->EventA[index].bValid == TRUE) &&
(Tab->EventA[index].Channel == ChannelNo) &&
(Tab->EventA[index].RegClass == RegClass)
)
{
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("ReturnDueToAlreadyInserted(EventIdx=%d,Ch=%d,Reg=%d)\n",
index, ChannelNo, RegClass));
#endif /* RELEASE_EXCLUDE */
return 0;
}
}
/*
If not set, add it to the Event table
*/
if (Tab->EventANo < MAX_TRIGGER_EVENT)
{
RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
Tab->EventA[Tab->EventANo].bValid = TRUE;
Tab->EventA[Tab->EventANo].Channel = ChannelNo;
if (RegClass != 0)
{
/* Beacon has Regulatory class IE. So use beacon's*/
Tab->EventA[Tab->EventANo].RegClass = RegClass;
}
else
{
/* Use Station's Regulatory class instead.*/
/* If no Reg Class in Beacon, set to "unknown"*/
/* TODO: Need to check if this's valid*/
Tab->EventA[Tab->EventANo].RegClass = 0; /* ????????????????? need to check*/
}
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("Insert EventA Entry(EvtIdx=%d,Ch=%d,Reg=%d,Mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
Tab->EventANo, ChannelNo, RegClass, PRINT_MAC(pBssid)));
#endif /* RELEASE_EXCLUDE */
Tab->EventANo ++;
}
}
#ifdef DOT11V_WNM_SUPPORT
/* Not complete yet. Ignore for compliing successfully.*/
#else
else if (pHtCapability->HtCapInfo.Forty_Mhz_Intolerant)
{
/* Event B. My BSS beacon has Intolerant40 bit set*/
Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
}
#endif /* DOT11V_WNM_SUPPORT */
return 0;
}
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
VOID BssTableSsidSort(
IN RTMP_ADAPTER *pAd,
OUT BSS_TABLE *OutTab,
IN CHAR Ssid[],
IN UCHAR SsidLen)
{
INT i;
#ifdef WSC_STA_SUPPORT
PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl;
#endif /* WSC_STA_SUPPORT */
struct wifi_dev *wdev = &pAd->StaCfg.wdev;
#ifdef DOT11W_PMF_SUPPORT
RSN_CAPABILITIES RsnCap;
#endif
BssTableInit(OutTab);
if ((SsidLen == 0) &&
(pAd->StaCfg.bAutoConnectIfNoSSID == FALSE))
return;
for (i = 0; i < pAd->ScanTab.BssNr; i++)
{
BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
BOOLEAN bIsHiddenApIncluded = FALSE;
if ( ((pAd->CommonCfg.bIEEE80211H == 1) &&
(pAd->MlmeAux.Channel > 14) &&
RadarChannelCheck(pAd, pInBss->Channel))
#ifdef DPA_T
||(pInBss->Channel >= 12)
#endif /* !DPA_T */
#ifdef WIFI_REGION32_HIDDEN_SSID_SUPPORT
||((pInBss->Channel == 12) || (pInBss->Channel == 13))
#endif /* WIFI_REGION32_HIDDEN_SSID_SUPPORT */
#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier */
|| (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
#endif /* CARRIER_DETECTION_SUPPORT */
)
{
if (pInBss->Hidden)
bIsHiddenApIncluded = TRUE;
}
if ((pInBss->BssType == pAd->StaCfg.BssType) &&
(SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
{
BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
#ifdef WPA_SUPPLICANT_SUPPORT
if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP & 0x80)
{
/* copy matching BSS from InTab to OutTab*/
NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
OutTab->BssNr++;
continue;
}
#endif /* WPA_SUPPLICANT_SUPPORT */
#ifdef WSC_STA_SUPPORT
if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && pWpsCtrl->bWscTrigger)
{
/* copy matching BSS from InTab to OutTab*/
NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
OutTab->BssNr++;
continue;
}
#endif /* WSC_STA_SUPPORT */
#ifdef EXT_BUILD_CHANNEL_LIST
/* If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.*/
if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
(pInBss->bHasCountryIE == FALSE))
{
DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
continue;
}
#endif /* EXT_BUILD_CHANNEL_LIST */
#ifdef DOT11_N_SUPPORT
/* 2.4G/5G N only mode*/
if ((pInBss->HtCapabilityLen == 0) &&
(WMODE_HT_ONLY(pAd->CommonCfg.PhyMode)))
{
DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
continue;
}
if ((pAd->CommonCfg.PhyMode == (WMODE_G | WMODE_GN)) &&
((pInBss->SupRateLen + pInBss->ExtRateLen) < 12))
{
DBGPRINT(RT_DEBUG_TRACE,("STA is in GN-only Mode, this AP is in B mode.\n"));
continue;
}
#endif /* DOT11_N_SUPPORT */
#ifdef DOT11W_PMF_SUPPORT
if (((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)
#ifdef WPA3_SUPPORT
|| (wdev->AuthMode == Ndis802_11AuthModeWPA3SAE)
#endif
) && (pInBss)) {
CLIENT_STATUS_CLEAR_FLAG(pInBss, fCLIENT_STATUS_PMF_CAPABLE);
CLIENT_STATUS_CLEAR_FLAG(pInBss, fCLIENT_STATUS_USE_SHA256);
NdisMoveMemory(&RsnCap, &pInBss->WPA2.RsnCapability, sizeof(RSN_CAPABILITIES));
RsnCap.word = cpu2le16(RsnCap.word);
if ((pAd->StaCfg.PmfCfg.MFPR) && (RsnCap.field.MFPC == FALSE))
continue;
if (((pAd->StaCfg.PmfCfg.MFPC == FALSE) && (RsnCap.field.MFPC == FALSE))
|| (pAd->StaCfg.PmfCfg.MFPC && RsnCap.field.MFPC && (pAd->StaCfg.PmfCfg.MFPR == FALSE) && (RsnCap.field.MFPR == FALSE)))
{
if ((pAd->StaCfg.PmfCfg.PMFSHA256) && (pInBss->IsSupportSHA256KeyDerivation == FALSE))
continue;
}
if ((pAd->StaCfg.PmfCfg.MFPC) && (RsnCap.field.MFPC))
CLIENT_STATUS_SET_FLAG(pInBss, fCLIENT_STATUS_PMF_CAPABLE);
if ((pAd->StaCfg.PmfCfg.PMFSHA256 && pInBss->IsSupportSHA256KeyDerivation)
|| (pAd->StaCfg.PmfCfg.MFPC && RsnCap.field.MFPR)
|| (pAd->StaCfg.PmfCfg.MFPC && pInBss->IsSupportSHA256KeyDerivation))
CLIENT_STATUS_SET_FLAG(pInBss, fCLIENT_STATUS_USE_SHA256);
}
#endif /* DOT11W_PMF_SUPPORT */
/* New for WPA2*/
/* Check the Authmode first*/
if (wdev->AuthMode >= Ndis802_11AuthModeWPA)
{
/* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode*/
#ifdef WPA3_SUPPORT
for (i = 0; i < pInBss->u4AuthModeCount; i++)
if (wdev->AuthMode != pInBss->AuthMode[i])
continue;/* None matched*/
#else
if ((wdev->AuthMode != pInBss->AuthMode) && (wdev->AuthMode != pInBss->AuthModeAux))
/* None matched*/
continue;
#endif
/* Check cipher suite, AP must have more secured cipher than station setting*/
if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK))
{
/* If it's not mixed mode, we should only let BSS pass with the same encryption*/
if (pInBss->WPA.bMixMode == FALSE)
if (wdev->WepStatus != pInBss->WPA.GroupCipher)
continue;
/* check group cipher*/
if ((wdev->WepStatus < pInBss->WPA.GroupCipher) &&
(pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
(pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
continue;
/* check pairwise cipher, skip if none matched*/
/* If profile set to AES, let it pass without question.*/
/* If profile set to TKIP, we must find one mateched*/
#ifdef WPA3_SUPPORT
if (wdev->WepStatus == Ndis802_11Encryption2Enabled) {
USHORT Count;
Count = 0;
for (i = 0; i < pInBss->WPA.u4PairwiseCipherCount; i++) {
if ((wdev->WepStatus != pInBss->WPA.PairCipher[i]))
Count++;
else
break;
}
if (Count == pInBss->WPA.u4PairwiseCipherCount)
continue;
}
#else
if ((wdev->WepStatus == Ndis802_11TKIPEnable) &&
(wdev->WepStatus != pInBss->WPA.PairCipher) &&
(wdev->WepStatus != pInBss->WPA.PairCipherAux))
continue;
#endif
}
else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) {
/* If it's not mixed mode, we should only let BSS pass with the same encryption*/
if (pInBss->WPA2.bMixMode == FALSE)
if (wdev->WepStatus != pInBss->WPA2.GroupCipher)
continue;
/* check group cipher*/
if ((wdev->WepStatus < pInBss->WPA.GroupCipher) &&
(pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
(pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
continue;
/* check pairwise cipher, skip if none matched*/
/* If profile set to AES, let it pass without question.*/
/* If profile set to TKIP, we must find one mateched*/
#ifdef WPA3_SUPPORT
if (wdev->WepStatus == Ndis802_11Encryption2Enabled) {
USHORT Count;
Count = 0;
for (i = 0; i < pInBss->WPA2.u4PairwiseCipherCount; i++) {
if (wdev->WepStatus != pInBss->WPA2.PairCipher[i])
Count++;
else
break;
}
if (Count == pInBss->WPA2.u4PairwiseCipherCount)
continue;
}
#else
if ((wdev->WepStatus == Ndis802_11TKIPEnable) &&
(wdev->WepStatus != pInBss->WPA2.PairCipher) &&
(wdev->WepStatus != pInBss->WPA2.PairCipherAux))
continue;
#endif
}
#ifdef WAPI_SUPPORT
else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK))
{
/* check cipher algorithm*/
if ((wdev->WepStatus != pInBss->WAPI.GroupCipher) ||
#ifdef WPA3_SUPPORT
(pAd->StaCfg.WepStatus != pInBss->WAPI.PairCipher[0])
#else
(wdev->WepStatus != pInBss->WAPI.PairCipher)
#endif
)
continue;
}
#endif /* WAPI_SUPPORT */
#ifdef WPA3_SUPPORT
else if ((wdev->AuthMode == Ndis802_11AuthModeWPA3SAE) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSKWPA3SAE)) {
if (pInBss->WPA2.bMixMode == FALSE)
if (wdev->WepStatus != pInBss->WPA2.GroupCipher)
continue;
/* check group cipher*/
if ((wdev->WepStatus < pInBss->WPA2.GroupCipher) &&
(pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
(pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
continue;
}
#endif
}
/* Bss Type matched, SSID matched. */
/* We will check wepstatus for qualification Bss*/
else if (wdev->WepStatus != pInBss->WepStatus)
{
DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", wdev->WepStatus, pInBss->WepStatus));
/* For the SESv2 case, we will not qualify WepStatus.*/
if (!pInBss->bSES)
continue;
}
/* Since the AP is using hidden SSID, and we are trying to connect to ANY*/
/* It definitely will fail. So, skip it.*/
/* CCX also require not even try to connect it!!*/
if (SsidLen == 0)
continue;
/* copy matching BSS from InTab to OutTab*/
NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
OutTab->BssNr++;
}
else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
{
BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
#ifdef WSC_STA_SUPPORT
if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && pWpsCtrl->bWscTrigger)
{
/* copy matching BSS from InTab to OutTab*/
NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
OutTab->BssNr++;
continue;
}
#endif /* WSC_STA_SUPPORT */
#ifdef DOT11_N_SUPPORT
/* 2.4G/5G N only mode*/
if ((pInBss->HtCapabilityLen == 0) &&
WMODE_HT_ONLY(pAd->CommonCfg.PhyMode))
{
DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
continue;
}
if ((pAd->CommonCfg.PhyMode == (WMODE_G | WMODE_GN)) &&
((pInBss->SupRateLen + pInBss->ExtRateLen) < 12))
{
DBGPRINT(RT_DEBUG_TRACE,("STA is in GN-only Mode, this AP is in B mode.\n"));
continue;
}
#endif /* DOT11_N_SUPPORT */
/* New for WPA2*/
/* Check the Authmode first*/
if (wdev->AuthMode >= Ndis802_11AuthModeWPA)
{
/* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode*/
#ifdef WPA3_SUPPORT
for (i = 0; i < pInBss->u4AuthModeCount; i++)
if (wdev->AuthMode != pInBss->AuthMode[i])
continue;/* None matched*/
#else
if ((wdev->AuthMode != pInBss->AuthMode) && (wdev->AuthMode != pInBss->AuthModeAux))
/* None matched*/
continue;
#endif
/* Check cipher suite, AP must have more secured cipher than station setting*/
if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK))
{
/* If it's not mixed mode, we should only let BSS pass with the same encryption*/
if (pInBss->WPA.bMixMode == FALSE)
if (wdev->WepStatus != pInBss->WPA.GroupCipher)
continue;
/* check group cipher*/
if (wdev->WepStatus < pInBss->WPA.GroupCipher)
continue;
/* check pairwise cipher, skip if none matched*/
/* If profile set to AES, let it pass without question.*/
/* If profile set to TKIP, we must find one mateched*/
#ifdef WPA3_SUPPORT
if (wdev->WepStatus == Ndis802_11Encryption2Enabled) {
USHORT Count;
Count = 0;
for (i = 0; i < pInBss->WPA.u4PairwiseCipherCount; i++) {
if (wdev->WepStatus != pInBss->WPA.PairCipher[i])
Count++;
else
break;
}
if (Count == pInBss->WPA.u4PairwiseCipherCount)
continue;
}
#else
if ((wdev->WepStatus == Ndis802_11TKIPEnable) &&
(wdev->WepStatus != pInBss->WPA.PairCipher) &&
(wdev->WepStatus != pInBss->WPA.PairCipherAux))
continue;
#endif
} else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) {
/* If it's not mixed mode, we should only let BSS pass with the same encryption*/
if (pInBss->WPA2.bMixMode == FALSE)
if (wdev->WepStatus != pInBss->WPA2.GroupCipher)
continue;
/* check group cipher*/
if (wdev->WepStatus < pInBss->WPA2.GroupCipher)
continue;
/* check pairwise cipher, skip if none matched*/
/* If profile set to AES, let it pass without question.*/
/* If profile set to TKIP, we must find one mateched*/
#ifdef WPA3_SUPPORT
if (wdev->WepStatus == Ndis802_11Encryption2Enabled) {
USHORT Count;
Count = 0;
for (i = 0; i < pInBss->WPA2.u4PairwiseCipherCount; i++) {
if (wdev->WepStatus != pInBss->WPA2.PairCipher[i])
Count++;
else
break;
}
if (Count == pInBss->WPA2.u4PairwiseCipherCount)
continue;
}
#else
if ((wdev->WepStatus == Ndis802_11TKIPEnable) &&
(wdev->WepStatus != pInBss->WPA2.PairCipher) &&
(wdev->WepStatus != pInBss->WPA2.PairCipherAux))
continue;
#endif
}
#ifdef WAPI_SUPPORT
else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK))
{
/* check cipher algorithm*/
if ((wdev->WepStatus != pInBss->WAPI.GroupCipher) ||
#ifdef WPA3_SUPPORT
(pAd->StaCfg.WepStatus != pInBss->WAPI.PairCipher[0])
#else
(wdev->WepStatus != pInBss->WAPI.PairCipher)
#endif
)
continue;
}
#endif /* WAPI_SUPPORT */
}
/* Bss Type matched, SSID matched. */
/* We will check wepstatus for qualification Bss*/
else if (wdev->WepStatus != pInBss->WepStatus)
continue;
/* copy matching BSS from InTab to OutTab*/
NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
OutTab->BssNr++;
}
#ifdef WSC_STA_SUPPORT
else if ((pWpsCtrl->WscConfMode != WSC_DISABLE) &&
(pWpsCtrl->bWscTrigger) &&
MAC_ADDR_EQUAL(pWpsCtrl->WscBssid, pInBss->Bssid))
{
BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
/* copy matching BSS from InTab to OutTab*/
NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
/*
Linksys WRT610N WPS AP will change the SSID from linksys to linksys_WPS_<four random characters>
when the Linksys WRT610N is in the state 'WPS Unconfigured' after set to factory default.
*/
NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
NdisMoveMemory(pAd->MlmeAux.Ssid, pInBss->Ssid, pInBss->SsidLen);
pAd->MlmeAux.SsidLen = pInBss->SsidLen;
/* Update Reconnect Ssid, that user desired to connect.*/
NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID);
NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen;
OutTab->BssNr++;
continue;
}
#endif /* WSC_STA_SUPPORT */
if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
break;
}
BssTableSortByRssi(OutTab, FALSE);
}
#endif /* CONFIG_STA_SUPPORT */
#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_AUTO_CONNECT_SUPPORT)
/* IRQL = DISPATCH_LEVEL*/
VOID BssTableSortByRssi(
IN OUT BSS_TABLE *OutTab,
IN BOOLEAN isInverseOrder)
{
INT i, j;
BSS_ENTRY *pTmpBss = NULL;
/* allocate memory */
os_alloc_mem(NULL, (UCHAR **)&pTmpBss, sizeof(BSS_ENTRY));
if (pTmpBss == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
return;
}
for (i = 0; i < OutTab->BssNr - 1; i++)
{
for (j = i+1; j < OutTab->BssNr; j++)
{
if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi ?
!isInverseOrder : isInverseOrder)
{
if (OutTab->BssEntry[j].Rssi != OutTab->BssEntry[i].Rssi )
{
NdisMoveMemory(pTmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
NdisMoveMemory(&OutTab->BssEntry[i], pTmpBss, sizeof(BSS_ENTRY));
}
}
}
}
if (pTmpBss != NULL)
os_free_mem(NULL, pTmpBss);
}
#endif /* defined(CONFIG_STA_SUPPORT) || defined(APCLI_AUTO_CONNECT_SUPPORT) */
VOID BssCipherParse(BSS_ENTRY *pBss)
{
PEID_STRUCT pEid;
PUCHAR pTmp;
PRSN_IE_HEADER_STRUCT pRsnHeader;
PCIPHER_SUITE_STRUCT pCipher;
PAKM_SUITE_STRUCT pAKM;
USHORT Count;
INT Length;
NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
#ifndef WPA3_SUPPORT
BOOLEAN fgMultiAKMs = FALSE;
#else
USHORT TmpCount;
USHORT MaxCount;
NDIS_802_11_AUTHENTICATION_MODE TmpAuthMode;
UINT32 TmpAKMSuite;
TmpCount = 0;
#endif
/* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.*/
if (pBss->Privacy)
{
pBss->WepStatus = Ndis802_11WEPEnabled;
}
else
{
pBss->WepStatus = Ndis802_11WEPDisabled;
}
#ifdef WPA3_SUPPORT
/* Set default to disable & open authentication before parsing variable IE*/
for (TmpCount = 0; TmpCount < MAX_NUM_SUPPORTED_AKM_SUITES; TmpCount++)
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeOpen;
/* Init WPA/WPA2 setting*/
pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
for (TmpCount = 0; TmpCount < MAX_NUM_SUPPORTED_CIPHER_SUITES; TmpCount++) {
pBss->WPA.PairCipher[TmpCount] = Ndis802_11WEPDisabled;
pBss->WPA2.PairCipher[TmpCount] = Ndis802_11WEPDisabled;
}
for (TmpCount = 0; TmpCount < MAX_NUM_SUPPORTED_AKM_SUITES; TmpCount++) {
pBss->WPA.au4AuthKeyMgtSuite[TmpCount] = RSN_AKM_SUITE_NONE;
pBss->WPA2.au4AuthKeyMgtSuite[TmpCount] = RSN_AKM_SUITE_NONE;
}
#ifdef DOT11W_PMF_SUPPORT
pBss->IsSupportSHA256KeyDerivation = FALSE;
#endif /* DOT11W_PMF_SUPPORT */
pBss->WPA.RsnCapability = 0;
pBss->WPA2.RsnCapability = 0;
pBss->WPA.u2PmkidCnt = 0;
NdisZeroMemory(pBss->WPA.aucPmkidList, (sizeof(UCHAR) * MAX_NUM_SUPPORTED_PMKID * RSN_PMKID_LEN));
pBss->WPA.u4GroupMgmtKeyCipherSuite = 0;
pBss->WPA2.u2PmkidCnt = 0;
NdisZeroMemory(pBss->WPA2.aucPmkidList, (sizeof(UCHAR) * MAX_NUM_SUPPORTED_PMKID * RSN_PMKID_LEN));
pBss->WPA2.u4GroupMgmtKeyCipherSuite = 0;
pBss->WPA.bMixMode = FALSE;
pBss->WPA2.bMixMode = FALSE;
#ifdef WAPI_SUPPORT
pBss->WPAI.GroupCipher = Ndis802_11WEPDisabled;
for (TmpCount = 0; TmpCount < MAX_NUM_SUPPORTED_CIPHER_SUITES; TmpCount++)
pBss->WPAI.PairCipher[TmpCount] = Ndis802_11WEPDisabled;
pBss->WPAI.RsnCapability = 0;
pBss->WPAI.u2PmkidCnt = 0;
NdisZeroMemory(pBss->WPAI.aucPmkidList, (sizeof(UCHAR) * MAX_NUM_SUPPORTED_PMKID * RSN_PMKID_LEN));
pBss->WPAI.u4GroupMgmtKeyCipherSuite = 0;
pBss->WPAI.bMixMode = FALSE;
#endif
#else /* WPA3_SUPPORT*/
/* Set default to disable & open authentication before parsing variable IE*/
pBss->AuthMode = Ndis802_11AuthModeOpen;
pBss->AuthModeAux = Ndis802_11AuthModeOpen;
#ifdef DOT11W_PMF_SUPPORT
pBss->IsSupportSHA256KeyDerivation = FALSE;
#endif /* DOT11W_PMF_SUPPORT */
/* Init WPA setting*/
pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
pBss->WPA.RsnCapability = 0;
pBss->WPA.bMixMode = FALSE;
/* Init WPA2 setting*/
pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
pBss->WPA2.RsnCapability = 0;
pBss->WPA2.bMixMode = FALSE;
#ifdef WAPI_SUPPORT
/* Init WAPI setting*/
pBss->WAPI.PairCipher = Ndis802_11WEPDisabled;
pBss->WAPI.PairCipherAux = Ndis802_11WEPDisabled;
pBss->WAPI.GroupCipher = Ndis802_11WEPDisabled;
pBss->WAPI.RsnCapability = 0;
pBss->WAPI.bMixMode = FALSE;
#endif /* WAPI_SUPPORT */
#endif /* WPA3_SUPPORT */
Length = (INT) pBss->VarIELen;
while (Length > 0)
{
/* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently*/
pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
pEid = (PEID_STRUCT) pTmp;
switch (pEid->Eid)
{
case IE_WPA:
if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
{
pBss->bSES = TRUE;
break;
}
else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
{
/* if unsupported vendor specific IE*/
break;
}
/*
Skip OUI, version, and multicast suite
This part should be improved in the future when AP supported multiple cipher suite.
For now, it's OK since almost all APs have fixed cipher suite supported.
*/
/* pTmp = (PUCHAR) pEid->Octet;*/
pTmp += 11;
/*
Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
Value Meaning
0 None
1 WEP-40
2 Tkip
3 WRAP
4 AES
5 WEP-104
*/
/* Parse group cipher*/
switch (*pTmp)
{
case 1:
pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
break;
case 5:
pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
break;
case 2:
pBss->WPA.GroupCipher = Ndis802_11TKIPEnable;
break;
case 4:
pBss->WPA.GroupCipher = Ndis802_11AESEnable;
break;
default:
break;
}
/* number of unicast suite*/
pTmp += 1;
#ifdef WPA3_SUPPORT
/* skip all unicast cipher suites*/
/*Count = *(PUSHORT) pTmp; */
Count = (pTmp[1]<<8) + pTmp[0];
pTmp += sizeof(USHORT);
pBss->WPA.u4PairwiseCipherCount = (Count > MAX_NUM_SUPPORTED_CIPHER_SUITES)?MAX_NUM_SUPPORTED_CIPHER_SUITES:Count;
TmpCount = 0;
/* Parsing all unicast cipher suite*/
while (Count > 0) {
/* Skip OUI*/
pTmp += 3;
switch (*pTmp) {
case 1:
case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway*/
pBss->WPA.PairCipher[TmpCount] = Ndis802_11Encryption1Enabled;
break;
case 2:
pBss->WPA.PairCipher[TmpCount] = Ndis802_11Encryption2Enabled;
break;
case 4:
pBss->WPA.PairCipher[TmpCount] = Ndis802_11Encryption3Enabled;
break;
default:
break;
}
pTmp++;
Count--;
TmpCount++;
}
/* sort the PairCipher, PairCipher[0] would be the max*/
for (Count = 0; Count < (pBss->WPA.u4PairwiseCipherCount-1); Count++) {
MaxCount = Count;
for (TmpCount = (Count+1); TmpCount < pBss->WPA.u4PairwiseCipherCount; TmpCount++) {
if (pBss->WPA.PairCipher[TmpCount] > pBss->WPA.PairCipher[MaxCount])
MaxCount = TmpCount;
}
TmpCipher = pBss->WPA.PairCipher[Count];
pBss->WPA.PairCipher[Count] = pBss->WPA.PairCipher[MaxCount];
pBss->WPA.PairCipher[MaxCount] = TmpCipher;
}
/* 4. get AKM suite counts*/
/*Count = *(PUSHORT) pTmp;*/
Count = (pTmp[1]<<8) + pTmp[0];
pTmp += sizeof(USHORT);
pBss->u4AuthModeCount = (Count > MAX_NUM_SUPPORTED_AKM_SUITES)?MAX_NUM_SUPPORTED_AKM_SUITES:Count;
pBss->WPA.u4AuthKeyMgtSuiteCount = pBss->u4AuthModeCount;
TmpCount = 0;
/* Parsing all AKM suite List */
while (Count > 0) {
/* Skip OUI*/
pTmp += 3;
switch (*pTmp) {
case 1:
/* Set AP support WPA-enterprise mode*/
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeWPA;
pBss->WPA.au4AuthKeyMgtSuite[TmpCount] = WPA_AKM_SUITE_802_1X;
break;
case 2:
/* Set AP support WPA-PSK mode*/
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeWPAPSK;
pBss->WPA.au4AuthKeyMgtSuite[TmpCount] = WPA_AKM_SUITE_PSK;
break;
default:
break;
}
pTmp++;
Count--;
TmpCount++;
}
/* sort the AuthMode, AuthMode[0] would be the max*/
for (Count = 0; Count < (pBss->u4AuthModeCount-1); Count++) {
MaxCount = Count;
for (TmpCount = (Count+1); TmpCount < pBss->u4AuthModeCount; TmpCount++) {
if (pBss->AuthMode[TmpCount] > pBss->AuthMode[MaxCount])
MaxCount = TmpCount;
}
TmpAuthMode = pBss->AuthMode[Count];
pBss->AuthMode[Count] = pBss->AuthMode[MaxCount];
pBss->AuthMode[MaxCount] = TmpAuthMode;
TmpAKMSuite = pBss->WPA.au4AuthKeyMgtSuite[Count];
pBss->WPA.au4AuthKeyMgtSuite[Count] = pBss->WPA.au4AuthKeyMgtSuite[MaxCount];
pBss->WPA.au4AuthKeyMgtSuite[MaxCount] = TmpAKMSuite;
}
pTmp += 1;
/* Fixed for WPA-None*/
if (pBss->BssType == BSS_ADHOC) {
for (Count = 0; Count < pBss->u4AuthModeCount; Count++)
pBss->AuthMode[Count] = Ndis802_11AuthModeWPANone;
pBss->WepStatus = pBss->WPA.GroupCipher;
/* Patched bugs for old driver*/
for (Count = 0; Count < pBss->WPA.u4PairwiseCipherCount; Count++)
if (pBss->WPA.PairCipher[Count] == Ndis802_11WEPDisabled)
pBss->WPA.PairCipher[Count] = pBss->WPA.GroupCipher;
} else
pBss->WepStatus = pBss->WPA.PairCipher[0];
/* Check the Pair & Group, if different, turn on mixed mode flag*/
if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher[0])
pBss->WPA.bMixMode = TRUE;
#else /* WPA3_SUPPORT */
/* skip all unicast cipher suites*/
/*Count = *(PUSHORT) pTmp; */
Count = (pTmp[1]<<8) + pTmp[0];
pTmp += sizeof(USHORT);
/* Parsing all unicast cipher suite*/
while (Count > 0)
{
/* Skip OUI*/
pTmp += 3;
TmpCipher = Ndis802_11WEPDisabled;
switch (*pTmp)
{
case 1:
case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway*/
TmpCipher = Ndis802_11WEPEnabled;
break;
case 2:
TmpCipher = Ndis802_11TKIPEnable;
break;
case 4:
TmpCipher = Ndis802_11AESEnable;
break;
default:
break;
}
if (TmpCipher > pBss->WPA.PairCipher)
{
/* Move the lower cipher suite to PairCipherAux*/
pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
pBss->WPA.PairCipher = TmpCipher;
}
else
{
pBss->WPA.PairCipherAux = TmpCipher;
}
pTmp++;
Count--;
}
/* 4. get AKM suite counts*/
/*Count = *(PUSHORT) pTmp;*/
Count = (pTmp[1]<<8) + pTmp[0];
pTmp += sizeof(USHORT);
pTmp += 3;
switch (*pTmp)
{
case 1:
/* Set AP support WPA-enterprise mode*/
if (pBss->AuthMode == Ndis802_11AuthModeOpen)
pBss->AuthMode = Ndis802_11AuthModeWPA;
else
pBss->AuthModeAux = Ndis802_11AuthModeWPA;
break;
case 2:
/* Set AP support WPA-PSK mode*/
if (pBss->AuthMode == Ndis802_11AuthModeOpen)
pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
else
pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
break;
default:
break;
}
pTmp += 1;
/* Fixed for WPA-None*/
if (pBss->BssType == BSS_ADHOC)
{
pBss->AuthMode = Ndis802_11AuthModeWPANone;
pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
pBss->WepStatus = pBss->WPA.GroupCipher;
/* Patched bugs for old driver*/
if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
}
else
pBss->WepStatus = pBss->WPA.PairCipher;
/* Check the Pair & Group, if different, turn on mixed mode flag*/
if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
pBss->WPA.bMixMode = TRUE;
#endif /* WPA3_SUPPORT */
break;
case IE_RSN:
pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
/* 0. Version must be 1*/
if (le2cpu16(pRsnHeader->Version) != 1)
break;
pTmp += sizeof(RSN_IE_HEADER_STRUCT);
/* 1. Check group cipher*/
pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
break;
/* Parse group cipher*/
switch (pCipher->Type)
{
case 1:
pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
break;
case 5:
pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
break;
case 2:
pBss->WPA2.GroupCipher = Ndis802_11TKIPEnable;
break;
case 4:
pBss->WPA2.GroupCipher = Ndis802_11AESEnable;
break;
default:
break;
}
/* set to correct offset for next parsing*/
pTmp += sizeof(CIPHER_SUITE_STRUCT);
#ifdef WPA3_SUPPORT
/* 2. Get pairwise cipher counts*/
Count = (pTmp[1]<<8) + pTmp[0];
pTmp += sizeof(USHORT);
pBss->WPA2.u4PairwiseCipherCount = (Count > MAX_NUM_SUPPORTED_CIPHER_SUITES)?MAX_NUM_SUPPORTED_CIPHER_SUITES:Count;
TmpCount = 0;
/* 3. Get pairwise cipher*/
/* Parsing all unicast cipher suite*/
while (Count > 0) {
/* Skip OUI*/
pTmp += 3;
switch (*pTmp) {
case 1:
case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway*/
pBss->WPA2.PairCipher[TmpCount] = Ndis802_11Encryption1Enabled;
break;
case 2:
pBss->WPA2.PairCipher[TmpCount] = Ndis802_11Encryption2Enabled;
break;
case 4:
pBss->WPA2.PairCipher[TmpCount] = Ndis802_11Encryption3Enabled;
break;
default:
break;
}
pTmp++;
Count--;
TmpCount++;
}
/* sort the PairCipher, PairCipher[0] would be the max*/
for (Count = 0; Count < (pBss->WPA2.u4PairwiseCipherCount-1); Count++) {
MaxCount = Count;
for (TmpCount = (Count+1); TmpCount < pBss->WPA2.u4PairwiseCipherCount; TmpCount++)
if (pBss->WPA2.PairCipher[TmpCount] > pBss->WPA2.PairCipher[MaxCount])
MaxCount = TmpCount;
TmpCipher = pBss->WPA2.PairCipher[Count];
pBss->WPA2.PairCipher[Count] = pBss->WPA2.PairCipher[MaxCount];
pBss->WPA2.PairCipher[MaxCount] = TmpCipher;
}
/* 4. get AKM suite counts*/
/*Count = *(PUSHORT) pTmp;*/
Count = (pTmp[1]<<8) + pTmp[0];
pTmp += sizeof(USHORT);
pBss->u4AuthModeCount = (Count > MAX_NUM_SUPPORTED_AKM_SUITES)?MAX_NUM_SUPPORTED_AKM_SUITES:Count;
pBss->WPA2.u4AuthKeyMgtSuiteCount = pBss->u4AuthModeCount;
TmpCount = 0;
/* 5. Get AKM ciphers*/
/* Parsing all AKM suite List */
while (Count > 0) {
/* Skip OUI*/
pAKM = (PAKM_SUITE_STRUCT) pTmp;
if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
break;
switch (pAKM->Type) {
case 0:
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeWPANone;
pBss->WPA2.au4AuthKeyMgtSuite[TmpCount] = RSN_AKM_SUITE_NONE;
break;
case 1:
#ifdef DOT11R_FT_SUPPORT
case 3:
#endif /* DOT11R_FT_SUPPORT */
/* Set AP support WPA-enterprise mode*/
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeWPA2;
pBss->WPA2.au4AuthKeyMgtSuite[TmpCount] = RSN_AKM_SUITE_802_1X;
break;
case 2:
#ifdef DOT11R_FT_SUPPORT
case 4:
#endif /* DOT11R_FT_SUPPORT */
/* Set AP support WPA-PSK mode*/
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeWPA2PSK;
pBss->WPA2.au4AuthKeyMgtSuite[TmpCount] = RSN_AKM_SUITE_PSK;
break;
#ifdef CFG_SUPPORT_802_11W
case 5:
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeWPA2;
pBss->WPA2.au4AuthKeyMgtSuite[TmpCount] = RSN_AKM_SUITE_802_1X_SHA256;
break;
case 6:
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeWPA2PSK;
pBss->WPA2.au4AuthKeyMgtSuite[TmpCount] = RSN_AKM_SUITE_PSK_SHA256;
pBss->IsSupportSHA256KeyDerivation = TRUE;
break;
#endif
#ifdef CFG_SUPPORT_SAE
case 8:
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeWPA3SAE;
pBss->WPA2.au4AuthKeyMgtSuite[TmpCount] = RSN_AKM_SUITE_SAE;
break;
#endif
#ifdef CFG_SUPPORT_SUITB
case 11:
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeWPA2PSK;
pBss->WPA2.au4AuthKeyMgtSuite[TmpCount] = RSN_AKM_SUITE_8021X_SUITE_B;
break;
#endif
#ifdef CFG_SUPPORT_SUITB_192
case 12:
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeWPA2PSK;
pBss->WPA2.au4AuthKeyMgtSuite[TmpCount] = RSN_AKM_SUITE_8021X_SUITE_B_192;
break;
#endif
#ifdef CFG_SUPPORT_OWE
case 18:
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeWPA2PSK;
pBss->WPA2.au4AuthKeyMgtSuite[TmpCount] = RSN_AKM_SUITE_OWE;
break;
#endif
default:
pBss->AuthMode[TmpCount] = Ndis802_11AuthModeMax;
pBss->WPA2.au4AuthKeyMgtSuite[TmpCount] = RSN_AKM_SUITE_NONE;
break;
}
pTmp += sizeof(AKM_SUITE_STRUCT);
Count--;
TmpCount++;
}
/* sort the AuthMode, AuthMode[0] would be the max*/
for (Count = 0; Count < (pBss->u4AuthModeCount-1); Count++) {
MaxCount = Count;
for (TmpCount = (Count+1); TmpCount < pBss->u4AuthModeCount; TmpCount++) {
if (pBss->AuthMode[TmpCount] > pBss->AuthMode[MaxCount])
MaxCount = TmpCount;
}
TmpAuthMode = pBss->AuthMode[Count];
pBss->AuthMode[Count] = pBss->AuthMode[MaxCount];
pBss->AuthMode[MaxCount] = TmpAuthMode;
TmpAKMSuite = pBss->WPA2.au4AuthKeyMgtSuite[Count];
pBss->WPA2.au4AuthKeyMgtSuite[Count] = pBss->WPA2.au4AuthKeyMgtSuite[MaxCount];
pBss->WPA2.au4AuthKeyMgtSuite[MaxCount] = TmpAKMSuite;
}
/* Fixed for WPA-None*/
if (pBss->BssType == BSS_ADHOC) {
pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
pBss->WPA.u4PairwiseCipherCount = 1;
/* Patched bugs for old driver*/
if (pBss->WPA.PairCipher[0] == Ndis802_11WEPDisabled)
pBss->WPA.PairCipher[0] = pBss->WPA.GroupCipher;
pBss->WepStatus = pBss->WPA.PairCipher[0];
} else
pBss->WepStatus = pBss->WPA2.PairCipher[0];
/* 6. Get RSN capability*/
/*pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;*/
pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
pTmp += sizeof(USHORT);
/* 7. Get PmkidCount */
Count = (pTmp[1]<<8) + pTmp[0];
pBss->WPA2.u2PmkidCnt = (Count > MAX_NUM_SUPPORTED_PMKID)?MAX_NUM_SUPPORTED_PMKID:Count;
pTmp += sizeof(USHORT);
/* 8. Parsing Pmkid List*/
NdisCopyMemory(pBss->WPA2.aucPmkidList, pTmp, (pBss->WPA2.u2PmkidCnt * RSN_PMKID_LEN));
pTmp += sizeof(UCHAR) * (pBss->WPA2.u2PmkidCnt * RSN_PMKID_LEN);
/* 9. Get u4GroupMgmtCipherSuite */
pBss->WPA2.u4GroupMgmtKeyCipherSuite = (pTmp[3]<<24) + (pTmp[2]<<16) + (pTmp[1]<<8) + pTmp[0];
pTmp += sizeof(UINT);
/* Check the Pair & Group, if different, turn on mixed mode flag*/
if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher[0])
pBss->WPA2.bMixMode = TRUE;
#else /* WPA3_SUPPORT */
/* 2. Get pairwise cipher counts*/
/*Count = *(PUSHORT) pTmp;*/
Count = (pTmp[1]<<8) + pTmp[0];
pTmp += sizeof(USHORT);
/* 3. Get pairwise cipher*/
/* Parsing all unicast cipher suite*/
while (Count > 0)
{
/* Skip OUI*/
pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
TmpCipher = Ndis802_11WEPDisabled;
switch (pCipher->Type)
{
case 1:
case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway*/
TmpCipher = Ndis802_11WEPEnabled;
break;
case 2:
TmpCipher = Ndis802_11TKIPEnable;
break;
case 4:
TmpCipher = Ndis802_11AESEnable;
break;
default:
break;
}
if (TmpCipher > pBss->WPA2.PairCipher)
{
/* Move the lower cipher suite to PairCipherAux*/
pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
pBss->WPA2.PairCipher = TmpCipher;
}
else
{
pBss->WPA2.PairCipherAux = TmpCipher;
}
pTmp += sizeof(CIPHER_SUITE_STRUCT);
Count--;
}
/* 4. get AKM suite counts*/
/*Count = *(PUSHORT) pTmp;*/
Count = (pTmp[1]<<8) + pTmp[0];
pTmp += sizeof(USHORT);
if (Count > 1)
fgMultiAKMs = TRUE;
/* 5. Get AKM ciphers*/
/* Parsing all AKM ciphers*/
while (Count > 0)
{
pAKM = (PAKM_SUITE_STRUCT) pTmp;
if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
break;
switch (pAKM->Type)
{
case 0:
if (pBss->AuthMode == Ndis802_11AuthModeOpen)
pBss->AuthMode = Ndis802_11AuthModeWPANone;
else
pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
break;
case 1:
#ifdef DOT11R_FT_SUPPORT
case 3:
#endif /* DOT11R_FT_SUPPORT */
/* Set AP support WPA-enterprise mode*/
if (pBss->AuthMode == Ndis802_11AuthModeOpen)
pBss->AuthMode = Ndis802_11AuthModeWPA2;
else
pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
break;
case 2:
#ifdef DOT11R_FT_SUPPORT
case 4:
#endif /* DOT11R_FT_SUPPORT */
#ifdef DOT11W_PMF_SUPPORT
case 6:
#endif /* DOT11W_PMF_SUPPORT */
/* Set AP support WPA-PSK mode*/
if (pBss->AuthMode == Ndis802_11AuthModeOpen)
pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
else
pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
#ifdef DOT11W_PMF_SUPPORT
if (pAKM->Type == 6)
pBss->IsSupportSHA256KeyDerivation = TRUE;
#endif /* DOT11W_PMF_SUPPORT */
break;
default:
if (fgMultiAKMs)
break;
if (pBss->AuthMode == Ndis802_11AuthModeOpen)
pBss->AuthMode = Ndis802_11AuthModeMax;
else
pBss->AuthModeAux = Ndis802_11AuthModeMax;
break;
}
pTmp += sizeof(AKM_SUITE_STRUCT);
Count--;
}
/* Fixed for WPA-None*/
if (pBss->BssType == BSS_ADHOC)
{
pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
pBss->WepStatus = pBss->WPA.GroupCipher;
/* Patched bugs for old driver*/
if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
}
pBss->WepStatus = pBss->WPA2.PairCipher;
/* 6. Get RSN capability*/
/*pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;*/
pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
pTmp += sizeof(USHORT);
/* Check the Pair & Group, if different, turn on mixed mode flag*/
if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
pBss->WPA2.bMixMode = TRUE;
#endif /* WPA3_SUPPORT */
break;
#ifdef WAPI_SUPPORT
case IE_WAPI:
#if 0
{
int c = 0;
printk("wapi_ie(len-%d):",Length);
for (c = 0; c < Length; c++)
printk("%02x-", (*pTmp+c));
printk("\n");
}
#endif
pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
/* 0. The version number must be 1*/
if (le2cpu16(pRsnHeader->Version) != 1)
break;
pTmp += sizeof(RSN_IE_HEADER_STRUCT);
/* 1. Get AKM suite counts*/
NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
Count = cpu2le16(Count);
pTmp += sizeof(USHORT);
#ifdef WPA3_SUPPORT
pBss->u4AuthModeCount = Count;
#endif
/* 2. Get AKM ciphers*/
pAKM = (PAKM_SUITE_STRUCT) pTmp;
if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3))
break;
switch (pAKM->Type)
{
case 1:
/* Support WAI certificate authentication*/
#ifdef WPA3_SUPPORT
pBss->AuthMode[0] = Ndis802_11AuthModeWAICERT;
#else
pBss->AuthMode = Ndis802_11AuthModeWAICERT;
#endif
break;
case 2:
#ifdef WPA3_SUPPORT
/* Support WAI PSK*/
pBss->AuthMode[0] = Ndis802_11AuthModeWAIPSK;
#else
/* Support WAI PSK*/
pBss->AuthMode = Ndis802_11AuthModeWAIPSK;
#endif
break;
default:
break;
}
pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
/* 3. Get pairwise cipher counts*/
NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
Count = cpu2le16(Count);
pTmp += sizeof(USHORT);
#ifdef WPA3_SUPPORT
pBss->WAPI.u4PairwiseCipherCount = Count;
TmpCount = 0;
/* 4. Get pairwise cipher*/
/* Parsing all unicast cipher suite*/
while (Count > 0) {
if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3))
break;
switch (*pTmp) {
case 1:
pBss->WPAI.PairCipher[TmpCount] = Ndis802_11EncryptionSMS4Enabled;
break;
default:
break;
}
pTmp += sizeof(CIPHER_SUITE_STRUCT);
Count--;
TmpCount++;
}
/* sort the PairCipher, PairCipher[0] would be the max*/
for (Count = 0; Count < (pBss->WPAI.u4PairwiseCipherCount-1); Count++) {
MaxCount = Count;
for (TmpCount = (Count+1); TmpCount < pBss->WPAI.u4PairwiseCipherCount; TmpCount++)
if (pBss->WPAI.PairCipher[TmpCount] > pBss->WPAI.PairCipher[MaxCount])
MaxCount = TmpCount;
TmpCipher = pBss->WPAI.PairCipher[Count];
pBss->WPAI.PairCipher[Count] = pBss->WPAI.PairCipher[MaxCount];
pBss->WPAI.PairCipher[MaxCount] = TmpCipher;
}
#else
/* 4. Get pairwise cipher*/
/* Parsing all unicast cipher suite*/
while (Count > 0)
{
if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3))
break;
/* Skip OUI*/
pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
TmpCipher = Ndis802_11WEPDisabled;
switch (pCipher->Type)
{
case 1:
TmpCipher = Ndis802_11EncryptionSMS4Enabled;
break;
default:
break;
}
if (TmpCipher > pBss->WAPI.PairCipher)
{
/* Move the lower cipher suite to PairCipherAux*/
pBss->WAPI.PairCipherAux = pBss->WAPI.PairCipher;
pBss->WAPI.PairCipher = TmpCipher;
}
else
{
pBss->WAPI.PairCipherAux = TmpCipher;
}
pTmp += sizeof(CIPHER_SUITE_STRUCT);
Count--;
}
#endif
/* 5. Check group cipher*/
if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3))
break;
pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
/* Parse group cipher*/
switch (pCipher->Type)
{
case 1:
pBss->WAPI.GroupCipher = Ndis802_11EncryptionSMS4Enabled;
break;
default:
break;
}
/* set to correct offset for next parsing*/
pTmp += sizeof(CIPHER_SUITE_STRUCT);
/* update the encryption type*/
pBss->WepStatus = pBss->WAPI.PairCipher;
/* update the WAPI capability*/
pBss->WAPI.RsnCapability = (pTmp[1]<<8) + pTmp[0];
pTmp += sizeof(USHORT);
break;
#endif /* WAPI_SUPPORT */
default:
break;
}
Length -= (pEid->Len + 2);
}
}
/*! \brief generates a random mac address value for IBSS BSSID
* \param Addr the bssid location
* \return none
* \pre
* \post
*/
VOID MacAddrRandomBssid(RTMP_ADAPTER *pAd, UCHAR *pAddr)
{
INT i;
for (i = 0; i < MAC_ADDR_LEN; i++)
{
pAddr[i] = RandomByte(pAd);
}
pAddr[0] = (pAddr[0] & 0xfe) | 0x02; /* the first 2 bits must be 01xxxxxxxx*/
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID AssocParmFill(
IN PRTMP_ADAPTER pAd,
IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
IN PUCHAR pAddr,
IN USHORT CapabilityInfo,
IN ULONG Timeout,
IN USHORT ListenIntv)
{
COPY_MAC_ADDR(AssocReq->Addr, pAddr);
/* Add mask to support 802.11b mode only */
AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; /* not cf-pollable, not cf-poll-request*/
AssocReq->Timeout = Timeout;
AssocReq->ListenIntv = ListenIntv;
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID DisassocParmFill(
IN PRTMP_ADAPTER pAd,
IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
IN PUCHAR pAddr,
IN USHORT Reason)
{
COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
DisassocReq->Reason = Reason;
}
/*! \brief init the management mac frame header
* \param p_hdr mac header
* \param subtype subtype of the frame
* \param p_ds destination address, don't care if it is a broadcast address
* \return none
* \pre the station has the following information in the pAd->StaCfg
* - bssid
* - station address
* \post
* \note this function initializes the following field
*/
VOID MgtMacHeaderInit(
IN RTMP_ADAPTER *pAd,
INOUT HEADER_802_11 *pHdr80211,
IN UCHAR SubType,
IN UCHAR ToDs,
IN UCHAR *pDA,
IN UCHAR *pSA,
IN UCHAR *pBssid)
{
NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
pHdr80211->FC.Type = FC_TYPE_MGMT;
pHdr80211->FC.SubType = SubType;
pHdr80211->FC.ToDs = ToDs;
COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) || defined(CFG80211_MULTI_STA)
COPY_MAC_ADDR(pHdr80211->Addr2, pSA);
#else
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
COPY_MAC_ADDR(pHdr80211->Addr2, pBssid);
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
#endif /* CONFIG_STA_SUPPORT */
#endif /* P2P_SUPPORT */
COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
}
VOID MgtMacHeaderInitExt(
IN RTMP_ADAPTER *pAd,
IN OUT HEADER_802_11 *pHdr80211,
IN UCHAR SubType,
IN UCHAR ToDs,
IN UCHAR *pAddr1,
IN UCHAR *pAddr2,
IN UCHAR *pAddr3)
{
NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
pHdr80211->FC.Type = FC_TYPE_MGMT;
pHdr80211->FC.SubType = SubType;
pHdr80211->FC.ToDs = ToDs;
COPY_MAC_ADDR(pHdr80211->Addr1, pAddr1);
COPY_MAC_ADDR(pHdr80211->Addr2, pAddr2);
COPY_MAC_ADDR(pHdr80211->Addr3, pAddr3);
}
/*!***************************************************************************
* This routine build an outgoing frame, and fill all information specified
* in argument list to the frame body. The actual frame size is the summation
* of all arguments.
* input params:
* Buffer - pointer to a pre-allocated memory segment
* args - a list of <int arg_size, arg> pairs.
* NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
* function will FAIL!!!
* return:
* Size of the buffer
* usage:
* MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
IRQL = PASSIVE_LEVEL
IRQL = DISPATCH_LEVEL
****************************************************************************/
ULONG MakeOutgoingFrame(UCHAR *Buffer, ULONG *FrameLen, ...)
{
UCHAR *p;
int leng;
ULONG TotLeng;
va_list Args;
/* calculates the total length*/
TotLeng = 0;
va_start(Args, FrameLen);
do
{
leng = va_arg(Args, int);
if (leng == END_OF_ARGS)
{
break;
}
p = va_arg(Args, PVOID);
NdisMoveMemory(&Buffer[TotLeng], p, leng);
TotLeng = TotLeng + leng;
} while(TRUE);
va_end(Args); /* clean up */
*FrameLen = TotLeng;
return TotLeng;
}
/*! \brief Initialize The MLME Queue, used by MLME Functions
* \param *Queue The MLME Queue
* \return Always Return NDIS_STATE_SUCCESS in this implementation
* \pre
* \post
* \note Because this is done only once (at the init stage), no need to be locked
IRQL = PASSIVE_LEVEL
*/
NDIS_STATUS MlmeQueueInit(RTMP_ADAPTER *pAd, MLME_QUEUE *Queue)
{
INT i;
NdisAllocateSpinLock(pAd, &Queue->Lock);
Queue->Num = 0;
Queue->Head = 0;
Queue->Tail = 0;
for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
{
Queue->Entry[i].Occupied = FALSE;
Queue->Entry[i].MsgLen = 0;
NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
}
return NDIS_STATUS_SUCCESS;
}
/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
* \param *Queue The MLME Queue
* \param Machine The State Machine Id
* \param MsgType The Message Type
* \param MsgLen The Message length
* \param *Msg The message pointer
* \return TRUE if enqueue is successful, FALSE if the queue is full
* \pre
* \post
* \note The message has to be initialized
*/
BOOLEAN MlmeEnqueue(
IN RTMP_ADAPTER *pAd,
IN ULONG Machine,
IN ULONG MsgType,
IN ULONG MsgLen,
IN VOID *Msg,
IN ULONG Priv)
{
INT Tail;
MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
/* Do nothing if the driver is starting halt state.*/
/* This might happen when timer already been fired before cancel timer with mlmehalt*/
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
return FALSE;
/* First check the size, it MUST not exceed the mlme queue size*/
if (MsgLen > MGMT_DMA_BUFFER_SIZE)
{
DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
return FALSE;
}
if (MlmeQueueFull(Queue, 1))
{
#ifdef RELEASE_EXCLUDE
/* Can't add debug print here. It'll make Mlme Stat machine freeze.*/
DBGPRINT(RT_DEBUG_INFO, ("%s():full, msg dropped and may corrupt MLME\n", __FUNCTION__));
#endif /* RELEASE_EXCLUDE */
return FALSE;
}
NdisAcquireSpinLock(&(Queue->Lock));
Tail = Queue->Tail;
/*
Double check for safety in multi-thread system.
*/
if (Queue->Entry[Tail].Occupied)
{
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("%s():full#2, msg dropped and may corrupt MLME\n", __FUNCTION__));
#endif /* RELEASE_EXCLUDE */
NdisReleaseSpinLock(&(Queue->Lock));
return FALSE;
}
Queue->Tail++;
Queue->Num++;
if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
Queue->Tail = 0;
Queue->Entry[Tail].Wcid = RESERVED_WCID;
Queue->Entry[Tail].Occupied = TRUE;
Queue->Entry[Tail].Machine = Machine;
Queue->Entry[Tail].MsgType = MsgType;
Queue->Entry[Tail].MsgLen = MsgLen;
Queue->Entry[Tail].Priv = Priv;
if (Msg != NULL)
{
NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
}
NdisReleaseSpinLock(&(Queue->Lock));
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("MlmeEnqueue, num=%ld\n",Queue->Num));
#endif /* RELEASE_EXCLUDE */
return TRUE;
}
/*! \brief This function is used when Recv gets a MLME message
* \param *Queue The MLME Queue
* \param TimeStampHigh The upper 32 bit of timestamp
* \param TimeStampLow The lower 32 bit of timestamp
* \param Rssi The receiving RSSI strength
* \param MsgLen The length of the message
* \param *Msg The message pointer
* \return TRUE if everything ok, FALSE otherwise (like Queue Full)
* \pre
* \post
*/
BOOLEAN MlmeEnqueueForRecv(
IN RTMP_ADAPTER *pAd,
IN ULONG Wcid,
IN struct raw_rssi_info *rssi_info,
IN ULONG MsgLen,
IN VOID *Msg,
IN UCHAR OpMode)
{
INT Tail, Machine = 0xff;
UINT32 TimeStampHigh, TimeStampLow;
PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
INT MsgType = 0x0;
MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
#ifdef APCLI_SUPPORT
UCHAR ApCliIdx = 0;
#endif /* APCLI_SUPPORT */
#ifdef MAC_REPEATER_SUPPORT
UCHAR CliIdx = 0;
#endif /* MAC_REPEATER_SUPPORT */
#ifdef CONFIG_ATE
/* Nothing to do in ATE mode */
if(ATE_ON(pAd))
return FALSE;
#endif /* CONFIG_ATE */
/*
Do nothing if the driver is starting halt state.
This might happen when timer already been fired before cancel timer with mlmehalt
*/
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
{
DBGPRINT_ERR(("%s(): fRTMP_ADAPTER_HALT_IN_PROGRESS\n", __FUNCTION__));
return FALSE;
}
/* First check the size, it MUST not exceed the mlme queue size*/
if (MsgLen > MGMT_DMA_BUFFER_SIZE)
{
DBGPRINT_ERR(("%s(): frame too large, size = %ld \n", __FUNCTION__, MsgLen));
return FALSE;
}
if (MlmeQueueFull(Queue, 0))
{
#ifdef RELEASE_EXCLUDE
/* Can't add debug print here. It'll make Mlme Stat machine freeze.*/
DBGPRINT(RT_DEBUG_INFO, ("%s(): full and dropped\n", __FUNCTION__));
#endif /* RELEASE_EXCLUDE */
RTMP_MLME_HANDLER(pAd);
return FALSE;
}
#ifdef CONFIG_AP_SUPPORT
#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) || defined(CFG80211_MULTI_STA)
if (OpMode == OPMODE_AP)
#else
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT */
{
#ifdef P2P_SUPPORT
if (P2P_CLI_ON(pAd))
{
if (pFrame->Hdr.FC.SubType == SUBTYPE_PROBE_REQ)
return FALSE;
}
#endif /* P2P_SUPPORT */
#ifdef APCLI_SUPPORT
/*
Beacon must be handled by ap-sync state machine.
Probe-rsp must be handled by apcli-sync state machine.
Those packets don't need to check its MAC address
*/
do
{
BOOLEAN bToApCli = FALSE;
UCHAR i;
/*
1. When P2P GO On and receive Probe Response, preCheckMsgTypeSubset function will
enquene Probe response to APCli sync state machine
Solution: when GO On skip preCheckMsgTypeSubset redirect to APMsgTypeSubst
2. When P2P Cli On and receive Probe Response, preCheckMsgTypeSubset function will
enquene Probe response to APCli sync state machine
Solution: handle MsgType == APCLI_MT2_PEER_PROBE_RSP on ApCli Sync state machine
when ApCli on idle state.
*/
for (i = 0; i < pAd->ApCfg.ApCliNum; i++)
{
if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[i].MlmeAux.Bssid, pFrame->Hdr.Addr2))
{
bToApCli = TRUE;
break;
}
}
if (!MAC_ADDR_EQUAL(pFrame->Hdr.Addr1, pAd->CurrentAddress) &&
#ifdef P2P_SUPPORT
!P2P_GO_ON(pAd) &&
#endif /* P2P_SUPPORT */
preCheckMsgTypeSubset(pAd, pFrame, &Machine, &MsgType))
break;
if (!MAC_ADDR_EQUAL(pFrame->Hdr.Addr1, pAd->CurrentAddress) && bToApCli)
{
if (ApCliMsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
break;
}
else
{
if (APMsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
break;
}
DBGPRINT_ERR(("%s(): un-recongnized mgmt->subtype=%d, STA-%02x:%02x:%02x:%02x:%02x:%02x\n",
__FUNCTION__, pFrame->Hdr.FC.SubType, PRINT_MAC(pFrame->Hdr.Addr2)));
return FALSE;
} while (FALSE);
#else
if (!APMsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
{
DBGPRINT(RT_DEBUG_TRACE,("%s(): un-recongnized mgmt->subtype=%d\n",
__FUNCTION__, pFrame->Hdr.FC.SubType));
return FALSE;
}
#endif /* APCLI_SUPPORT */
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) || defined(CFG80211_MULTI_STA)
if (OpMode == OPMODE_STA)
#else
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
#endif /* P2P_SUPPORT */
{
if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
{
#ifdef WIDI_SUPPORT
if (!pAd->StaCfg.WscControl.bWscTrigger)
#endif /* WIDI_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE,("%s(): un-recongnized mgmt->subtype=%d\n",
__FUNCTION__, pFrame->Hdr.FC.SubType));
return FALSE;
}
}
#endif /* CONFIG_STA_SUPPORT */
TimeStampHigh = TimeStampLow = 0;
#ifdef RTMP_MAC_PCI
if (!IS_USB_INF(pAd))
AsicGetTsfTime(pAd, &TimeStampHigh, &TimeStampLow);
#endif /* RTMP_MAC_PCI */
/* OK, we got all the informations, it is time to put things into queue*/
NdisAcquireSpinLock(&(Queue->Lock));
Tail = Queue->Tail;
/*
Double check for safety in multi-thread system.
*/
if (Queue->Entry[Tail].Occupied)
{
NdisReleaseSpinLock(&(Queue->Lock));
return FALSE;
}
Queue->Tail++;
Queue->Num++;
if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
Queue->Tail = 0;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("%s():num=%ld\n", __FUNCTION__, Queue->Num));
#endif /* RELEASE_EXCLUDE */
Queue->Entry[Tail].Occupied = TRUE;
Queue->Entry[Tail].Machine = Machine;
Queue->Entry[Tail].MsgType = MsgType;
Queue->Entry[Tail].MsgLen = MsgLen;
Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
NdisMoveMemory(&Queue->Entry[Tail].rssi_info, rssi_info, sizeof(struct raw_rssi_info));
Queue->Entry[Tail].Signal = rssi_info->raw_snr;
Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
Queue->Entry[Tail].OpMode = (UCHAR)OpMode;
Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
Queue->Entry[Tail].Priv = 0;
#ifdef APCLI_SUPPORT
Queue->Entry[Tail].Priv = ApCliIdx;
#endif /* APCLI_SUPPORT */
#ifdef MAC_REPEATER_SUPPORT
if (pAd->ApCfg.bMACRepeaterEn)
{
for (CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++)
{
if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ApCliIdx].RepeaterCli[CliIdx].CurrentAddress, pFrame->Hdr.Addr1))
{
Queue->Entry[Tail].Priv = (64 + (MAX_EXT_MAC_ADDR_SIZE * ApCliIdx) + CliIdx);
break;
}
}
}
#endif /* MAC_REPEATER_SUPPORT */
if (Msg != NULL)
{
NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
}
NdisReleaseSpinLock(&(Queue->Lock));
RTMP_MLME_HANDLER(pAd);
return TRUE;
}
#ifdef WSC_INCLUDED
/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
* \param *Queue The MLME Queue
* \param TimeStampLow The lower 32 bit of timestamp, here we used for eventID.
* \param Machine The State Machine Id
* \param MsgType The Message Type
* \param MsgLen The Message length
* \param *Msg The message pointer
* \return TRUE if enqueue is successful, FALSE if the queue is full
* \pre
* \post
* \note The message has to be initialized
*/
BOOLEAN MlmeEnqueueForWsc(
IN RTMP_ADAPTER *pAd,
IN ULONG eventID,
IN LONG senderID,
IN ULONG Machine,
IN ULONG MsgType,
IN ULONG MsgLen,
IN VOID *Msg)
{
INT Tail;
MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
DBGPRINT(RT_DEBUG_TRACE, ("-----> MlmeEnqueueForWsc\n"));
/* Do nothing if the driver is starting halt state.*/
/* This might happen when timer already been fired before cancel timer with mlmehalt*/
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
return FALSE;
/* First check the size, it MUST not exceed the mlme queue size*/
if (MsgLen > MGMT_DMA_BUFFER_SIZE)
{
DBGPRINT_ERR(("MlmeEnqueueForWsc: msg too large, size = %ld \n", MsgLen));
return FALSE;
}
if (MlmeQueueFull(Queue, 1))
{
#ifdef RELEASE_EXCLUDE
/* Can't add debug print here. It'll make Mlme Stat machine freeze.*/
DBGPRINT(RT_DEBUG_INFO, ("MlmeEnqueueForWsc: full, msg dropped and may corrupt MLME\n"));
#endif /* RELEASE_EXCLUDE */
return FALSE;
}
/* OK, we got all the informations, it is time to put things into queue*/
NdisAcquireSpinLock(&(Queue->Lock));
Tail = Queue->Tail;
/*
Double check for safety in multi-thread system.
*/
if (Queue->Entry[Tail].Occupied)
{
NdisReleaseSpinLock(&(Queue->Lock));
return FALSE;
}
Queue->Tail++;
Queue->Num++;
if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
{
Queue->Tail = 0;
}
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("MlmeEnqueueForWsc, num=%ld\n",Queue->Num));
#endif /* RELEASE_EXCLUDE */
Queue->Entry[Tail].Occupied = TRUE;
Queue->Entry[Tail].Machine = Machine;
Queue->Entry[Tail].MsgType = MsgType;
Queue->Entry[Tail].MsgLen = MsgLen;
Queue->Entry[Tail].TimeStamp.u.LowPart = eventID;
Queue->Entry[Tail].TimeStamp.u.HighPart = senderID;
if (Msg != NULL)
NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
NdisReleaseSpinLock(&(Queue->Lock));
DBGPRINT(RT_DEBUG_TRACE, ("<----- MlmeEnqueueForWsc\n"));
return TRUE;
}
#endif /* WSC_INCLUDED */
/*! \brief Dequeue a message from the MLME Queue
* \param *Queue The MLME Queue
* \param *Elem The message dequeued from MLME Queue
* \return TRUE if the Elem contains something, FALSE otherwise
* \pre
* \post
*/
BOOLEAN MlmeDequeue(MLME_QUEUE *Queue, MLME_QUEUE_ELEM **Elem)
{
NdisAcquireSpinLock(&(Queue->Lock));
*Elem = &(Queue->Entry[Queue->Head]);
Queue->Num--;
Queue->Head++;
if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
{
Queue->Head = 0;
}
NdisReleaseSpinLock(&(Queue->Lock));
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("MlmeDequeue, num=%ld\n",Queue->Num));
#endif /* RELEASE_EXCLUDE */
return TRUE;
}
VOID MlmeRestartStateMachine(RTMP_ADAPTER *pAd)
{
#ifdef RTMP_MAC_PCI
MLME_QUEUE_ELEM *Elem = NULL;
#endif /* RTMP_MAC_PCI */
#ifdef CONFIG_STA_SUPPORT
BOOLEAN Cancelled;
#ifdef P2P_SUPPORT
PAPCLI_STRUCT pApCliEntry = NULL;
#endif /* P2P_SUPPORT */
#endif /* CONFIG_STA_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
#ifdef RTMP_MAC_PCI
NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
if(pAd->Mlme.bRunning)
{
NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
return;
}
else
{
pAd->Mlme.bRunning = TRUE;
}
NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
/* Remove all Mlme queues elements*/
while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
{
/*From message type, determine which state machine I should drive*/
if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
{
/* free MLME element*/
Elem->Occupied = FALSE;
Elem->MsgLen = 0;
}
else {
DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
}
}
#endif /* RTMP_MAC_PCI */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
#ifdef QOS_DLS_SUPPORT
UCHAR i;
#endif /* QOS_DLS_SUPPORT */
/* Cancel all timer events*/
/* Be careful to cancel new added timer*/
RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
#ifdef QOS_DLS_SUPPORT
for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
{
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
}
#endif /* QOS_DLS_SUPPORT */
}
#endif /* CONFIG_STA_SUPPORT */
/* Change back to original channel in case of doing scan*/
#ifdef P2P_SUPPORT
pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0];
if (!P2P_GO_ON(pAd) && (pApCliEntry->Valid == FALSE))
#endif /* P2P_SUPPORT */
{
AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
AsicLockChannel(pAd, pAd->CommonCfg.Channel);
}
/* Resume MSDU which is turned off durning scan*/
RTMPResumeMsduTransmission(pAd);
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
/* Set all state machines back IDLE*/
pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
#ifdef QOS_DLS_SUPPORT
pAd->Mlme.DlsMachine.CurrState = DLS_IDLE;
#endif /* QOS_DLS_SUPPORT */
#ifdef DOT11Z_TDLS_SUPPORT
pAd->Mlme.TdlsMachine.CurrState = TDLS_IDLE;
#endif /* DOT11Z_TDLS_SUPPORT */
}
#endif /* CONFIG_STA_SUPPORT */
#ifdef RTMP_MAC_PCI
/* Remove running state*/
NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
pAd->Mlme.bRunning = FALSE;
NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
#endif /* RTMP_MAC_PCI */
//CFG_TODO for SCAN
#ifdef RT_CFG80211_SUPPORT
RTEnqueueInternalCmd(pAd, CMDTHREAD_SCAN_END, NULL, 0);
#endif /* RT_CFG80211_SUPPORT */
}
/*! \brief test if the MLME Queue is empty
* \param *Queue The MLME Queue
* \return TRUE if the Queue is empty, FALSE otherwise
* \pre
* \post
IRQL = DISPATCH_LEVEL
*/
BOOLEAN MlmeQueueEmpty(MLME_QUEUE *Queue)
{
BOOLEAN Ans;
NdisAcquireSpinLock(&(Queue->Lock));
Ans = (Queue->Num == 0);
NdisReleaseSpinLock(&(Queue->Lock));
return Ans;
}
/*! \brief test if the MLME Queue is full
* \param *Queue The MLME Queue
* \return TRUE if the Queue is empty, FALSE otherwise
* \pre
* \post
IRQL = PASSIVE_LEVEL
IRQL = DISPATCH_LEVEL
*/
BOOLEAN MlmeQueueFull(MLME_QUEUE *Queue, UCHAR SendId)
{
BOOLEAN Ans;
NdisAcquireSpinLock(&(Queue->Lock));
if (SendId == 0)
Ans = ((Queue->Num >= (MAX_LEN_OF_MLME_QUEUE / 2)) || Queue->Entry[Queue->Tail].Occupied);
else
Ans = ((Queue->Num == MAX_LEN_OF_MLME_QUEUE) || Queue->Entry[Queue->Tail].Occupied);
NdisReleaseSpinLock(&(Queue->Lock));
return Ans;
}
/*! \brief The destructor of MLME Queue
* \param
* \return
* \pre
* \post
* \note Clear Mlme Queue, Set Queue->Num to Zero.
IRQL = PASSIVE_LEVEL
*/
VOID MlmeQueueDestroy(MLME_QUEUE *pQueue)
{
NdisAcquireSpinLock(&(pQueue->Lock));
pQueue->Num = 0;
pQueue->Head = 0;
pQueue->Tail = 0;
NdisReleaseSpinLock(&(pQueue->Lock));
NdisFreeSpinLock(&(pQueue->Lock));
}
/*! \brief To substitute the message type if the message is coming from external
* \param pFrame The frame received
* \param *Machine The state machine
* \param *MsgType the message type for the state machine
* \return TRUE if the substitution is successful, FALSE otherwise
* \pre
* \post
IRQL = DISPATCH_LEVEL
*/
#ifdef CONFIG_STA_SUPPORT
BOOLEAN MsgTypeSubst(RTMP_ADAPTER *pAd, FRAME_802_11 *pFrame, INT *Machine, INT *MsgType)
{
USHORT Seq, Alg;
UCHAR EAPType;
PUCHAR pData;
BOOLEAN bRV = FALSE;
#ifdef WSC_STA_SUPPORT
UCHAR EAPCode;
#endif /* WSC_STA_SUPPORT */
/* Pointer to start of data frames including SNAP header*/
pData = (PUCHAR) pFrame + LENGTH_802_11;
/* The only data type will pass to this function is EAPOL frame*/
if (pFrame->Hdr.FC.Type == FC_TYPE_DATA)
{
#ifdef DOT11Z_TDLS_SUPPORT
if (NdisEqualMemory(TDLS_LLC_SNAP_WITH_CATEGORY, pData, LENGTH_802_1_H + 2))
{
UCHAR TDLSType;
/* ieee802.11z TDLS SNAP header*/
*Machine = TDLS_STATE_MACHINE;
TDLSType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 2);
return (TDLS_MsgTypeSubst(TDLSType, (INT *)MsgType));
}
else
#endif /* DOT11Z_TDLS_SUPPORT */
#ifdef WSC_STA_SUPPORT
/* check for WSC state machine first*/
if (pAd->StaCfg.WscControl.WscState >= WSC_STATE_LINK_UP)
{
*Machine = WSC_STATE_MACHINE;
EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
EAPCode = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 4);
bRV = WscMsgTypeSubst(EAPType, EAPCode, MsgType);
if (bRV)
return bRV;
}
#endif /* WSC_STA_SUPPORT */
if (bRV == FALSE)
{
*Machine = WPA_STATE_MACHINE;
EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
return (WpaMsgTypeSubst(EAPType, (INT *) MsgType));
}
}
switch (pFrame->Hdr.FC.SubType)
{
case SUBTYPE_ASSOC_REQ:
*Machine = ASSOC_STATE_MACHINE;
*MsgType = MT2_PEER_ASSOC_REQ;
break;
case SUBTYPE_ASSOC_RSP:
*Machine = ASSOC_STATE_MACHINE;
*MsgType = MT2_PEER_ASSOC_RSP;
break;
case SUBTYPE_REASSOC_REQ:
*Machine = ASSOC_STATE_MACHINE;
*MsgType = MT2_PEER_REASSOC_REQ;
break;
case SUBTYPE_REASSOC_RSP:
*Machine = ASSOC_STATE_MACHINE;
*MsgType = MT2_PEER_REASSOC_RSP;
break;
case SUBTYPE_PROBE_REQ:
*Machine = SYNC_STATE_MACHINE;
*MsgType = MT2_PEER_PROBE_REQ;
break;
case SUBTYPE_PROBE_RSP:
*Machine = SYNC_STATE_MACHINE;
*MsgType = MT2_PEER_PROBE_RSP;
break;
case SUBTYPE_BEACON:
*Machine = SYNC_STATE_MACHINE;
*MsgType = MT2_PEER_BEACON;
break;
case SUBTYPE_ATIM:
*Machine = SYNC_STATE_MACHINE;
*MsgType = MT2_PEER_ATIM;
break;
case SUBTYPE_DISASSOC:
*Machine = ASSOC_STATE_MACHINE;
*MsgType = MT2_PEER_DISASSOC_REQ;
break;
case SUBTYPE_AUTH:
/* get the sequence number from payload 24 Mac Header + 2 bytes algorithm*/
NdisMoveMemory(&Seq, (UCHAR *)pFrame+sizeof(HEADER_802_11)+2, sizeof(USHORT));
NdisMoveMemory(&Alg, (UCHAR *)pFrame+sizeof(HEADER_802_11), sizeof(USHORT));
if ((Seq < 0) || (Seq > 4)) {
DBGPRINT(RT_DEBUG_ERROR, ("%s() Rx auth with unexpected TransactionSeqNum:%d\n", __func__, Seq));
return FALSE;
}
#ifdef WPA3_SUPPORT
if (Alg == AUTH_MODE_SAE) {
if ((Seq == 1) || (Seq == 2)) {
*Machine = AUTH_STATE_MACHINE;
*MsgType = MT2_PEER_AUTH_EVEN;
} else
DBGPRINT(RT_DEBUG_ERROR, ("%s() Rx SAE auth with unexpected TransSeqNum:%d\n", __func__, Seq));
} else {
#endif
if (Seq == 1 || Seq == 3)
{
*Machine = AUTH_RSP_STATE_MACHINE;
*MsgType = MT2_PEER_AUTH_ODD;
}
else if (Seq == 2 || Seq == 4)
{
#ifdef DOT11R_FT_SUPPORT
if (Alg == AUTH_MODE_FT)
{
*Machine = FT_OTA_AUTH_STATE_MACHINE;
*MsgType = FT_OTA_MT2_PEER_AUTH_EVEN;
}
else
#endif /* DOT11R_FT_SUPPORT */
if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY)
{
*Machine = AUTH_STATE_MACHINE;
*MsgType = MT2_PEER_AUTH_EVEN;
}
}
else
{
return FALSE;
}
#ifdef WPA3_SUPPORT
}
#endif
break;
case SUBTYPE_DEAUTH:
*Machine = AUTH_RSP_STATE_MACHINE;
*MsgType = MT2_PEER_DEAUTH;
break;
case SUBTYPE_ACTION:
case SUBTYPE_ACTION_NO_ACK:
*Machine = ACTION_STATE_MACHINE;
#ifdef DOT11R_FT_SUPPORT
if ((pFrame->Octet[0]&0x7F) == FT_CATEGORY_BSS_TRANSITION)
{
*Machine = FT_OTD_ACT_STATE_MACHINE;
*MsgType = FT_OTD_MT2_PEER_EVEN;
}
else
#endif /* DOT11R_FT_SUPPORT */
/* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support*/
if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
{
*MsgType = MT2_ACT_INVALID;
}
else
{
*MsgType = (pFrame->Octet[0]&0x7F);
}
break;
default:
return FALSE;
break;
}
return TRUE;
}
#endif /* CONFIG_STA_SUPPORT */
/*! \brief Initialize the state machine.
* \param *S pointer to the state machine
* \param Trans State machine transition function
* \param StNr number of states
* \param MsgNr number of messages
* \param DefFunc default function, when there is invalid state/message combination
* \param InitState initial state of the state machine
* \param Base StateMachine base, internal use only
* \pre p_sm should be a legal pointer
* \post
IRQL = PASSIVE_LEVEL
*/
VOID StateMachineInit(
IN STATE_MACHINE *S,
IN STATE_MACHINE_FUNC Trans[],
IN ULONG StNr,
IN ULONG MsgNr,
IN STATE_MACHINE_FUNC DefFunc,
IN ULONG InitState,
IN ULONG Base)
{
ULONG i, j;
/* set number of states and messages*/
S->NrState = StNr;
S->NrMsg = MsgNr;
S->Base = Base;
S->TransFunc = Trans;
/* init all state transition to default function*/
for (i = 0; i < StNr; i++)
{
for (j = 0; j < MsgNr; j++)
{
S->TransFunc[i * MsgNr + j] = DefFunc;
}
}
/* set the starting state*/
S->CurrState = InitState;
}
/*! \brief This function fills in the function pointer into the cell in the state machine
* \param *S pointer to the state machine
* \param St state
* \param Msg incoming message
* \param f the function to be executed when (state, message) combination occurs at the state machine
* \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state
* \post
IRQL = PASSIVE_LEVEL
*/
VOID StateMachineSetAction(
IN STATE_MACHINE *S,
IN ULONG St,
IN ULONG Msg,
IN STATE_MACHINE_FUNC Func)
{
ULONG MsgIdx;
MsgIdx = Msg - S->Base;
if (St < S->NrState && MsgIdx < S->NrMsg)
{
/* boundary checking before setting the action*/
S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
}
}
/*! \brief This function does the state transition
* \param *Adapter the NIC adapter pointer
* \param *S the state machine
* \param *Elem the message to be executed
* \return None
*/
VOID StateMachinePerformAction(
IN PRTMP_ADAPTER pAd,
IN STATE_MACHINE *S,
IN MLME_QUEUE_ELEM *Elem,
IN ULONG CurrState)
{
if (S->TransFunc[(CurrState) * S->NrMsg + Elem->MsgType - S->Base])
(*(S->TransFunc[(CurrState) * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
}
/*
==========================================================================
Description:
The drop function, when machine executes this, the message is simply
ignored. This function does nothing, the message is freed in
StateMachinePerformAction()
==========================================================================
*/
VOID Drop(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem)
{
}
/*
==========================================================================
Description:
==========================================================================
*/
UCHAR RandomByte(RTMP_ADAPTER *pAd)
{
ULONG i;
UCHAR R, Result;
R = 0;
if (pAd->Mlme.ShiftReg == 0)
NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
for (i = 0; i < 8; i++)
{
if (pAd->Mlme.ShiftReg & 0x00000001)
{
pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
Result = 1;
}
else
{
pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
Result = 0;
}
R = (R << 1) | Result;
}
return R;
}
UCHAR RandomByte2(RTMP_ADAPTER *pAd)
{
UINT32 a,b;
UCHAR value, seed = 0;
if (pAd->chipCap.hif_type == HIF_MT) {
DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n",
__FUNCTION__, __LINE__));
return 0;
}
/*MAC statistic related*/
a = AsicGetCCACnt(pAd);
a &= 0x0000ffff;
b = AsicGetCrcErrCnt(pAd);
b &= 0x0000ffff;
value = (UCHAR)((a<<16)|b);
/*get seed by RSSI or SNR related info */
seed = get_random_seed_by_phy(pAd);
return value ^ seed ^ RandomByte(pAd);
}
/*
========================================================================
Routine Description:
Verify the support rate for different PHY type
Arguments:
pAd Pointer to our adapter
Return Value:
None
IRQL = PASSIVE_LEVEL
========================================================================
*/
VOID RTMPCheckRates(RTMP_ADAPTER *pAd, UCHAR SupRate[], UCHAR *SupRateLen)
{
UCHAR RateIdx, i, j;
UCHAR NewRate[12]={0}, NewRateLen;
NewRateLen = 0;
if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B))
RateIdx = 4;
else
RateIdx = 12;
/* Check for support rates exclude basic rate bit */
for (i = 0; i < *SupRateLen && i < 12; i++)
for (j = 0; j < RateIdx; j++)
if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
{
NewRate[NewRateLen++] = SupRate[i];
break;
}
*SupRateLen = NewRateLen;
NdisMoveMemory(SupRate, NewRate, NewRateLen);
}
#ifdef CONFIG_STA_SUPPORT
#ifdef DOT11_N_SUPPORT
BOOLEAN RTMPCheckChannel(RTMP_ADAPTER *pAd, UCHAR CentralCh, UCHAR ch)
{
UCHAR k;
UCHAR UpperChannel = 0, LowerChannel = 0;
UCHAR NoEffectChannelinList = 0;
/* Find upper and lower channel according to 40MHz current operation. */
if (CentralCh < ch)
{
UpperChannel = ch;
if (CentralCh > 2)
LowerChannel = CentralCh - 2;
else
return FALSE;
}
else if (CentralCh > ch)
{
UpperChannel = CentralCh + 2;
LowerChannel = ch;
}
for (k = 0;k < pAd->ChannelListNum;k++)
{
if (pAd->ChannelList[k].Channel == UpperChannel)
{
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO,("UpperChannel=%d is in Channel List[%d]\n", UpperChannel, k ));
#endif /* RELEASE_EXCLUDE */
NoEffectChannelinList ++;
}
if (pAd->ChannelList[k].Channel == LowerChannel)
{
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO,("LowerChannel=%d is in Channel List[%d]\n", LowerChannel, k ));
#endif /* RELEASE_EXCLUDE */
NoEffectChannelinList ++;
}
}
DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
if (NoEffectChannelinList == 2)
return TRUE;
else
return FALSE;
}
/*
========================================================================
Routine Description:
Verify the support rate for HT phy type
Arguments:
pAd Pointer to our adapter
Return Value:
FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
IRQL = PASSIVE_LEVEL
========================================================================
*/
BOOLEAN RTMPCheckHt(
IN RTMP_ADAPTER *pAd,
IN UCHAR Wcid,
IN HT_CAPABILITY_IE *pHtCap,
IN ADD_HT_INFO_IE *pAddHtInfo)
{
MAC_TABLE_ENTRY *sta;
if (Wcid >= MAX_LEN_OF_MAC_TABLE)
return FALSE;
sta = &pAd->MacTab.Content[Wcid];
/* If use AMSDU, set flag.*/
if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_AMSDU_INUSED);
/* Save Peer Capability*/
if (pAd->CommonCfg.ht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) {
if (pHtCap->HtCapInfo.ht_rx_ldpc)
CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_HT_RX_LDPC_CAPABLE);
}
if (pHtCap->HtCapInfo.ShortGIfor20)
CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_SGI20_CAPABLE);
if (pHtCap->HtCapInfo.ShortGIfor40)
CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_SGI40_CAPABLE);
if (pHtCap->HtCapInfo.TxSTBC)
CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_TxSTBC_CAPABLE);
if (pHtCap->HtCapInfo.RxSTBC)
CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_RxSTBC_CAPABLE);
if (pAd->CommonCfg.bRdg && pHtCap->ExtHtCapInfo.RDGSupport)
{
CLIENT_STATUS_SET_FLAG(sta, fCLIENT_STATUS_RDG_CAPABLE);
}
if (Wcid < MAX_LEN_OF_MAC_TABLE)
{
sta->MpduDensity = pHtCap->HtCapParm.MpduDensity;
}
/* Will check ChannelWidth for MCSSet[4] below*/
NdisZeroMemory(&pAd->MlmeAux.HtCapability.MCSSet[0], 16);
pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
switch (pAd->CommonCfg.RxStream)
{
case 3:
pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
case 2:
pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
case 1:
default:
pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
break;
}
pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
/*
If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
*/
if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40)
{
if (RTMPCheckChannel(pAd, pAd->MlmeAux.CentralChannel, pAd->MlmeAux.Channel) == FALSE)
{
pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = BW_20;
}
/*BW setting limited by EEPROM setting*/
if(pAd->MlmeAux.Channel > 14) /* a-band*/
{
if ( pAd->NicConfig2.field.BW40MAvailForA ) /* 1: OFF; 0: ON */
pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = BW_20;
}
else
{
if ( pAd->NicConfig2.field.BW40MAvailForG ) /* 1: OFF; 0: ON */
pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = BW_20;
}
}
DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCap->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
/* Send Assoc Req with my HT capability.*/
pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
/* The HT Capabilities element are used to advertise optional HT capabilities of an HT STA.
* We shouldn't care about the AP's Capabilities in here
*/
pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = pAd->CommonCfg.DesiredHtPhy.ShortGIfor20;
pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = pAd->CommonCfg.DesiredHtPhy.ShortGIfor40;
pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = pAd->CommonCfg.DesiredHtPhy.TxSTBC;
pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = pAd->CommonCfg.DesiredHtPhy.RxSTBC;
if (CLIENT_STATUS_TEST_FLAG(sta, fCLIENT_STATUS_HT_RX_LDPC_CAPABLE))
pAd->MlmeAux.HtCapability.HtCapInfo.ht_rx_ldpc = 1;
else
pAd->MlmeAux.HtCapability.HtCapInfo.ht_rx_ldpc = 0;
pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCap->ExtHtCapInfo.PlusHTC;
sta->HTCapability.ExtHtCapInfo.PlusHTC = pHtCap->ExtHtCapInfo.PlusHTC;
if (pAd->CommonCfg.bRdg)
{
pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCap->ExtHtCapInfo.RDGSupport;
pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
}
if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; /* BW20 can't transmit MCS32*/
#ifdef TXBF_SUPPORT
if (pAd->chipCap.FlgHwTxBfCap)
setETxBFCap(pAd, &pAd->MlmeAux.HtCapability.TxBFCap);
#endif /* TXBF_SUPPORT */
COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCap);
return TRUE;
}
#ifdef DOT11_VHT_AC
/*
========================================================================
Routine Description:
Verify the support rate for HT phy type
Arguments:
pAd Pointer to our adapter
Return Value:
FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
IRQL = PASSIVE_LEVEL
========================================================================
*/
BOOLEAN RTMPCheckVht(
IN PRTMP_ADAPTER pAd,
IN UCHAR Wcid,
IN VHT_CAP_IE *vht_cap,
IN VHT_OP_IE *vht_op)
{
VHT_CAP_INFO *vht_cap_info = &vht_cap->vht_cap;
MAC_TABLE_ENTRY *pEntry;
// TODO: shiang-6590, not finish yet!!!!
if (Wcid >= MAX_LEN_OF_MAC_TABLE)
return FALSE;
pEntry = &pAd->MacTab.Content[Wcid];
/* Save Peer Capability*/
if (vht_cap_info->sgi_80M)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI80_CAPABLE);
if (vht_cap_info->sgi_160M)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI160_CAPABLE);
if (vht_cap_info->tx_stbc)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_TXSTBC_CAPABLE);
if (vht_cap_info->rx_stbc)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RXSTBC_CAPABLE);
if (pAd->CommonCfg.vht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) {
if (vht_cap_info->rx_ldpc)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RX_LDPC_CAPABLE);
}
/* Will check ChannelWidth for MCSSet[4] below */
NdisZeroMemory(&pAd->MlmeAux.vht_cap.mcs_set, sizeof(VHT_MCS_SET));
pAd->MlmeAux.vht_cap.mcs_set.rx_high_rate = pAd->CommonCfg.RxStream * 325;
pAd->MlmeAux.vht_cap.mcs_set.tx_high_rate = pAd->CommonCfg.TxStream * 325;
//pAd->MlmeAux.vht_cap.vht_cap.ch_width = vht_cap_info->ch_width;
#ifdef VHT_TXBF_SUPPORT
if (pAd->chipCap.FlgHwTxBfCap)
setVHTETxBFCap(pAd, &pAd->MlmeAux.vht_cap.vht_cap);
#endif /* TXBF_SUPPORT */
return TRUE;
}
#endif /* DOT11_VHT_AC */
#endif /* DOT11_N_SUPPORT */
/*
========================================================================
Routine Description:
Verify the support rate for different PHY type
Arguments:
pAd Pointer to our adapter
Return Value:
None
IRQL = PASSIVE_LEVEL
========================================================================
*/
VOID RTMPUpdateMlmeRate(RTMP_ADAPTER *pAd)
{
UCHAR MinimumRate;
UCHAR ProperMlmeRate; /*= RATE_54; */
UCHAR i, j, RateIdx = 12; /* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
BOOLEAN bMatch = FALSE;
switch (pAd->CommonCfg.PhyMode)
{
case ((UCHAR)WMODE_B):
ProperMlmeRate = RATE_11;
MinimumRate = RATE_1;
break;
case ((UCHAR)(WMODE_B | WMODE_G)):
#ifdef DOT11_N_SUPPORT
case ((UCHAR)(WMODE_B | WMODE_G | WMODE_GN | WMODE_A | WMODE_AN)):
case ((UCHAR)(WMODE_B | WMODE_G | WMODE_GN)):
#ifdef DOT11_VHT_AC
case ((UCHAR)(WMODE_B | WMODE_G | WMODE_GN | WMODE_A | WMODE_AN | WMODE_AC)):
#endif /* DOT11_VHT_AC */
#endif /* DOT11_N_SUPPORT */
if ((pAd->MlmeAux.SupRateLen == 4) &&
(pAd->MlmeAux.ExtRateLen == 0))
ProperMlmeRate = RATE_11; /* B only AP */
else
ProperMlmeRate = RATE_24;
if (pAd->MlmeAux.Channel <= 14)
MinimumRate = RATE_1;
else
MinimumRate = RATE_6;
break;
case ((UCHAR)WMODE_A):
#ifdef DOT11_N_SUPPORT
case ((UCHAR)WMODE_GN):
case ((UCHAR)(WMODE_G | WMODE_GN)):
case ((UCHAR)(WMODE_A | WMODE_G | WMODE_GN | WMODE_AN)):
case ((UCHAR)(WMODE_A | WMODE_AN)):
case ((UCHAR)WMODE_AN):
#ifdef DOT11_VHT_AC
case ((UCHAR)(WMODE_A | WMODE_G | WMODE_GN | WMODE_AN | WMODE_AC)):
#endif /* DOT11_VHT_AC */
#endif /* DOT11_N_SUPPORT */
ProperMlmeRate = RATE_24;
MinimumRate = RATE_6;
break;
case ((UCHAR)(WMODE_A | WMODE_B | WMODE_G)):
ProperMlmeRate = RATE_24;
if (pAd->MlmeAux.Channel <= 14)
MinimumRate = RATE_1;
else
MinimumRate = RATE_6;
break;
default:
ProperMlmeRate = RATE_1;
MinimumRate = RATE_1;
break;
}
#ifdef DOT11_VHT_AC
if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B))
{
ProperMlmeRate = RATE_11;
MinimumRate = RATE_1;
}
else
{
if (WMODE_CAP(pAd->CommonCfg.PhyMode, WMODE_B))
{
if ((pAd->MlmeAux.SupRateLen == 4) && (pAd->MlmeAux.ExtRateLen == 0))
ProperMlmeRate = RATE_11; /* B only AP */
else
ProperMlmeRate = RATE_24;
if (pAd->MlmeAux.Channel <= 14)
MinimumRate = RATE_1;
else
MinimumRate = RATE_6;
}
else
{
ProperMlmeRate = RATE_24;
MinimumRate = RATE_6;
}
}
#endif /* DOT11_VHT_AC */
for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
{
for (j = 0; j < RateIdx; j++)
{
if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
{
if (j == ProperMlmeRate)
{
bMatch = TRUE;
break;
}
}
}
if (bMatch)
break;
}
if (bMatch == FALSE)
{
for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
{
for (j = 0; j < RateIdx; j++)
{
if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
{
if (j == ProperMlmeRate)
{
bMatch = TRUE;
break;
}
}
}
if (bMatch)
break;
}
}
if (bMatch == FALSE)
ProperMlmeRate = MinimumRate;
pAd->CommonCfg.MlmeRate = MinimumRate;
pAd->CommonCfg.RtsRate = ProperMlmeRate;
if (pAd->CommonCfg.MlmeRate >= RATE_6)
{
pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
}
else
{
pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
}
DBGPRINT(RT_DEBUG_TRACE, ("%s():=>MlmeTransmit=0x%x\n",
__FUNCTION__, pAd->CommonCfg.MlmeTransmit.word));
}
#endif /* CONFIG_STA_SUPPORT */
CHAR RTMPAvgRssi(RTMP_ADAPTER *pAd, RSSI_SAMPLE *pRssi)
{
CHAR Rssi;
if(pAd->Antenna.field.RxPath == 3)
{
Rssi = (pRssi->AvgRssi[0] + pRssi->AvgRssi[1] + pRssi->AvgRssi[2])/3;
}
else if(pAd->Antenna.field.RxPath == 2)
{
Rssi = (pRssi->AvgRssi[0] + pRssi->AvgRssi[1])>>1;
}
else
{
Rssi = pRssi->AvgRssi[0];
}
return Rssi;
}
CHAR RTMPMaxNoise(RTMP_ADAPTER *pAd, CHAR Noise0, CHAR Noise1, CHAR Noise2)
{
CHAR larger = -127;
if ((pAd->Antenna.field.RxPath == 1) && (Noise0 != 0))
larger = Noise0;
if ((pAd->Antenna.field.RxPath >= 2) && (Noise1 != 0))
larger = max(Noise0, Noise1);
if ((pAd->Antenna.field.RxPath == 3) && (Noise2 != 0))
larger = max(larger, Noise2);
if (larger == -127)
larger = 0;
return larger;
}
CHAR RTMPMaxRssi(RTMP_ADAPTER *pAd, CHAR Rssi0, CHAR Rssi1, CHAR Rssi2)
{
CHAR larger = -127;
if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
{
larger = Rssi0;
}
if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
{
larger = max(Rssi0, Rssi1);
}
if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
{
larger = max(larger, Rssi2);
}
if (larger == -127)
larger = 0;
return larger;
}
CHAR RTMPMinRssi(RTMP_ADAPTER *pAd, CHAR Rssi0, CHAR Rssi1, CHAR Rssi2)
{
CHAR smaller = -127;
if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
smaller = Rssi0;
if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
smaller = min(Rssi0, Rssi1);
if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
smaller = min(smaller, Rssi2);
if (smaller == -127)
smaller = 0;
return smaller;
}
CHAR RTMPMinSnr(RTMP_ADAPTER *pAd, CHAR Snr0, CHAR Snr1)
{
CHAR smaller = Snr0;
if (pAd->Antenna.field.RxPath == 1)
{
smaller = Snr0;
}
if ((pAd->Antenna.field.RxPath >= 2) && (Snr1 != 0))
{
smaller = min(Snr0, Snr1);
}
return smaller;
}
/*
========================================================================
Routine Description:
Periodic evaluate antenna link status
Arguments:
pAd - Adapter pointer
Return Value:
None
========================================================================
*/
VOID AsicEvaluateRxAnt(RTMP_ADAPTER *pAd)
{
#ifdef CONFIG_ATE
if (ATE_ON(pAd))
return;
#endif /* CONFIG_ATE */
#ifdef RTMP_MAC_USB
#ifdef CONFIG_STA_SUPPORT
if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
return;
#endif /* CONFIG_STA_SUPPORT */
#endif /* RTMP_MAC_USB */
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
fRTMP_ADAPTER_HALT_IN_PROGRESS |
fRTMP_ADAPTER_RADIO_OFF |
fRTMP_ADAPTER_NIC_NOT_EXIST |
fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
|| OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
#ifdef RT3090
|| (pAd->bPCIclkOff == TRUE)
#endif /* RT3090 */
#ifdef ANT_DIVERSITY_SUPPORT
|| (pAd->EepromAccess)
#endif /* ANT_DIVERSITY_SUPPORT */
#ifdef RT3593
|| IS_RT3593(pAd)
#endif /* RT3593 */
)
return;
#ifdef RT3290
if (IS_RT3290(pAd) && (pAd->RalinkCounters.OneSecTransmittedByteCount >= 500))
return;
#endif /* RT3290 */
#ifdef MT_MAC
// TODO: shiang-7603
if (pAd->chipCap.hif_type == HIF_MT)
return;
#endif /* MT_MAC */
#ifdef ANT_DIVERSITY_SUPPORT
if ((pAd->CommonCfg.bSWRxAntDiversity)
&& (pAd->CommonCfg.RxAntDiversityCfg == ANT_SW_DIVERSITY_ENABLE))
{
/* two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove*/
/* one is antenna diversity:there is only one antenna can rx and tx*/
/* the other is failed antenna remove:two physical antenna can rx and tx*/
DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
pAd->RxAnt.EvaluatePeriod = 1; /* 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt*/
pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
/* a one-shot timer to end the evalution*/
/* dynamic adjust antenna evaluation period according to the traffic*/
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) ||
OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED))
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 5000);
else
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
else
#endif /* CONFIG_STA_SUPPORT */
RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
}
else
#endif /* ANT_DIVERSITY_SUPPORT */
{
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
/* if (pAd->CommonCfg.bRxAntDiversity == ANT_DIVERSITY_DISABLE)*/
/* for SmartBit 64-byte stream test */
if (pAd->MacTab.Size > 0)
APAsicEvaluateRxAnt(pAd);
return;
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("AsicEvaluateRxAnt : RealRxPath=%d \n", pAd->Mlme.RealRxPath));
#endif /* RELEASE_EXCLUDE */
if (pAd->StaCfg.PwrMgmt.Psm == PWR_SAVE)
return;
bbp_set_rxpath(pAd, pAd->Antenna.field.RxPath);
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
#ifdef MESH_SUPPORT
|| MESH_ON(pAd)
#endif /* MESH_SUPPORT */
#ifdef P2P_SUPPORT
|| P2P_GO_ON(pAd) || P2P_CLI_ON(pAd)
#endif /* P2P_SUPPORT */
)
{
ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
pAd->RalinkCounters.OneSecTxRetryOkCount +
pAd->RalinkCounters.OneSecTxFailCount;
/* dynamic adjust antenna evaluation period according to the traffic*/
if (TxTotalCnt > 50)
{
RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
pAd->Mlme.bLowThroughput = FALSE;
}
else
{
RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
pAd->Mlme.bLowThroughput = TRUE;
}
}
}
#endif /* CONFIG_STA_SUPPORT */
}
}
/*
========================================================================
Routine Description:
After evaluation, check antenna link status
Arguments:
pAd - Adapter pointer
Return Value:
None
========================================================================
*/
VOID AsicRxAntEvalTimeout(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
#ifdef CONFIG_STA_SUPPORT
CHAR larger = -127, rssi0, rssi1, rssi2;
#endif /* CONFIG_STA_SUPPORT */
#ifdef ANT_DIVERSITY_SUPPORT
BOOLEAN bSwapAnt = FALSE;
#ifdef CONFIG_AP_SUPPORT
SHORT realrssi, last_rssi = pAd->RxAnt.Pair1LastAvgRssi;
ULONG recv = pAd->RxAnt.RcvPktNum[pAd->RxAnt.Pair1SecondaryRxAnt];
#endif /* CONFIG_AP_SUPPORT */
#endif /* ANT_DIVERSITY_SUPPORT */
#ifdef CONFIG_ATE
if (ATE_ON(pAd))
return;
#endif /* CONFIG_ATE */
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
fRTMP_ADAPTER_HALT_IN_PROGRESS |
fRTMP_ADAPTER_RADIO_OFF |
fRTMP_ADAPTER_NIC_NOT_EXIST)
|| OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
#ifdef RT3090
|| (pAd->bPCIclkOff == TRUE)
#endif /* RT3090 */
#ifdef ANT_DIVERSITY_SUPPORT
|| (pAd->EepromAccess)
#endif /* ANT_DIVERSITY_SUPPORT */
)
return;
#ifdef ANT_DIVERSITY_SUPPORT
if ((pAd->CommonCfg.bSWRxAntDiversity)
&& (pAd->CommonCfg.RxAntDiversityCfg == ANT_SW_DIVERSITY_ENABLE))
{
#ifdef CONFIG_AP_SUPPORT
#ifdef RELEASE_EXCLUDE
/* For the corner case, AP can't set the threshold too higher.
* In test environment, the Avg. RSSI only get 1 or 2dBm as AP can take care the bad RSSI STA.
*/
#endif /* RELEASE_EXCLUDE */
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
APAsicAntennaAvg(pAd, pAd->RxAnt.Pair1SecondaryRxAnt, &realrssi);
if ((recv != 0) && (realrssi >= (pAd->RxAnt.Pair1LastAvgRssi + 1)))
bSwapAnt = TRUE;
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
bSwapAnt = TRUE;
#endif /* CONFIG_STA_SUPPORT */
if (bSwapAnt == TRUE)
{
UCHAR temp;
/* select PrimaryRxAntPair*/
/* Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.*/
/* Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt*/
temp = pAd->RxAnt.Pair1PrimaryRxAnt;
pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
pAd->RxAnt.Pair1SecondaryRxAnt = temp;
#ifdef CONFIG_AP_SUPPORT
pAd->RxAnt.Pair1LastAvgRssi = realrssi;
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
#endif /* CONFIG_STA_SUPPORT */
/* pAd->RxAnt.EvaluateStableCnt = 0;*/
}
else
{
/* if the evaluated antenna is not better than original, switch back to original antenna*/
AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
pAd->RxAnt.EvaluateStableCnt ++;
}
pAd->RxAnt.EvaluatePeriod = 0; /* 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt*/
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
pAd->RxAnt.Pair1PrimaryRxAnt, last_rssi, realrssi, recv));
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
#endif /* CONFIG_STA_SUPPORT */
}
else
#endif /* ANT_DIVERSITY_SUPPORT */
{
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
/* if (pAd->CommonCfg.bRxAntDiversity == ANT_DIVERSITY_DISABLE)*/
APAsicRxAntEvalTimeout(pAd);
return;
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
if (pAd->StaCfg.PwrMgmt.Psm == PWR_SAVE)
return;
/* if the traffic is low, use average rssi as the criteria*/
if (pAd->Mlme.bLowThroughput == TRUE)
{
rssi0 = pAd->StaCfg.RssiSample.LastRssi[0];
rssi1 = pAd->StaCfg.RssiSample.LastRssi[1];
rssi2 = pAd->StaCfg.RssiSample.LastRssi[2];
}
else
{
rssi0 = pAd->StaCfg.RssiSample.AvgRssi[0];
rssi1 = pAd->StaCfg.RssiSample.AvgRssi[1];
rssi2 = pAd->StaCfg.RssiSample.AvgRssi[2];
}
if(pAd->Antenna.field.RxPath == 3)
{
larger = max(rssi0, rssi1);
#ifdef DOT11N_SS3_SUPPORT
if (pAd->CommonCfg.TxStream >= 3)
{
pAd->Mlme.RealRxPath = 3;
}
else
#endif /* DOT11N_SS3_SUPPORT */
if (larger > (rssi2 + 20))
pAd->Mlme.RealRxPath = 2;
else
pAd->Mlme.RealRxPath = 3;
}
else if(pAd->Antenna.field.RxPath == 2)
{
if (rssi0 > (rssi1 + 20))
pAd->Mlme.RealRxPath = 1;
else
pAd->Mlme.RealRxPath = 2;
}
bbp_set_rxpath(pAd, pAd->Mlme.RealRxPath);
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("AsicRxAntEvalTimeout : RealRxPath=%d, AvgRssi=%d, %d, %d \n",
pAd->Mlme.RealRxPath, rssi0, rssi1, rssi2));
#endif /* RELEASE_EXCLUDE */
}
#endif /* CONFIG_STA_SUPPORT */
}
}
VOID APSDPeriodicExec(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
!OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED))
return;
pAd->CommonCfg.TriggerTimerCount++;
/* Driver should not send trigger frame, it should be send by application layer*/
/*
if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
&& (pAd->CommonCfg.bNeedSendTriggerFrame ||
(((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
{
DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
pAd->CommonCfg.TriggerTimerCount = 0;
pAd->CommonCfg.bInServicePeriod = TRUE;
}*/
}
/*
========================================================================
Routine Description:
check if this entry need to switch rate automatically
Arguments:
pAd
pEntry
Return Value:
TURE
FALSE
========================================================================
*/
BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
IN RTMP_ADAPTER *pAd,
IN MAC_TABLE_ENTRY *pEntry)
{
BOOLEAN result = TRUE;
if ((!pEntry) || (!(pEntry->wdev))) {
#if 1
DBGPRINT(RT_DEBUG_ERROR, ("%s(): entry or wdev is NULL!\n",
__FUNCTION__));
#else
/* If pEntry is null, pEntry->wdev would cause system crash */
DBGPRINT(RT_DEBUG_ERROR, ("%s(): entry(%p) or wdev(%p) is NULL!\n",
__FUNCTION__, pEntry, pEntry->wdev));
#endif
return FALSE;
}
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd) {
result = pEntry->wdev->bAutoTxRateSwitch;
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
/* only associated STA counts*/
#ifdef P2P_SUPPORT
if (pEntry && IS_P2P_GO_ENTRY(pEntry))
result = pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bAutoTxRateSwitch;
else if (pEntry && IS_ENTRY_APCLI(pEntry))
result = pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].wdev.bAutoTxRateSwitch;
else
#endif /* P2P_SUPPORT */
if ((pEntry && IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC))
#ifdef QOS_DLS_SUPPORT
|| (pEntry && IS_ENTRY_DLS(pEntry))
#endif /* QOS_DLS_SUPPORT */
#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT)
|| (pEntry && IS_ENTRY_TDLS(pEntry))
#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */
)
{
result = pAd->StaCfg.wdev.bAutoTxRateSwitch;
}
else
result = FALSE;
}
#endif /* CONFIG_STA_SUPPORT */
#ifdef MESH_SUPPORT
if (IS_ENTRY_MESH(pEntry))
result = pEntry->wdev->bAutoTxRateSwitch;
#endif /* MESH_SUPPORT */
#ifdef TXBF_SUPPORT
if (result == FALSE)
{
//Force MCS will be fixed
if (pAd->chipCap.FlgHwTxBfCap)
{
eTxBFProbing(pAd, pEntry);
}
}
#endif /* TXBF_SUPPORT */
return result;
}
BOOLEAN RTMPAutoRateSwitchCheck(RTMP_ADAPTER *pAd)
{
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
INT apidx = 0;
for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
{
if (pAd->ApCfg.MBSSID[apidx].wdev.bAutoTxRateSwitch)
return TRUE;
}
#ifdef WDS_SUPPORT
for (apidx = 0; apidx < MAX_WDS_ENTRY; apidx++)
{
if (pAd->WdsTab.WdsEntry[apidx].wdev.bAutoTxRateSwitch)
return TRUE;
}
#endif /* WDS_SUPPORT */
#ifdef APCLI_SUPPORT
for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++)
{
if (pAd->ApCfg.ApCliTab[apidx].wdev.bAutoTxRateSwitch)
return TRUE;
}
#endif /* APCLI_SUPPORT */
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
if (pAd->StaCfg.wdev.bAutoTxRateSwitch)
return TRUE;
}
#endif /* CONFIG_STA_SUPPORT */
return FALSE;
}
/*
========================================================================
Routine Description:
check if this entry need to fix tx legacy rate
Arguments:
pAd
pEntry
Return Value:
TURE
FALSE
========================================================================
*/
UCHAR RTMPStaFixedTxMode(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry)
{
UCHAR tx_mode = FIXED_TXMODE_HT;
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
if (pEntry)
{
if (IS_ENTRY_CLIENT(pEntry))
tx_mode = (UCHAR)pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.DesiredTransmitSetting.field.FixedTxMode;
#ifdef WDS_SUPPORT
else if (IS_ENTRY_WDS(pEntry))
tx_mode = (UCHAR)pAd->WdsTab.WdsEntry[pEntry->func_tb_idx].wdev.DesiredTransmitSetting.field.FixedTxMode;
#endif /* WDS_SUPPORT */
#ifdef APCLI_SUPPORT
else if (IS_ENTRY_APCLI(pEntry))
tx_mode = (UCHAR)pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].wdev.DesiredTransmitSetting.field.FixedTxMode;
#endif /* APCLI_SUPPORT */
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
#ifdef P2P_SUPPORT
if (IS_P2P_GO_ENTRY(pEntry))
tx_mode = (UCHAR)pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.DesiredTransmitSetting.field.FixedTxMode;
else if (IS_ENTRY_APCLI(pEntry))
tx_mode = (UCHAR)pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].wdev.DesiredTransmitSetting.field.FixedTxMode;
else
#endif /* P2P_SUPPORT */
tx_mode = (UCHAR)pAd->StaCfg.wdev.DesiredTransmitSetting.field.FixedTxMode;
}
#endif /* CONFIG_STA_SUPPORT */
return tx_mode;
}
/*
========================================================================
Routine Description:
Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
Arguments:
pAd
pEntry
Return Value:
TURE
FALSE
========================================================================
*/
VOID RTMPUpdateLegacyTxSetting(UCHAR fixed_tx_mode, MAC_TABLE_ENTRY *pEntry)
{
HTTRANSMIT_SETTING TransmitSetting;
if ((fixed_tx_mode != FIXED_TXMODE_CCK) &&
(fixed_tx_mode != FIXED_TXMODE_OFDM)
#ifdef DOT11_VHT_AC
&& (fixed_tx_mode != FIXED_TXMODE_VHT)
#endif /* DOT11_VHT_AC */
)
return;
TransmitSetting.word = 0;
TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
#ifdef DOT11_VHT_AC
if (fixed_tx_mode == FIXED_TXMODE_VHT)
{
TransmitSetting.field.MODE = MODE_VHT;
TransmitSetting.field.BW = pEntry->MaxHTPhyMode.field.BW;
/* CCK mode allow MCS 0~3*/
if (TransmitSetting.field.MCS > ((1 << 4) + MCS_7))
TransmitSetting.field.MCS = ((1 << 4) + MCS_7);
}
else
#endif /* DOT11_VHT_AC */
if (fixed_tx_mode == FIXED_TXMODE_CCK)
{
TransmitSetting.field.MODE = MODE_CCK;
/* CCK mode allow MCS 0~3*/
if (TransmitSetting.field.MCS > MCS_3)
TransmitSetting.field.MCS = MCS_3;
}
else
{
TransmitSetting.field.MODE = MODE_OFDM;
/* OFDM mode allow MCS 0~7*/
if (TransmitSetting.field.MCS > MCS_7)
TransmitSetting.field.MCS = MCS_7;
}
if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
{
pEntry->HTPhyMode.word = TransmitSetting.word;
DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
pEntry->wcid, get_phymode_str(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s : the fixed TxMode is invalid \n", __FUNCTION__));
}
}
#ifdef CONFIG_STA_SUPPORT
/*
==========================================================================
Description:
dynamic tune BBP R66 to find a balance between sensibility and
noise isolation
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID AsicStaBbpTuning(RTMP_ADAPTER *pAd)
{
UCHAR OrigR66Value = 0, R66;/*, R66UpperBound = 0x30, R66LowerBound = 0x30;*/
CHAR Rssi;
#ifdef RT2883
UCHAR byteValue = 0;
#endif /* RT2883 */
// TODO: shiang-7603
if (pAd->chipCap.hif_type == HIF_MT) {
return;
}
/* 2860C did not support Fase CCA, therefore can't tune*/
if (pAd->MACVersion == 0x28600100)
return;
/* work as a STA*/
if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) /* no R66 tuning when SCANNING*/
return;
if ((pAd->OpMode == OPMODE_STA)
&& (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
#ifdef MESH_SUPPORT
|| MESH_ON(pAd)
#endif /* MESH_SUPPORT */
)
&& !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
#ifdef RTMP_MAC_PCI
&& (pAd->bPCIclkOff == FALSE)
#endif /* RTMP_MAC_PCI */
)
{
bbp_get_agc(pAd, &OrigR66Value, RX_CHAIN_0);
R66 = OrigR66Value;
if (pAd->Antenna.field.RxPath > 1)
Rssi = (pAd->StaCfg.RssiSample.AvgRssi[0] + pAd->StaCfg.RssiSample.AvgRssi[1]) >> 1;
else
Rssi = pAd->StaCfg.RssiSample.AvgRssi[0];
RTMP_CHIP_ASIC_AGC_ADJUST(pAd, Rssi, R66);
// TODO: shiang,I didn't find AsicAGCAdjust for RT30xx, so I move following code from upper #if case.
#ifdef RT3290
#ifdef RELEASE_EXCLUDE
//Customer-Samsung: <1m distance throughput issue
#endif /* RELEASE_EXCLUDE */
// TODO: shiang, what's the BbpWriteLatch[ ] ?????
if (IS_RT3290(pAd))
{
if (Rssi >= -36)
{
if (pAd->BbpWriteLatch[BBP_R77] != 0x27)
{
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x52);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R77, 0x27);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1C);
}
}
else
{
if (pAd->BbpWriteLatch[BBP_R77] != 0x58)
{
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R77, 0x58);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x12);
}
}
}
#endif /* RT3290 */
#ifdef RELEASE_EXCLUDE
if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
{
DBGPRINT(RT_DEBUG_INFO,
("RSSI=%d, CCA=%d, BW=%d, LNA_GAIN=0x%x, fixed R66 at 0x%x\n",
Rssi, pAd->RalinkCounters.OneSecFalseCCACnt,
pAd->CommonCfg.BBPCurrentBW, pAd->hw_cfg.lan_gain, R66));
}
#endif /* RELEASE_EXCLUDE */
}
}
#endif /* CONFIG_STA_SUPPORT */
VOID RTMPSetAGCInitValue(RTMP_ADAPTER *pAd, UCHAR BandWidth)
{
if (pAd->chipOps.ChipAGCInit != NULL)
pAd->chipOps.ChipAGCInit(pAd, BandWidth);
}
/*
========================================================================
Routine Description:
Check if the channel has the property.
Arguments:
pAd - WLAN control block pointer
ChanNum - channel number
Property - channel property, CHANNEL_PASSIVE_SCAN, etc.
Return Value:
TRUE - YES
FALSE - NO
Note:
========================================================================
*/
BOOLEAN CHAN_PropertyCheck(RTMP_ADAPTER *pAd, UINT32 ChanNum, UCHAR Property)
{
UINT32 IdChan;
/* look for all registered channels */
for(IdChan=0; IdChan<pAd->ChannelListNum; IdChan++)
{
if (pAd->ChannelList[IdChan].Channel == ChanNum)
{
if ((pAd->ChannelList[IdChan].Flags & Property) == Property)
return TRUE;
break;
}
}
return FALSE;
}
#ifdef P2P_CHANNEL_LIST_SEPARATE
BOOLEAN P2P_CHAN_PropertyCheck(
IN PRTMP_ADAPTER pAd,
IN UINT32 ChanNum,
IN UCHAR Property)
{
UINT32 IdChan;
PCFG80211_CTRL pCfg80211_Ctrl = &pAd->cfg80211_ctrl;
/* look for all registered channels */
for(IdChan = 0; IdChan < pCfg80211_Ctrl->ChannelListNum; IdChan++)
{
if (pCfg80211_Ctrl->ChannelList[IdChan].Channel == ChanNum)
{
if ((pCfg80211_Ctrl->ChannelList[IdChan].Flags & Property) == Property)
return TRUE;
break;
}
}
return FALSE;
}
#endif /* P2P_CHANNEL_LIST_SEPARATE */
NDIS_STATUS RtmpEnqueueTokenFrame(
IN RTMP_ADAPTER *pAd,
IN UCHAR *pAddr,
IN UCHAR TxRate,
IN UCHAR AID,
IN UCHAR apidx,
IN UCHAR OldUP)
{
NDIS_STATUS NState = NDIS_STATUS_FAILURE;
HEADER_802_11 *pNullFr;
UCHAR *pFrame;
UINT frm_len;
NState = MlmeAllocateMemory(pAd, (UCHAR **)&pFrame);
if (NState == NDIS_STATUS_SUCCESS)
{
UCHAR *qos_p;
pNullFr = (PHEADER_802_11) pFrame;
frm_len = sizeof(HEADER_802_11);
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd) {
MgtMacHeaderInit(pAd, pNullFr, SUBTYPE_DATA_NULL, 0, pAddr,
pAd->ApCfg.MBSSID[apidx].wdev.if_addr,
pAd->ApCfg.MBSSID[apidx].wdev.bssid);
pNullFr->FC.ToDs = 0;
pNullFr->FC.FrDs = 1;
pNullFr->Frag = 0x0f;
}
#endif /* CONFIG_AP_SUPPORT */
pNullFr->FC.Type = FC_TYPE_DATA;
qos_p = ((UCHAR *)pNullFr) + frm_len;
pNullFr->FC.SubType = SUBTYPE_QOS_NULL;
/* copy QOS control bytes */
qos_p[0] = OldUP;
qos_p[1] = PS_RETRIEVE_TOKEN;
frm_len += 2;
/* since TxRate may change, we have to change Duration each time */
pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, frm_len);
NState = MiniportMMRequest(pAd, OldUP | MGMT_USE_QUEUE_FLAG, (PUCHAR)pNullFr, frm_len);
MlmeFreeMemory(pAd, pFrame);
}
return NState;
}
#if defined(RT5370) || defined(RT5372) || defined(RT5390) || defined(RT5392)
VOID AsicCheckForHwRecovery(RTMP_ADAPTER *pAd)
{
if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
{
#ifdef RELEASE_EXCLUDE
/* Bug 1. BBP dead. Need to Hard-Reset BBP */
#endif /* RELEASE_EXCLUDE */
if (pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount)
{
/* If ReceiveByteCount doesn't change, increase SameRxByteCount by 1 */
pAd->SameRxByteCount++;
}
else
{
pAd->SameRxByteCount = 0;
pAd->BbpResetCount = 0;
}
#ifdef RELEASE_EXCLUDE
/*
If SameRxByteCount keeps happening :
for 3 second in infra mode
for 5 seconds in idle mode
for 1 second in P2PGO
*/
#endif /* RELEASE_EXCLUDE */
if (
#ifdef CONFIG_STA_SUPPORT
((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 3)) ||
((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 5))
#endif /* CONFIG_STA_SUPPORT */
#ifdef P2P_SUPPORT
||((P2P_GO_ON(pAd)) && (pAd->SameRxByteCount > 1))
#else
#ifdef CONFIG_AP_SUPPORT
(pAd->SameRxByteCount > 0)
#endif /* CONFIG_AP_SUPPORT */
#endif /* P2P_SUPPORT */
)
{
DBGPRINT(RT_DEBUG_TRACE, ("AsicCheckForHwRecovery!!\n"));
#ifdef CONFIG_STA_SUPPORT
if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
|| (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
|| RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
AsicForceWakeup(pAd, DOT11POWERSAVE);
#endif /* CONFIG_STA_SUPPORT */
#ifdef RELEASE_EXCLUDE
/*
Patch Scan no AP issue.
Firmware will write RF_R08(xtal_vdd_select) to LDOADC.
This is HW issue.
New RT3572(0x35720223) should not have this issue.
*/
#endif /* RELEASE_EXCLUDE */
if (IS_RT5392(pAd))
{
UCHAR RfValue = 0;
RT30xxReadRFRegister(pAd, RF_R42, &RfValue);
RfValue = (RfValue | 0xC0); /* rx_ctb_en, rx_mix2_en */
RT30xxWriteRFRegister(pAd, RF_R42, RfValue);
}
if(pAd->BbpResetFlag == 0)
{
AsicResetBBPAgent(pAd);
pAd->BbpResetFlag = 1;
}
pAd->SameRxByteCount = 0;
pAd->BbpResetCount++;
}
}
/* Update lastReceiveByteCount */
pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
}
#endif /* defined(RT5370) || defined(RT5372) || defined(RT5390) || defined(RT5392) || defined(RT5592) */