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

2064 lines
65 KiB
C

/****************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
* (c) Copyright 2002, 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:
sync.c
Abstract:
Synchronization state machine related services
Revision History:
Who When What
-------- ---------- ----------------------------------------------
John Chang 08-04-2003 created for 11g soft-AP
*/
#include "rt_config.h"
#ifdef MESH_SUPPORT
#include "mesh_sanity.h"
#endif /* MESH_SUPPORT */
#define OBSS_BEACON_RSSI_THRESHOLD (-85)
/*
==========================================================================
Description:
Process the received ProbeRequest from clients
Parameters:
Elem - msg containing the ProbeReq frame
==========================================================================
*/
VOID APPeerProbeReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
PEER_PROBE_REQ_PARAM ProbeReqParam;
HEADER_802_11 ProbeRspHdr;
NDIS_STATUS NStatus;
PUCHAR pOutBuffer = NULL;
ULONG FrameLen = 0, TmpLen;
LARGE_INTEGER FakeTimestamp;
UCHAR DsLen = 1;
UCHAR ErpIeLen = 1;
UCHAR apidx = 0, PhyMode, SupRateLen;
UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2;
BSS_STRUCT *mbss;
struct wifi_dev *wdev;
#ifdef WSC_AP_SUPPORT
UCHAR Addr3[MAC_ADDR_LEN];
PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg;
COPY_MAC_ADDR(Addr3, pFrame->Hdr.Addr3);
#endif /* WSC_AP_SUPPORT */
#ifdef WDS_SUPPORT
/* if in bridge mode, no need to reply probe req. */
if (pAd->WdsTab.Mode == WDS_BRIDGE_MODE)
return;
#endif /* WDS_SUPPORT */
#ifdef P2P_SUPPORT
/* When enable P2P scan, there driver alway sent probe request.
But when user enter main page, LG request not sent probe response. */
if ( pAd->P2pCfg.bSentProbeRSP != TRUE )
return;
#endif /* P2P_SUPPORT */
if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, &ProbeReqParam) == FALSE) {
DBGPRINT(RT_DEBUG_OFF, ("%s():shiang! PeerProbeReqSanity failed!\n", __FUNCTION__));
return;
}
#ifdef NINTENDO_AP
if ((NdisEqualMemory(NINTENDO_SSID_NAME, ProbeReqParam.Ssid, NINTENDO_SSID_NAME_LN)) && (0 == pAd->bNintendoCapable)) {
DBGPRINT(RT_DEBUG_TRACE, ("iwpriv ra0 nintendocapable 0 (Not Enable)\n"));
}
if (pAd->bNintendoCapable)
return;
#endif /* NINTENDO_AP */
for(apidx=0; apidx<pAd->ApCfg.BssidNum; apidx++)
{
mbss = &pAd->ApCfg.MBSSID[apidx];
wdev = &mbss->wdev;
RSNIe = IE_WPA;
if ((wdev->if_dev == NULL) || ((wdev->if_dev != NULL) &&
!(RTMP_OS_NETDEV_STATE_RUNNING(wdev->if_dev))))
{
/* the interface is down, so we can not send probe response */
continue;
}
PhyMode = wdev->PhyMode;
if ( ((((ProbeReqParam.SsidLen == 0) && (!mbss->bHideSsid)) ||
((ProbeReqParam.SsidLen == mbss->SsidLen) && NdisEqualMemory(ProbeReqParam.Ssid, mbss->Ssid, (ULONG) ProbeReqParam.SsidLen)))
#ifdef CONFIG_HOTSPOT
&& ProbeReqforHSAP(pAd, apidx, &ProbeReqParam)
#endif
)
#ifdef WSC_AP_SUPPORT
/* buffalo WPS testbed STA send ProbrRequest ssid length = 32 and ssid are not AP , but DA are AP. for WPS test send ProbeResponse */
|| ((ProbeReqParam.SsidLen == 32) && MAC_ADDR_EQUAL(Addr3, wdev->bssid) && (mbss->bHideSsid == 0))
#endif /* WSC_AP_SUPPORT */
#ifdef P2P_SUPPORT
|| (NdisEqualMemory(ProbeReqParam.Ssid, &WILDP2PSSID[0], WILDP2PSSIDLEN))
#endif /* P2P_SUPPORT */
)
{
;
}
else {
continue; /* check next BSS */
}
#ifdef NINTENDO_AP
if (NdisEqualMemory(NINTENDO_SSID_NAME, ProbeReqParam.Ssid, NINTENDO_SSID_NAME_LN) &&
(1 == pAd->bNintendoCapable) &&
(CheckNINTENDO_TABLE(pAd, ProbeReqParam.Ssid, ProbeReqParam.SsidLen, ProbeReqParam.Addr2))
)
return;
#endif /* NINTENDO_AP */
/* allocate and send out ProbeRsp frame */
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if (NStatus != NDIS_STATUS_SUCCESS)
return;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("SYNC - Send PROBE_RSP to %02x:%02x:%02x:%02x:%02x:%02x...\n",
PRINT_MAC(ProbeReqParam.Addr2)));
#endif /* RELEASE_EXCLUDE */
MgtMacHeaderInit(pAd, &ProbeRspHdr, SUBTYPE_PROBE_RSP, 0, ProbeReqParam.Addr2,
wdev->if_addr, wdev->bssid);
if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK))
RSNIe = IE_WPA;
else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)
#ifdef WPA3_SUPPORT
|| (wdev->AuthMode == Ndis802_11AuthModeWPA3SAE)
#endif
)
RSNIe = IE_WPA2;
#ifdef WAPI_SUPPORT
else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK))
RSNIe = IE_WAPI;
#endif /* WAPI_SUPPORT */
#ifdef P2P_SUPPORT
if (P2P_GO_ON(pAd))
{
UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES];
UCHAR SupRateIe = IE_SUPP_RATES;
UCHAR SupRateLen = 0;
UCHAR Channel = pAd->CommonCfg.Channel;
if (IS_P2P_LISTEN(pAd))
Channel = pAd->P2pCfg.ListenChannel;
SupRate[0] = 0x8C; /* 6 mbps, in units of 0.5 Mbps, basic rate */
SupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps */
SupRate[2] = 0x98; /* 12 mbps, in units of 0.5 Mbps, basic rate */
SupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps */
SupRate[4] = 0xb0; /* 24 mbps, in units of 0.5 Mbps, basic rate */
SupRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps */
SupRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps */
SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps */
SupRateLen = 8;
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &ProbeRspHdr,
TIMESTAMP_LEN, &FakeTimestamp,
2, &pAd->CommonCfg.BeaconPeriod,
2, &mbss->CapabilityInfo,
1, &SsidIe,
1, &mbss->SsidLen,
mbss->SsidLen, mbss->Ssid,
1, &SupRateIe,
1, &SupRateLen,
SupRateLen, &SupRate,
1, &DsIe,
1, &DsLen,
1, &Channel,
END_OF_ARGS);
}
else
#endif /* P2P_SUPPORT */
{
SupRateLen = pAd->CommonCfg.SupRateLen;
if (PhyMode == WMODE_B)
SupRateLen = 4;
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &ProbeRspHdr,
TIMESTAMP_LEN, &FakeTimestamp,
2, &pAd->CommonCfg.BeaconPeriod,
2, &mbss->CapabilityInfo,
1, &SsidIe,
1, &mbss->SsidLen,
mbss->SsidLen, mbss->Ssid,
1, &SupRateIe,
1, &SupRateLen,
SupRateLen, pAd->CommonCfg.SupRate,
1, &DsIe,
1, &DsLen,
1, &pAd->CommonCfg.Channel,
END_OF_ARGS);
}
if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B))
{
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
1, &ErpIe,
1, &ErpIeLen,
1, &pAd->ApCfg.ErpIeContent,
1, &ExtRateIe,
1, &pAd->CommonCfg.ExtRateLen,
pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate,
END_OF_ARGS);
FrameLen += TmpLen;
}
#ifdef A_BAND_SUPPORT
/* add Channel switch announcement IE */
if ((pAd->CommonCfg.Channel > 14)
&& (pAd->CommonCfg.bIEEE80211H == 1)
&& (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE))
{
UCHAR CSAIe=IE_CHANNEL_SWITCH_ANNOUNCEMENT;
UCHAR CSALen=3;
UCHAR CSAMode=1;
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
1, &CSAIe,
1, &CSALen,
1, &CSAMode,
1, &pAd->CommonCfg.Channel,
1, &pAd->Dot11_H.CSCount,
END_OF_ARGS);
FrameLen += TmpLen;
}
#endif /* A_BAND_SUPPORT */
#ifdef DOT11_N_SUPPORT
if (WMODE_CAP_N(PhyMode) &&
(wdev->DesiredHtPhyInfo.bHtEnable))
{
ULONG TmpLen;
UCHAR HtLen, AddHtLen/*, NewExtLen*/;
HT_CAPABILITY_IE HtCapabilityTmp;
#ifdef RT_BIG_ENDIAN
ADD_HT_INFO_IE addHTInfoTmp;
#endif
/* YF@20120419: Fix IOT Issue with Atheros STA on Windows 7 When IEEE80211H flag turn on. */
#if 0
#ifdef A_BAND_SUPPORT
if (pAd->CommonCfg.bExtChannelSwitchAnnouncement && (pAd->CommonCfg.Channel > 14))
{
HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe;
build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe);
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE), &HtExtChannelSwitchIe,
END_OF_ARGS);
FrameLen += TmpLen;
}
#endif /* A_BAND_SUPPORT */
#endif
HtLen = sizeof(pAd->CommonCfg.HtCapability);
AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo);
//NewExtLen = 1;
/*New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame */
#ifndef RT_BIG_ENDIAN
NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
HtCapabilityTmp.HtCapInfo.ChannelWidth = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1, &HtCapIe,
1, &HtLen,
sizeof(HT_CAPABILITY_IE), &HtCapabilityTmp,
1, &AddHtInfoIe,
1, &AddHtLen,
sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo,
END_OF_ARGS);
#else
NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
HtCapabilityTmp.HtCapInfo.ChannelWidth = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
*(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
#ifdef UNALIGNMENT_SUPPORT
{
EXT_HT_CAP_INFO extHtCapInfo;
NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO));
*(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo));
NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO));
}
#else
*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
#endif /* UNALIGNMENT_SUPPORT */
NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen);
*(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2));
*(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3));
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1, &HtCapIe,
1, &HtLen,
HtLen, &HtCapabilityTmp,
1, &AddHtInfoIe,
1, &AddHtLen,
AddHtLen, &addHTInfoTmp,
END_OF_ARGS);
#endif
FrameLen += TmpLen;
}
#endif /* DOT11_N_SUPPORT */
/* Append RSN_IE when WPA OR WPAPSK, */
if (wdev->AuthMode < Ndis802_11AuthModeWPA)
; /* enough information */
else if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
(wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
{
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
1, &RSNIe,
1, &mbss->RSNIE_Len[0],
mbss->RSNIE_Len[0], mbss->RSN_IE[0],
1, &RSNIe2,
1, &mbss->RSNIE_Len[1],
mbss->RSNIE_Len[1], mbss->RSN_IE[1],
END_OF_ARGS);
FrameLen += TmpLen;
}
else
{
#ifdef CONFIG_HOTSPOT_R2
PHOTSPOT_CTRL pHSCtrl = &mbss->HotSpotCtrl;
extern UCHAR OSEN_IE[];
extern UCHAR OSEN_IELEN;
if ((pHSCtrl->HotSpotEnable == 0) && (pHSCtrl->bASANEnable == 1) && (wdev->AuthMode == Ndis802_11AuthModeWPA2))
{
RSNIe = IE_WPA;
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
1, &RSNIe,
1, &OSEN_IELEN,
OSEN_IELEN, OSEN_IE,
END_OF_ARGS);
}
else
#endif
{
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
1, &RSNIe,
1, &mbss->RSNIE_Len[0],
mbss->RSNIE_Len[0], mbss->RSN_IE[0],
END_OF_ARGS);
}
FrameLen += TmpLen;
}
#ifdef CONFIG_HOTSPOT
if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HotSpotEnable)
{
ULONG TmpLen;
/* Hotspot 2.0 Indication */
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HSIndicationIELen,
pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HSIndicationIE, END_OF_ARGS);
FrameLen += TmpLen;
/* Interworking element */
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.InterWorkingIELen,
pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.InterWorkingIE, END_OF_ARGS);
FrameLen += TmpLen;
/* Advertisement Protocol element */
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.AdvertisementProtoIELen,
pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.AdvertisementProtoIE, END_OF_ARGS);
FrameLen += TmpLen;
/* Roaming Consortium element */
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.RoamingConsortiumIELen,
pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.RoamingConsortiumIE, END_OF_ARGS);
FrameLen += TmpLen;
/* P2P element */
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.P2PIELen,
pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.P2PIE, END_OF_ARGS);
FrameLen += TmpLen;
}
#endif
/* Extended Capabilities IE */
{
ULONG TmpLen;
EXT_CAP_INFO_ELEMENT extCapInfo;
UCHAR extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT);
NdisZeroMemory(&extCapInfo, extInfoLen);
#ifdef DOT11_N_SUPPORT
#ifdef DOT11N_DRAFT3
/* P802.11n_D1.10, HT Information Exchange Support */
if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.Channel <= 14) &&
(pAd->ApCfg.MBSSID[apidx].wdev.DesiredHtPhyInfo.bHtEnable) &&
(pAd->CommonCfg.bBssCoexEnable == TRUE))
{
extCapInfo.BssCoexistMgmtSupport = 1;
}
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
#ifdef CONFIG_DOT11V_WNM
if (pAd->ApCfg.MBSSID[apidx].WNMCtrl.ProxyARPEnable)
extCapInfo.proxy_arp = 1;
#ifdef CONFIG_HOTSPOT_R2
if (pAd->ApCfg.MBSSID[apidx].WNMCtrl.WNMNotifyEnable)
extCapInfo.wnm_notification= 1;
if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QosMapEnable)
extCapInfo.qosmap= 1;
#endif
#endif
#ifdef CONFIG_HOTSPOT
if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HotSpotEnable)
extCapInfo.interworking = 1;
#endif
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
1, &ExtCapIe,
1, &extInfoLen,
extInfoLen, &extCapInfo,
END_OF_ARGS);
FrameLen += TmpLen;
}
#ifdef AP_QLOAD_SUPPORT
if (pAd->phy_ctrl.FlgQloadEnable != 0)
{
#ifdef CONFIG_HOTSPOT_R2
if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QLoadTestEnable == 1)
FrameLen += QBSS_LoadElementAppend_HSTEST(pAd, pOutBuffer+FrameLen, apidx);
else if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QLoadTestEnable == 0)
#endif
FrameLen += QBSS_LoadElementAppend(pAd, pOutBuffer+FrameLen);
}
#endif /* AP_QLOAD_SUPPORT */
/* add WMM IE here */
if (mbss->wdev.bWmmCapable)
{
UCHAR i;
UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0};
WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f;
#ifdef UAPSD_SUPPORT
UAPSD_MR_IE_FILL(WmeParmIe[8], &mbss->wdev.UapsdInfo);
#endif /* UAPSD_SUPPORT */
for (i=QID_AC_BE; i<=QID_AC_VO; i++)
{
WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */
((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */
(pAd->ApCfg.BssEdcaParm.Aifsn[i] & 0x0f); /* b0-3 is AIFSN */
WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */
(pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */
WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */
WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */
}
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
26, WmeParmIe,
END_OF_ARGS);
FrameLen += TmpLen;
}
/* add country IE, power constraint IE */
if (pAd->CommonCfg.bCountryFlag)
{
#ifndef EXT_BUILD_CHANNEL_LIST
ULONG TmpLen;
#endif /* !EXT_BUILD_CHANNEL_LIST */
ULONG TmpLen2=0;
UCHAR *TmpFrame = NULL;
os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256);
if (TmpFrame != NULL)
{
NdisZeroMemory(TmpFrame, 256);
/* prepare channel information */
#ifdef EXT_BUILD_CHANNEL_LIST
BuildBeaconChList(pAd, TmpFrame, &TmpLen2);
#else
{
UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen,
1, &pAd->ChannelList[0].Channel,
1, &pAd->ChannelListNum,
1, &MaxTxPower,
END_OF_ARGS);
TmpLen2 += TmpLen;
}
#endif /* EXT_BUILD_CHANNEL_LIST */
#ifdef DOT11K_RRM_SUPPORT
if (IS_RRM_ENABLE(pAd, apidx)
&& (pAd->CommonCfg.RegulatoryClass[0] != 0))
{
TmpLen2 = 0;
NdisZeroMemory(TmpFrame, sizeof(TmpFrame));
RguClass_BuildBcnChList(pAd, TmpFrame, &TmpLen2);
}
#endif /* DOT11K_RRM_SUPPORT */
#if 0
UCHAR CountryIe = IE_COUNTRY;
/* need to do the padding bit check, and concatenate it */
if ((TmpLen2%2) == 0)
{
UCHAR TmpLen3 = TmpLen2+4;
MakeOutgoingFrame(pOutBuffer+FrameLen,&TmpLen,
1, &CountryIe,
1, &TmpLen3,
3, pAd->CommonCfg.CountryCode,
TmpLen2+1, TmpFrame,
END_OF_ARGS);
}
else
{
UCHAR TmpLen3 = TmpLen2+3;
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
1, &CountryIe,
1, &TmpLen3,
3, pAd->CommonCfg.CountryCode,
TmpLen2, TmpFrame,
END_OF_ARGS);
}
FrameLen += TmpLen;
#endif
os_free_mem(NULL, TmpFrame);
}
else
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
}
#ifdef DOT11K_RRM_SUPPORT
if (IS_RRM_ENABLE(pAd, apidx))
{
InsertTpcReportIE(pAd, pOutBuffer+FrameLen, &FrameLen,
RTMP_GetTxPwr(pAd, pAd->CommonCfg.MlmeTransmit), 0);
RRM_InsertRRMEnCapIE(pAd, pOutBuffer+FrameLen, &FrameLen, apidx);
}
{
INT loop;
for (loop=0; loop<MAX_NUM_OF_REGULATORY_CLASS; loop++)
{
if (pAd->CommonCfg.RegulatoryClass[loop] == 0)
break;
InsertChannelRepIE(pAd, pOutBuffer+FrameLen, &FrameLen,
(RTMP_STRING *)pAd->CommonCfg.CountryCode,
pAd->CommonCfg.RegulatoryClass[loop]);
}
}
/* Insert BSS AC Access Delay IE. */
RRM_InsertBssACDelayIE(pAd, pOutBuffer+FrameLen, &FrameLen);
/* Insert BSS Available Access Capacity IE. */
RRM_InsertBssAvailableACIE(pAd, pOutBuffer+FrameLen, &FrameLen);
#endif /* DOT11K_RRM_SUPPORT */
#ifdef DOT11_N_SUPPORT
#ifdef DOT11N_DRAFT3
/* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */
if (WMODE_CAP_N(PhyMode) &&
(pAd->CommonCfg.Channel <= 14) &&
(wdev->DesiredHtPhyInfo.bHtEnable) &&
(pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1))
{
OVERLAP_BSS_SCAN_IE OverlapScanParam;
ULONG TmpLen;
UCHAR OverlapScanIE, ScanIELen;
OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM;
ScanIELen = 14;
OverlapScanParam.ScanPassiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveDwell);
OverlapScanParam.ScanActiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveDwell);
OverlapScanParam.TriggerScanInt = cpu2le16(pAd->CommonCfg.Dot11BssWidthTriggerScanInt);
OverlapScanParam.PassiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel);
OverlapScanParam.ActiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel);
OverlapScanParam.DelayFactor = cpu2le16(pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor);
OverlapScanParam.ScanActThre = cpu2le16(pAd->CommonCfg.Dot11OBssScanActivityThre);
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1, &OverlapScanIE,
1, &ScanIELen,
ScanIELen, &OverlapScanParam,
END_OF_ARGS);
FrameLen += TmpLen;
}
/* 7.3.2.27 Extended Capabilities IE */
{
ULONG TmpLen;
EXT_CAP_INFO_ELEMENT extCapInfo;
UCHAR extInfoLen;
extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT);
NdisZeroMemory(&extCapInfo, extInfoLen);
/* P802.11n_D1.10, HT Information Exchange Support */
if (WMODE_CAP_N(PhyMode) && (pAd->CommonCfg.Channel <= 14) &&
(pAd->ApCfg.MBSSID[apidx].wdev.DesiredHtPhyInfo.bHtEnable) &&
(pAd->CommonCfg.bBssCoexEnable == TRUE))
{
extCapInfo.BssCoexistMgmtSupport = 1;
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
1, &ExtCapIe,
1, &extInfoLen,
extInfoLen, &extCapInfo,
END_OF_ARGS);
FrameLen += TmpLen;
}
}
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
/* add country IE, power constraint IE */
if (pAd->CommonCfg.bCountryFlag)
{
ULONG TmpLen2=0;
UCHAR TmpFrame[256];
UCHAR CountryIe = IE_COUNTRY;
UCHAR MaxTxPower=16;
#ifdef A_BAND_SUPPORT
/*
Only 802.11a APs that comply with 802.11h are required to include
a Power Constrint Element(IE=32) in beacons and probe response frames
*/
if (pAd->CommonCfg.Channel > 14 && pAd->CommonCfg.bIEEE80211H == TRUE)
{
/* prepare power constraint IE */
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
3, PowerConstraintIE,
END_OF_ARGS);
FrameLen += TmpLen;
#ifdef DOT11_VHT_AC
if (WMODE_CAP_AC(PhyMode)) {
ULONG TmpLen;
UINT8 vht_txpwr_env_ie = IE_VHT_TXPWR_ENV;
UINT8 ie_len;
VHT_TXPWR_ENV_IE txpwr_env;
ie_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env);
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1, &vht_txpwr_env_ie,
1, &ie_len,
ie_len, &txpwr_env,
END_OF_ARGS);
FrameLen += TmpLen;
}
#endif /* DOT11_VHT_AC */
}
#endif /* A_BAND_SUPPORT */
NdisZeroMemory(TmpFrame, sizeof(TmpFrame));
/* prepare channel information */
MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen,
1, &pAd->ChannelList[0].Channel,
1, &pAd->ChannelListNum,
1, &MaxTxPower,
END_OF_ARGS);
TmpLen2 += TmpLen;
/* need to do the padding bit check, and concatenate it */
if ((TmpLen2%2) == 0)
{
UCHAR TmpLen3 = TmpLen2+4;
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
1, &CountryIe,
1, &TmpLen3,
3, pAd->CommonCfg.CountryCode,
TmpLen2+1, TmpFrame,
END_OF_ARGS);
}
else
{
UCHAR TmpLen3 = TmpLen2+3;
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
1, &CountryIe,
1, &TmpLen3,
3, pAd->CommonCfg.CountryCode,
TmpLen2, TmpFrame,
END_OF_ARGS);
}
FrameLen += TmpLen;
}/* Country IE - */
#ifdef A_BAND_SUPPORT
/* add Channel switch announcement IE */
if ((pAd->CommonCfg.Channel > 14)
&& (pAd->CommonCfg.bIEEE80211H == 1)
&& (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE))
{
UCHAR CSAIe=IE_CHANNEL_SWITCH_ANNOUNCEMENT;
UCHAR CSALen=3;
UCHAR CSAMode=1;
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
1, &CSAIe,
1, &CSALen,
1, &CSAMode,
1, &pAd->CommonCfg.Channel,
1, &pAd->Dot11_H.CSCount,
END_OF_ARGS);
FrameLen += TmpLen;
#ifdef DOT11_N_SUPPORT
if (pAd->CommonCfg.bExtChannelSwitchAnnouncement)
{
HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe;
build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe);
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE), &HtExtChannelSwitchIe,
END_OF_ARGS);
}
#endif /* DOT11_N_SUPPORT */
FrameLen += TmpLen;
}
#endif /* A_BAND_SUPPORT */
#ifdef DOT11_N_SUPPORT
if (WMODE_CAP_N(PhyMode) &&
(wdev->DesiredHtPhyInfo.bHtEnable))
{
ULONG TmpLen;
UCHAR HtLen, AddHtLen;/*, NewExtLen; */
#ifdef RT_BIG_ENDIAN
HT_CAPABILITY_IE HtCapabilityTmp;
ADD_HT_INFO_IE addHTInfoTmp;
#endif
HtLen = sizeof(pAd->CommonCfg.HtCapability);
AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo);
if (pAd->bBroadComHT == TRUE)
{
UCHAR epigram_ie_len;
UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33};
UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34};
epigram_ie_len = HtLen + 4;
#ifndef RT_BIG_ENDIAN
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1, &WpaIe,
1, &epigram_ie_len,
4, &BROADCOM_HTC[0],
HtLen, &pAd->CommonCfg.HtCapability,
END_OF_ARGS);
#else
NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
*(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
#ifdef UNALIGNMENT_SUPPORT
{
EXT_HT_CAP_INFO extHtCapInfo;
NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO));
*(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo));
NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO));
}
#else
*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
#endif /* UNALIGNMENT_SUPPORT */
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1, &WpaIe,
1, &epigram_ie_len,
4, &BROADCOM_HTC[0],
HtLen, &HtCapabilityTmp,
END_OF_ARGS);
#endif
FrameLen += TmpLen;
epigram_ie_len = AddHtLen + 4;
#ifndef RT_BIG_ENDIAN
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1, &WpaIe,
1, &epigram_ie_len,
4, &BROADCOM_AHTINFO[0],
AddHtLen, &pAd->CommonCfg.AddHTInfo,
END_OF_ARGS);
#else
NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen);
*(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2));
*(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3));
MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
1, &WpaIe,
1, &epigram_ie_len,
4, &BROADCOM_AHTINFO[0],
AddHtLen, &addHTInfoTmp,
END_OF_ARGS);
#endif
FrameLen += TmpLen;
}
#ifdef DOT11_VHT_AC
if (WMODE_CAP_AC(PhyMode) &&
(pAd->CommonCfg.Channel > 14)) {
FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer+FrameLen), SUBTYPE_PROBE_RSP);
}
#endif /* DOT11_VHT_AC */
}
#endif /* DOT11_N_SUPPORT */
#ifdef WSC_AP_SUPPORT
/* for windows 7 logo test */
if ((mbss->WscControl.WscConfMode != WSC_DISABLE) &&
#ifdef DOT1X_SUPPORT
(wdev->IEEE8021X == FALSE) &&
#endif /* DOT1X_SUPPORT */
(wdev->WepStatus == Ndis802_11WEPEnabled))
{
/*
Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based
or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP
network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't
receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and
prompt user for the WEP key. <<from "WPS and Static Key WEP Networks">>
A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network.
The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp
*/
ULONG TempLen1 = 0;
UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00};
MakeOutgoingFrame(pOutBuffer+FrameLen, &TempLen1,
7, PROVISION_SERVICE_IE,
END_OF_ARGS);
FrameLen += TempLen1;
}
/* add Simple Config Information Element */
if ((mbss->WscControl.WscConfMode > WSC_DISABLE) && (mbss->WscIEProbeResp.ValueLen))
{
ULONG WscTmpLen = 0;
MakeOutgoingFrame(pOutBuffer+FrameLen, &WscTmpLen,
mbss->WscIEProbeResp.ValueLen, mbss->WscIEProbeResp.Value,
END_OF_ARGS);
FrameLen += WscTmpLen;
}
#endif /* WSC_AP_SUPPORT */
#ifdef WAC_SUPPORT
WAC_PeerProbeReq(pAd, apidx, Elem, Addr2, pOutBuffer, &FrameLen);
if (mbss->EasyConfigInfo.pVendorInfoForProbeRsp)
{
ULONG tmpWACLen = 0;
MakeOutgoingFrame(pOutBuffer+FrameLen,
&tmpWACLen,
mbss->EasyConfigInfo.VendorInfoForProbeRspLen,
mbss->EasyConfigInfo.pVendorInfoForProbeRsp,
END_OF_ARGS);
FrameLen += tmpWACLen;
}
#endif /* WAC_SUPPORT */
#ifdef DOT11R_FT_SUPPORT
/* The Mobility Domain information element (MDIE) is present in Probe-
** Request frame when dot11FastBssTransitionEnable is set to true. */
if (pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable)
{
PFT_CFG pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg;
FT_CAP_AND_POLICY FtCap;
FtCap.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs;
FtCap.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap;
FT_InsertMdIE(pAd, pOutBuffer + FrameLen, &FrameLen,
pFtCfg->FtMdId, FtCap);
}
#endif /* DOT11R_FT_SUPPORT */
#ifdef P2P_SUPPORT
if (P2P_GO_ON(pAd))
{
ULONG Peerip, P2PSubelementLen = 0, WpsLen = 0;
UCHAR *P2pSubelement;
UCHAR *WpsIE;
UCHAR Addr2[MAC_ADDR_LEN];
CHAR Ssid[MAX_LEN_OF_SSID];
UCHAR SsidLen;
#ifdef WFD_SUPPORT
UCHAR DeviceType, SourceCoupled, SinkCoupled, SessionAvail, WSD, PreC, CP, TimeSync, CoupledSinkStatus;
UCHAR BssidAddr[6];
ULONG WfdSubelementLen;
USHORT RtspPort, MaxThroughput;
PUCHAR WfdSubelement = NULL;
BOOLEAN WfdClient = FALSE;
#endif /* WFD_SUPPORT */
os_alloc_mem(NULL, (UCHAR **)&P2pSubelement, MAX_VIE_LEN);
os_alloc_mem(NULL, (UCHAR **)&WpsIE, MAX_VIE_LEN);
#ifdef WFD_SUPPORT
os_alloc_mem(NULL, (UCHAR **)&WfdSubelement, MAX_VIE_LEN);
#endif /* WFD_SUPPORT */
/*PeerP2pProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen, &Peerip, &P2PSubelementLen, P2pSubelement, &WpsLen, WpsIE);*/
/* Ralink Proprietary feature for IP */
/*
P2pMakeProbeWSCIE(pAd, pOutBuffer + FrameLen, &TmpLen);
FrameLen += TmpLen;
*/
/* APPeerProbeReqAction() is called when I am already GO. So doesn't use Is_P2P_on to check whether need to add P2P IE in response. */
/*if (P2PSubelementLen > 0)*/
if (PeerP2pProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen, &Peerip,
&P2PSubelementLen, P2pSubelement,
#ifdef WFD_SUPPORT
&WfdSubelementLen,
WfdSubelement,
#endif /* WFD_SUPPORT */
&WpsLen, WpsIE))
{
ULONG P2PIeLen;
PUCHAR ptr;
ptr = pOutBuffer + FrameLen;
P2pMakeP2pIE(pAd, SUBTYPE_PROBE_RSP, ptr, &P2PIeLen);
FrameLen += P2PIeLen;
}
#ifdef WFD_SUPPORT
{
PUCHAR ptr;
ptr = pOutBuffer + FrameLen;
WfdMakeWfdIE(pAd, SUBTYPE_PROBE_RSP, ptr, &TmpLen);
FrameLen += TmpLen;
}
#endif /* WFD_SUPPORT */
#ifdef WFA_WFD_SUPPORT
if (pAd->P2pCfg.bWIDI)
{
if (pAd->pWfdIeInProbeRsp && (pAd->WfdIeInProbeRspLen != 0))
{
ULONG WfdIeTmpLen = 0;
MakeOutgoingFrame(pOutBuffer+FrameLen, &WfdIeTmpLen,
pAd->WfdIeInProbeRspLen, pAd->pWfdIeInProbeRsp,
END_OF_ARGS);
FrameLen += WfdIeTmpLen;
}
}
#endif /* WFA_WFD_SUPPORT */
if (P2pSubelement)
os_free_mem(NULL, P2pSubelement);
if (WpsIE)
os_free_mem(NULL, WpsIE);
#ifdef WFD_SUPPORT
if (WfdSubelement)
os_free_mem(NULL, WfdSubelement);
#endif /* WFD_SUPPORT */
}
#endif /* P2P_SUPPORT */
/*
add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back
Byte0.b3=1 for rssi-feedback
*/
{
ULONG TmpLen;
UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00};
if (pAd->CommonCfg.bAggregationCapable)
RalinkSpecificIe[5] |= 0x1;
if (pAd->CommonCfg.bPiggyBackCapable)
RalinkSpecificIe[5] |= 0x2;
#ifdef DOT11_N_SUPPORT
if (pAd->CommonCfg.bRdg)
RalinkSpecificIe[5] |= 0x4;
#endif /* DOT11_N_SUPPORT */
#ifdef RSSI_FEEDBACK
if (ProbeReqParam.bRequestRssi == TRUE)
{
MAC_TABLE_ENTRY *pEntry=NULL;
DBGPRINT(RT_DEBUG_ERROR, ("SYNC - Send PROBE_RSP to %02x:%02x:%02x:%02x:%02x:%02x...\n",
PRINT_MAC(Addr2)));
RalinkSpecificIe[5] |= 0x8;
pEntry = MacTableLookup(pAd, Addr2);
if (pEntry != NULL)
{
RalinkSpecificIe[6] = (UCHAR)pEntry->RssiSample.AvgRssi[0];
RalinkSpecificIe[7] = (UCHAR)pEntry->RssiSample.AvgRssi[1];
RalinkSpecificIe[8] = (UCHAR)pEntry->RssiSample.AvgRssi[2];
}
}
#endif /* RSSI_FEEDBACK */
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
9, RalinkSpecificIe,
END_OF_ARGS);
FrameLen += TmpLen;
#ifdef RT3883
if (IS_RT3883(pAd))
FrameLen += RT3883_ext_pkt_len(pOutBuffer, FrameLen, RalinkSpecificIe, 9);
#endif /* RT3883 */
}
/* 802.11n 11.1.3.2.2 active scanning. sending probe response with MCS rate is */
MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
}
}
/*
==========================================================================
Description:
parse the received BEACON
NOTE:
The only thing AP cares about received BEACON frames is to decide
if there's any overlapped legacy BSS condition (OLBC).
If OLBC happened, this AP should set the ERP->Use_Protection bit in its
outgoing BEACON. The result is to tell all its clients to use RTS/CTS
or CTS-to-self protection to protect B/G mixed traffic
==========================================================================
*/
typedef struct
{
ULONG count;
UCHAR bssid[MAC_ADDR_LEN];
} BSSIDENTRY;
VOID APPeerBeaconAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
UCHAR Rates[MAX_LEN_OF_SUPPORTED_RATES], *pRates = NULL, RatesLen;
BOOLEAN LegacyBssExist;
CHAR RealRssi;
UCHAR *VarIE = NULL;
USHORT LenVIE;
NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
UCHAR MaxSupportedRate = 0;
#ifdef APCLI_SUPPORT
UINT ApCliIndex = 0;
#ifdef MT_MAC
BOOLEAN ApCliWcid = FALSE;
#endif /* MT_MAC */
#endif /* APCLI_SUPPORT */
#ifdef MESH_SUPPORT
UCHAR HostName[MAX_HOST_NAME_LEN] = {0};
UCHAR HostNameLen = 0;
UCHAR MeshId[MAX_MESH_ID_LEN] = {0};
UCHAR MeshIdLen = 0;
MESH_CONFIGURAION_IE MeshConfig = {0};
#endif /* MESH_SUPPORT */
BCN_IE_LIST *ie_list = NULL;
/* allocate memory */
os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST));
if (ie_list == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate ie_list fail!!!\n", __FUNCTION__));
goto LabelErr;
}
NdisZeroMemory(ie_list, sizeof(BCN_IE_LIST));
/* Init Variable IE structure */
os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN);
if (VarIE == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate VarIE fail!!!\n", __FUNCTION__));
goto LabelErr;
}
pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
pVIE->Length = 0;
pRates = (PUCHAR)Rates;
ie_list->Channel = Elem->Channel;
RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0),
ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1),
ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2));
if (PeerBeaconAndProbeRspSanity(pAd,
Elem->Msg,
Elem->MsgLen,
Elem->Channel,
ie_list,
&LenVIE,
pVIE,
FALSE))
{
#ifdef MESH_SUPPORT
MeshPeerBeaconAndProbeSanity(pAd, Elem->Msg, Elem->MsgLen, HostName, &HostNameLen, MeshId, &MeshIdLen, &MeshConfig);
if(MESH_ON(pAd) && (MeshIdLen != 0))
{
ULONG LinkIdx;
InsertNeighborMP(pAd, RealRssi, ie_list->Bssid, ie_list->Channel,
(UINT8)ie_list->AddHtInfo.AddHtInfo.RecomWidth,
(UINT8)ie_list->AddHtInfo.AddHtInfo.ExtChanOffset,
HostName, MeshId, MeshIdLen,
ie_list->CapabilityInfo, (PUCHAR)pVIE, LenVIE, &MeshConfig);
LinkIdx = GetMeshLinkId(pAd, (PCHAR)ie_list->Addr2);
if(VALID_MESH_LINK_ID(LinkIdx))
{
ULONG Now;
NdisGetSystemUpTime(&Now);
pAd->MeshTab.MeshLink[LinkIdx].Entry.LastBeaconTime = Now;
pAd->MeshTab.MeshLink[LinkIdx].Entry.OneSecBeaconCount++;
}
}
#endif /* MESH_SUPPORT */
/* ignore BEACON not in this channel */
if (ie_list->Channel != pAd->CommonCfg.Channel
#ifdef DOT11_N_SUPPORT
#ifdef DOT11N_DRAFT3
&& (pAd->CommonCfg.bOverlapScanning == FALSE)
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
#ifdef P2P_SUPPORT
&& (!P2P_CLI_ON(pAd))
#endif /* P2P_SUPPORT */
#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE
&& (!RTMP_CFG80211_VIF_P2P_CLI_ON(pAd))
#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */
#ifdef CFG80211_MULTI_STA
&& (!RTMP_CFG80211_MULTI_STA_ON(pAd, pAd->cfg80211_ctrl.multi_sta_net_dev))
#endif /* CFG80211_MULTI_STA */
)
{
goto __End_Of_APPeerBeaconAction;
}
#ifdef IDS_SUPPORT
/* Conflict SSID detection */
RTMPConflictSsidDetection(pAd, (PUCHAR)ie_list->Ssid, ie_list->SsidLen,
(CHAR)Elem->rssi_info.raw_rssi[0],
(CHAR)Elem->rssi_info.raw_rssi[1],
(CHAR)Elem->rssi_info.raw_rssi[2]);
#endif /* IDS_SUPPORT */
#ifdef DOT11_N_SUPPORT
/* 40Mhz BSS Width Trigger events Intolerant devices */
if ((RealRssi > OBSS_BEACON_RSSI_THRESHOLD) && (ie_list->HtCapability.HtCapInfo.Forty_Mhz_Intolerant)) /* || (HtCapabilityLen == 0))) */
{
Handle_BSS_Width_Trigger_Events(pAd);
}
#endif /* DOT11_N_SUPPORT */
#ifdef DOT11_N_SUPPORT
if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)
#ifdef DOT11N_DRAFT3
&& (pAd->CommonCfg.bOverlapScanning == FALSE)
#endif /* DOT11N_DRAFT3 */
)
{
if (pAd->CommonCfg.Channel<=14)
{
#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) || defined(CFG80211_MULTI_STA)
if(OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED) &&
#ifdef P2P_SUPPORT
P2P_CLI_ON(pAd)
#else
#ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE
RTMP_CFG80211_VIF_P2P_CLI_ON(pAd)
#else
RTMP_CFG80211_MULTI_STA_ON(pAd, pAd->cfg80211_ctrl.multi_sta_net_dev)
#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE */
#endif /* P2P_SUPPORT */
)
{
if (ie_list->Channel != pAd->CommonCfg.Channel)
{
DBGPRINT(RT_DEBUG_INFO, ("Channel=%d is not equal as CommonCfg.Channel = %d.\n", ie_list->Channel, pAd->CommonCfg.Channel));
// goto __End_Of_APPeerBeaconAction;
}
}
else
#endif /* P2P_SUPPORT || RT_CFG80211_P2P_CONCURRENT_DEVICE */
if (((pAd->CommonCfg.CentralChannel+2) != ie_list->Channel) &&
((pAd->CommonCfg.CentralChannel-2) != ie_list->Channel))
{
/*
DBGPRINT(RT_DEBUG_TRACE, ("%02x:%02x:%02x:%02x:%02x:%02x is a legacy BSS (%d) \n",
Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5], Channel));
*/
goto __End_Of_APPeerBeaconAction;
}
}
else
{
if (ie_list->Channel != pAd->CommonCfg.Channel)
{
//goto __End_Of_APPeerBeaconAction;
}
}
}
#endif /* DOT11_N_SUPPORT */
SupportRate(ie_list->SupRate, ie_list->SupRateLen, ie_list->ExtRate, ie_list->ExtRateLen, &pRates, &RatesLen, &MaxSupportedRate);
if ((ie_list->Erp & 0x01) || (RatesLen <= 4))
LegacyBssExist = TRUE;
else
LegacyBssExist = FALSE;
if (LegacyBssExist && pAd->CommonCfg.DisableOLBCDetect == 0)
{
pAd->ApCfg.LastOLBCDetectTime = pAd->Mlme.Now32;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("%02x:%02x:%02x:%02x:%02x:%02x is a legacy BSS (rate# =%d, ERP=%d), set Use_Protection bit\n",
PRINT_MAC(ie_list->Bssid), RatesLen, ie_list->Erp));
#endif /* RELEASE_EXCLUDE */
}
#ifdef DOT11_N_SUPPORT
if ((pAd->CommonCfg.bHTProtect)
&& (ie_list->HtCapabilityLen == 0) && (RealRssi > OBSS_BEACON_RSSI_THRESHOLD))
{
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("(RSSI:%d) %02x:%02x:%02x:%02x:%02x:%02x is a legacy BSS (rate# =%d, ERP=%d), set Use_Protection bit\n",
RealRssi, PRINT_MAC(ie_list->Bssid), RatesLen, ie_list->Erp));
#endif /* RELEASE_EXCLUDE */
pAd->ApCfg.LastNoneHTOLBCDetectTime = pAd->Mlme.Now32;
}
#endif /* DOT11_N_SUPPORT */
#ifdef APCLI_SUPPORT
#ifdef MT_MAC
if (Elem->Wcid == APCLI_MCAST_WCID)
ApCliWcid = TRUE;
#endif
if (Elem->Wcid < MAX_LEN_OF_MAC_TABLE
#ifdef MT_MAC
|| ApCliWcid
#endif
)
{
PMAC_TABLE_ENTRY pEntry = NULL;
#ifdef MT_MAC
if (ApCliWcid == FALSE)
#endif
pEntry = &pAd->MacTab.Content[Elem->Wcid];
#ifdef MT_MAC
else
pEntry = MacTableLookup(pAd, ie_list->Addr2);//Found the pEntry from Peer Bcn Content
#endif /* MT_MAC */
if (pEntry && IS_ENTRY_APCLI(pEntry) && (pEntry->func_tb_idx < MAX_APCLI_NUM))
{
//printk("%s: ===> beacon FINAL WCID[%d]\n", __FUNCTION__, Elem->Wcid);
ApCliIndex = pEntry->func_tb_idx;
pAd->ApCfg.ApCliTab[ApCliIndex].ApCliRcvBeaconTime = pAd->Mlme.Now32;
if (pAd->CommonCfg.BBPCurrentBW == BW_40)
{
/* Check if root-ap change BW to 20 */
if ((ie_list->AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_NONE) &&
(ie_list->AddHtInfo.AddHtInfo.RecomWidth == 0))
{
#ifdef MAC_REPEATER_SUPPORT
UINT ifIndex;
UCHAR CliIdx;
REPEATER_CLIENT_ENTRY *pReptEntry = NULL;
#endif /* MAC_REPEATER_SUPPORT */
pEntry->HTPhyMode.field.BW = 0;
#ifdef MAC_REPEATER_SUPPORT
ifIndex = pEntry->func_tb_idx;
if (pAd->ApCfg.bMACRepeaterEn)
{
for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++)
{
pReptEntry = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx];
if ((pReptEntry->CliEnable) && (pReptEntry->CliValid))
{
pEntry = &pAd->MacTab.Content[pReptEntry->MacTabWCID];
if (pEntry)
pEntry->HTPhyMode.field.BW = 0;
}
}
}
#endif /* MAC_REPEATER_SUPPORT */
DBGPRINT(RT_DEBUG_INFO, ("FallBack APClient BW to 20MHz\n"));
}
/* Check if root-ap change BW to 40 */
if ((ie_list->AddHtInfo.AddHtInfo.ExtChanOffset != EXTCHA_NONE) &&
(ie_list->HtCapabilityLen > 0) &&
(ie_list->HtCapability.HtCapInfo.ChannelWidth == 1))
{
#ifdef MAC_REPEATER_SUPPORT
UINT ifIndex;
UCHAR CliIdx;
REPEATER_CLIENT_ENTRY *pReptEntry = NULL;
#endif /* MAC_REPEATER_SUPPORT */
pEntry->HTPhyMode.field.BW = 1;
#ifdef MAC_REPEATER_SUPPORT
ifIndex = pEntry->func_tb_idx;
if (pAd->ApCfg.bMACRepeaterEn)
{
for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++)
{
pReptEntry = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx];
if ((pReptEntry->CliEnable) && (pReptEntry->CliValid))
{
pEntry = &pAd->MacTab.Content[pReptEntry->MacTabWCID];
if (pEntry)
pEntry->HTPhyMode.field.BW = 1;
}
}
}
#endif /* MAC_REPEATER_SUPPORT */
DBGPRINT(RT_DEBUG_INFO, ("FallBack APClient BW to 40MHz\n"));
}
}
}
//ApCliWaitProbRsp(pAd, ApCliIndex);
if ( /*ApCliWaitProbRsp(pAd, ApCliIndex) && */
(NdisEqualMemory(pAd->ApCfg.ApCliTab[ApCliIndex].CfgApCliBssid, ie_list->Bssid, MAC_ADDR_LEN)))
{
MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_PEER_BEACON, Elem->MsgLen, Elem->Msg, ApCliIndex);
}
#ifdef P2P_SUPPORT
else
{
PeerP2pBeacon(pAd, ie_list->Addr2, Elem, ie_list->TimeStamp);
if(ie_list->MessageToMe)
{
MiniportMMRequest(pAd, 0, (PUCHAR)&pAd->ApCfg.ApCliTab[0].PsPollFrame, sizeof(PSPOLL_FRAME));
}
}
#endif /* P2P_SUPPORT */
}
#endif /* APCLI_SUPPORT */
#ifdef WDS_SUPPORT
do
{
MAC_TABLE_ENTRY *pEntry;
BOOLEAN bWmmCapable;
/* check BEACON does in WDS TABLE. */
pEntry = WdsTableLookup(pAd, ie_list->Addr2, FALSE);
bWmmCapable = ie_list->EdcaParm.bValid ? TRUE : FALSE;
if (pEntry)
{
WdsPeerBeaconProc(pAd, pEntry, ie_list->CapabilityInfo,
MaxSupportedRate, RatesLen, bWmmCapable,
ie_list->RalinkIe, &ie_list->HtCapability,
ie_list->HtCapabilityLen);
}
} while(FALSE);
#endif /* WDS_SUPPORT */
#ifdef DOT11_N_SUPPORT
#ifdef DOT11N_DRAFT3
if (pAd->CommonCfg.bOverlapScanning == TRUE)
{
INT index,secChIdx;
//BOOLEAN found = FALSE;
ADD_HTINFO *pAdd_HtInfo;
for (index = 0; index < pAd->ChannelListNum; index++)
{
/* found the effected channel, mark that. */
if(pAd->ChannelList[index].Channel == ie_list->Channel)
{
secChIdx = -1;
if (ie_list->HtCapabilityLen > 0 && ie_list->AddHtInfoLen > 0)
{ /* This is a 11n AP. */
pAd->ChannelList[index].bEffectedChannel |= EFFECTED_CH_PRIMARY; /* 2; // 2 for 11N 20/40MHz AP with primary channel set as this channel. */
pAdd_HtInfo = &ie_list->AddHtInfo.AddHtInfo;
if (pAdd_HtInfo->ExtChanOffset == EXTCHA_BELOW)
{
#ifdef A_BAND_SUPPORT
if (ie_list->Channel > 14)
secChIdx = ((index > 0) ? (index - 1) : -1);
else
#endif /* A_BAND_SUPPORT */
secChIdx = ((index >= 4) ? (index - 4) : -1);
}
else if (pAdd_HtInfo->ExtChanOffset == EXTCHA_ABOVE)
{
#ifdef A_BAND_SUPPORT
if (ie_list->Channel > 14)
secChIdx = (((index+1) < pAd->ChannelListNum) ? (index + 1) : -1);
else
#endif /* A_BAND_SUPPORT */
secChIdx = (((index+4) < pAd->ChannelListNum) ? (index + 4) : -1);
}
if (secChIdx >=0)
pAd->ChannelList[secChIdx].bEffectedChannel |= EFFECTED_CH_SECONDARY; /* 1; */
if ((pAd->CommonCfg.Channel != ie_list->Channel) ||
(pAdd_HtInfo->ExtChanOffset != pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)
)
pAd->CommonCfg.BssCoexApCnt++;
}
else
{
/* This is a legacy AP. */
pAd->ChannelList[index].bEffectedChannel |= EFFECTED_CH_LEGACY; /* 4; 1 for legacy AP. */
pAd->CommonCfg.BssCoexApCnt++;
}
//found = TRUE;
}
}
}
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
}
/* sanity check fail, ignore this frame */
__End_Of_APPeerBeaconAction:
/*#ifdef AUTO_CH_SELECT_ENHANCE */
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
if (ie_list->Channel == pAd->ApCfg.AutoChannel_Channel)
{
if (AutoChBssSearchWithSSID(pAd, ie_list->Bssid, (PUCHAR)ie_list->Ssid, ie_list->SsidLen, ie_list->Channel) == BSS_NOT_FOUND)
pAd->pChannelInfo->ApCnt[pAd->ApCfg.current_channel_index]++;
AutoChBssInsertEntry(pAd, ie_list->Bssid, ie_list->Ssid, ie_list->SsidLen, ie_list->Channel, ie_list->NewExtChannelOffset, RealRssi);
}
}
#endif /* CONFIG_AP_SUPPORT */
/*#endif // AUTO_CH_SELECT_ENHANCE */
LabelErr:
if (VarIE != NULL)
os_free_mem(NULL, VarIE);
if (ie_list != NULL)
os_free_mem(NULL, ie_list);
return;
}
#ifdef AP_SCAN_SUPPORT
/*
==========================================================================
Description:
==========================================================================
*/
VOID APInvalidStateWhenScan(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem)
{
#ifdef MESH_SUPPORT
MlmeEnqueue(pAd, MESH_CTRL_STATE_MACHINE, APMT2_MLME_SCAN_ABORT, 0, NULL, 0);
#endif /* MESH_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.ApSyncMachine.CurrState));
}
/*
==========================================================================
Description:
Scan timeout handler, executed in timer thread
==========================================================================
*/
VOID APScanTimeout(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
DBGPRINT(RT_DEBUG_TRACE, ("AP SYNC - Scan Timeout \n"));
MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_SCAN_TIMEOUT, 0, NULL, 0);
RTMP_MLME_HANDLER(pAd);
}
/*
==========================================================================
Description:
Scan timeout procedure. basically add channel index by 1 and rescan
==========================================================================
*/
VOID APScanTimeoutAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem)
{
pAd->ScanCtrl.Channel = NextChannel(pAd, pAd->ScanCtrl.Channel);
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
/*
iwpriv set auto channel selection
update the current index of the channel
*/
if (pAd->ApCfg.bAutoChannelAtBootup == TRUE)
{
/* update current channel info */
UpdateChannelInfo(pAd, pAd->ApCfg.current_channel_index, pAd->ApCfg.AutoChannelAlg);
/* move to next channel */
pAd->ApCfg.current_channel_index++;
if (pAd->ApCfg.current_channel_index < pAd->ChannelListNum)
{
pAd->ApCfg.AutoChannel_Channel = pAd->ChannelList[pAd->ApCfg.current_channel_index].Channel;
}
}
}
#endif /* CONFIG_AP_SUPPORT */
ScanNextChannel(pAd, OPMODE_AP);
}
/*
==========================================================================
Description:
MLME SCAN req state machine procedure
==========================================================================
*/
VOID APMlmeScanReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem)
{
BOOLEAN Cancelled;
UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType;
/* Suspend MSDU transmission here */
RTMPSuspendMsduTransmission(pAd);
/* first check the parameter sanity */
if (MlmeScanReqSanity(pAd, Elem->Msg, Elem->MsgLen, &BssType, (PCHAR)Ssid, &SsidLen, &ScanType))
{
DBGPRINT(RT_DEBUG_TRACE, ("AP SYNC - MlmeScanReqAction\n"));
NdisGetSystemUpTime(&pAd->ApCfg.LastScanTime);
RTMPCancelTimer(&pAd->ScanCtrl.APScanTimer, &Cancelled);
/* record desired BSS parameters */
pAd->ScanCtrl.BssType = BssType;
pAd->ScanCtrl.ScanType = ScanType;
pAd->ScanCtrl.SsidLen = SsidLen;
NdisMoveMemory(pAd->ScanCtrl.Ssid, Ssid, SsidLen);
/* start from the first channel */
pAd->ScanCtrl.Channel = FirstChannel(pAd);
/* Let BBP register at 20MHz to do scan */
bbp_set_bw(pAd, BW_20);
DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n"));
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
if (pAd->ApCfg.bAutoChannelAtBootup == TRUE)/* iwpriv set auto channel selection */
{
APAutoChannelInit(pAd);
pAd->ApCfg.AutoChannel_Channel = pAd->ChannelList[0].Channel;
}
}
#endif /* CONFIG_AP_SUPPORT */
ScanNextChannel(pAd, OPMODE_AP);
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("AP SYNC - MlmeScanReqAction() sanity check fail. BUG!!!\n"));
pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE;
}
}
/*
==========================================================================
Description:
peer sends beacon back when scanning
==========================================================================
*/
VOID APPeerBeaconAtScanAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem)
{
//PFRAME_802_11 pFrame;
UCHAR *VarIE = NULL;
USHORT LenVIE;
NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
CHAR RealRssi = -127;
#ifdef MESH_SUPPORT
UCHAR HostName[MAX_HOST_NAME_LEN] = {0};
UCHAR HostNameLen = 0;
UCHAR MeshId[MAX_MESH_ID_LEN] = {0};
UCHAR MeshIdLen = 0;
MESH_CONFIGURAION_IE MeshConfig = {0};
#endif /* MESH_SUPPORT */
BCN_IE_LIST *ie_list = NULL;
os_alloc_mem(pAd, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST));
if (!ie_list) {
DBGPRINT(RT_DEBUG_ERROR, ("%s: Alloc memory for ie_list fail!!!\n", __FUNCTION__));
return;
}
NdisZeroMemory((UCHAR *)ie_list, sizeof(BCN_IE_LIST));
/* allocate memory */
os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN);
if (VarIE == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
goto LabelErr;
}
//pFrame = (PFRAME_802_11) Elem->Msg;
/* Init Variable IE structure */
pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
pVIE->Length = 0;
if (PeerBeaconAndProbeRspSanity(pAd,
Elem->Msg, Elem->MsgLen, Elem->Channel,
ie_list, &LenVIE, pVIE, FALSE))
{
ULONG Idx;
CHAR Rssi = -127;
RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0),
ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1),
ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2));
#ifdef MESH_SUPPORT
MeshPeerBeaconAndProbeSanity(pAd, Elem->Msg, Elem->MsgLen, HostName, &HostNameLen, MeshId, &MeshIdLen, &MeshConfig);
if(MESH_ON(pAd) && (MeshIdLen != 0))
{
ULONG LinkIdx;
InsertNeighborMP(pAd, RealRssi, ie_list->Bssid, ie_list->Channel, (UINT8)ie_list->AddHtInfo.AddHtInfo.RecomWidth,
(UINT8)ie_list->AddHtInfo.AddHtInfo.ExtChanOffset, HostName, MeshId, MeshIdLen, ie_list->CapabilityInfo, (PUCHAR)pVIE, LenVIE, &MeshConfig);
LinkIdx = GetMeshLinkId(pAd, (PCHAR)ie_list->Addr2);
if(VALID_MESH_LINK_ID(LinkIdx))
{
ULONG Now;
NdisGetSystemUpTime(&Now);
pAd->MeshTab.MeshLink[LinkIdx].Entry.LastBeaconTime = Now;
}
}
#endif /* MESH_SUPPORT */
#ifdef P2P_SUPPORT
MlmeEnqueue(pAd, P2P_DISC_STATE_MACHINE, P2P_DISC_PEER_PROB_RSP, Elem->MsgLen, Elem->Msg, ie_list->Channel);
#endif /* P2P_SUPPORT */
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("Channel = %d, RealRssi = %d\n", ie_list->Channel, RealRssi));
#endif /* RELEASE_EXCLUDE */
/* ignore BEACON not in this channel */
if (ie_list->Channel != pAd->ScanCtrl.Channel
#ifdef DOT11_N_SUPPORT
#ifdef DOT11N_DRAFT3
&& (pAd->CommonCfg.bOverlapScanning == FALSE)
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
)
{
goto __End_Of_APPeerBeaconAtScanAction;
}
#ifdef DOT11_N_SUPPORT
if ((RealRssi > OBSS_BEACON_RSSI_THRESHOLD) && (ie_list->HtCapability.HtCapInfo.Forty_Mhz_Intolerant)) /* || (HtCapabilityLen == 0))) */
{
Handle_BSS_Width_Trigger_Events(pAd);
}
#endif /* DOT11_N_SUPPORT */
#ifdef IDS_SUPPORT
/* Conflict SSID detection */
if (ie_list->Channel == pAd->CommonCfg.Channel)
RTMPConflictSsidDetection(pAd, ie_list->Ssid, ie_list->SsidLen,
Elem->rssi_info.raw_rssi[0],
Elem->rssi_info.raw_rssi[1],
Elem->rssi_info.raw_rssi[2]);
#endif /* IDS_SUPPORT */
/*
This correct im-proper RSSI indication during SITE SURVEY issue.
Always report bigger RSSI during SCANNING when receiving multiple BEACONs from the same AP.
This case happens because BEACONs come from adjacent channels, so RSSI become weaker as we
switch to more far away channels.
*/
Idx = BssTableSearch(&pAd->ScanTab, ie_list->Bssid, ie_list->Channel);
if (Idx != BSS_NOT_FOUND)
{
UINT32 u4MaxBssEntrySize = sizeof(pAd->ScanTab.BssEntry)/sizeof(pAd->ScanTab.BssEntry[0]);
if(Idx < u4MaxBssEntrySize)
Rssi = pAd->ScanTab.BssEntry[Idx].Rssi;
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s(): Over buffer size!\n", __FUNCTION__));
}
}
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("(RSSI:%d) %02x:%02x:%02x:%02x:%02x:%02x is a [legacy] BSS\n",
Rssi, PRINT_MAC(ie_list->Bssid)));
#endif /* RELEASE_EXCLUDE */
/* TODO: 2005-03-04 dirty patch. we should change all RSSI related variables to SIGNED SHORT for easy/efficient reading and calaulation */
RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0),
ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1),
ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2));
if ((RealRssi + pAd->BbpRssiToDbmDelta) > Rssi)
Rssi = RealRssi + pAd->BbpRssiToDbmDelta;
Idx = BssTableSetEntry(pAd, &pAd->ScanTab, ie_list, Rssi, LenVIE, pVIE);
if ((Idx != BSS_NOT_FOUND) && (Idx >= ARRAY_SIZE(pAd->ScanTab.BssEntry))) {
DBGPRINT(RT_DEBUG_OFF,
("%s wrong idx %lu BssEntry sz %zu\n", __func__,
Idx, ARRAY_SIZE(pAd->ScanTab.BssEntry)));
} else if (Idx != BSS_NOT_FOUND) {
NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4);
NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4);
NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4);
}
#if defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) || defined(CFG80211_MULTI_STA)
if (RTMPEqualMemory(ie_list->Ssid, "DIRECT-", 7))
DBGPRINT(RT_DEBUG_OFF, ("%s P2P_SCANNING: %s [%lu], channel =%u\n", __FUNCTION__, ie_list->Ssid, Idx, Elem->Channel));
if (ie_list->Channel != 0)
Elem->Channel = ie_list->Channel;
//DBGPRINT(RT_DEBUG_TRACE, ("APPeerBeaconAtScanAction : Update the SSID %s in Kernel Table, Elem->Channel=%u\n", ie_list->Ssid,Elem->Channel));
RT_CFG80211_SCANNING_INFORM(pAd, Idx, /*ie_list->Channel*/Elem->Channel, (UCHAR *)Elem->Msg, Elem->MsgLen, RealRssi);
#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE || CFG80211_MULTI_STA */
}
/* sanity check fail, ignored */
__End_Of_APPeerBeaconAtScanAction:
/*scan beacon in pastive */
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
if (ie_list->Channel == pAd->ApCfg.AutoChannel_Channel)
{
if (AutoChBssSearchWithSSID(pAd, ie_list->Bssid, (PUCHAR)ie_list->Ssid, ie_list->SsidLen, ie_list->Channel) == BSS_NOT_FOUND)
pAd->pChannelInfo->ApCnt[pAd->ApCfg.current_channel_index]++;
AutoChBssInsertEntry(pAd, ie_list->Bssid, (CHAR *)ie_list->Ssid, ie_list->SsidLen, ie_list->Channel, ie_list->NewExtChannelOffset, RealRssi);
}
}
#endif /* CONFIG_AP_SUPPORT */
LabelErr:
if (VarIE != NULL)
os_free_mem(NULL, VarIE);
if (ie_list != NULL)
os_free_mem(NULL, ie_list);
}
/*
==========================================================================
Description:
MLME Cancel the SCAN req state machine procedure
==========================================================================
*/
VOID APScanCnclAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem)
{
BOOLEAN Cancelled;
RTMPCancelTimer(&pAd->ScanCtrl.APScanTimer, &Cancelled);
pAd->ScanCtrl.Channel = 0;
ScanNextChannel(pAd, OPMODE_AP);
return;
}
/*
==========================================================================
Description:
if ChannelSel is false,
AP scans channels and lists the information of channels.
if ChannelSel is true,
AP scans channels and selects an optimal channel.
NOTE:
==========================================================================
*/
VOID ApSiteSurvey(
IN PRTMP_ADAPTER pAd,
IN PNDIS_802_11_SSID pSsid,
IN UCHAR ScanType,
IN BOOLEAN ChannelSel)
{
MLME_SCAN_REQ_STRUCT ScanReq;
AsicDisableSync(pAd);
BssTableInit(&pAd->ScanTab);
pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE;
RTMPZeroMemory(ScanReq.Ssid, MAX_LEN_OF_SSID);
ScanReq.SsidLen = 0;
if (pSsid) {
ScanReq.SsidLen = (UCHAR)pSsid->SsidLength;
if (pSsid->SsidLength > 0)
NdisMoveMemory(ScanReq.Ssid, pSsid->Ssid, pSsid->SsidLength);
}
ScanReq.BssType = BSS_ANY;
ScanReq.ScanType = ScanType;
pAd->ApCfg.bAutoChannelAtBootup = ChannelSel;
MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0);
RTMP_MLME_HANDLER(pAd);
}
BOOLEAN ApScanRunning(RTMP_ADAPTER *pAd)
{
return (pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_LISTEN) ? TRUE : FALSE;
}
#endif /* AP_SCAN_SUPPORT */
/*
==========================================================================
Description:
The sync state machine,
Parameters:
Sm - pointer to the state machine
Note:
the state machine looks like the following
AP_SYNC_IDLE
APMT2_PEER_PROBE_REQ peer_probe_req_action
==========================================================================
*/
VOID APSyncStateMachineInit(
IN RTMP_ADAPTER *pAd,
IN STATE_MACHINE *Sm,
OUT STATE_MACHINE_FUNC Trans[])
{
StateMachineInit(Sm, (STATE_MACHINE_FUNC *)Trans, AP_MAX_SYNC_STATE, AP_MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, AP_SYNC_IDLE, AP_SYNC_MACHINE_BASE);
StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)APPeerProbeReqAction);
StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_PEER_BEACON, (STATE_MACHINE_FUNC)APPeerBeaconAction);
#if defined(P2P_SUPPORT) || defined(RT_CFG80211_P2P_SUPPORT) || defined(CFG80211_MULTI_STA)
StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)APPeerBeaconAtScanAction);
#endif /* P2P_SUPPORT || RT_CFG80211_P2P_SUPPORT || CFG80211_MULTI_STA */
#ifdef AP_SCAN_SUPPORT
StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)APMlmeScanReqAction);
/* scan_listen state */
StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)APInvalidStateWhenScan);
StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_PEER_BEACON, (STATE_MACHINE_FUNC)APPeerBeaconAtScanAction);
StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)APPeerBeaconAtScanAction);
StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)APScanTimeoutAction);
StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_MLME_SCAN_CNCL, (STATE_MACHINE_FUNC)APScanCnclAction);
RTMPInitTimer(pAd, &pAd->ScanCtrl.APScanTimer, GET_TIMER_FUNCTION(APScanTimeout), pAd, FALSE);
#endif /* AP_SCAN_SUPPORT */
}
VOID SupportRate(
IN PUCHAR SupRate,
IN UCHAR SupRateLen,
IN PUCHAR ExtRate,
IN UCHAR ExtRateLen,
OUT PUCHAR *ppRates,
OUT PUCHAR RatesLen,
OUT PUCHAR pMaxSupportRate)
{
INT i;
*pMaxSupportRate = 0;
if ((SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) && (SupRateLen > 0))
{
NdisMoveMemory(*ppRates, SupRate, SupRateLen);
*RatesLen = SupRateLen;
}
else
{
/* HT rate not ready yet. return true temporarily. rt2860c */
/*DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SUPP_RATES\n")); */
*RatesLen = 8;
*(*ppRates + 0) = 0x82;
*(*ppRates + 1) = 0x84;
*(*ppRates + 2) = 0x8b;
*(*ppRates + 3) = 0x96;
*(*ppRates + 4) = 0x12;
*(*ppRates + 5) = 0x24;
*(*ppRates + 6) = 0x48;
*(*ppRates + 7) = 0x6c;
DBGPRINT(RT_DEBUG_TRACE, ("SUPP_RATES., Len=%d\n", SupRateLen));
}
if (ExtRateLen + *RatesLen <= MAX_LEN_OF_SUPPORTED_RATES)
{
NdisMoveMemory((*ppRates + (ULONG)*RatesLen), ExtRate, ExtRateLen);
*RatesLen = (*RatesLen) + ExtRateLen;
}
else
{
NdisMoveMemory((*ppRates + (ULONG)*RatesLen), ExtRate, MAX_LEN_OF_SUPPORTED_RATES - (*RatesLen));
*RatesLen = MAX_LEN_OF_SUPPORTED_RATES;
}
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("%s - SUPP_RATES., Len=%d. Rates[0]=%x\n", __FUNCTION__, *RatesLen, **ppRates));
DBGPRINT(RT_DEBUG_INFO, ("Rates[1]=%x %x %x %x %x %x %x\n",
*(*ppRates+1), *(*ppRates+2), *(*ppRates+3), *(*ppRates+4), *(*ppRates+5), *(*ppRates+6), *(*ppRates+7)));
#endif /* RELEASE_EXCLUDE */
for (i = 0; i < *RatesLen; i++)
{
if(*pMaxSupportRate < (*(*ppRates + i) & 0x7f))
*pMaxSupportRate = (*(*ppRates + i) & 0x7f);
}
return;
}
#ifdef DOT11_N_SUPPORT
/* Regulatory classes in the USA */
typedef struct
{
UCHAR regclass; /* regulatory class */
UCHAR spacing; /* 0: 20Mhz, 1: 40Mhz */
UCHAR channelset[16]; /* max 15 channels, use 0 as terminator */
} REG_CLASS;
REG_CLASS reg_class[] =
{
{ 1, 0, {36, 40, 44, 48, 0}},
{ 2, 0, {52, 56, 60, 64, 0}},
{ 3, 0, {149, 153, 157, 161, 0}},
{ 4, 0, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0}},
{ 5, 0, {165, 0}},
{ 22, 1, {36, 44, 0}},
{ 23, 1, {52, 60, 0}},
{ 24, 1, {100, 108, 116, 124, 132, 0}},
{ 25, 1, {149, 157, 0}},
{ 26, 1, {149, 157, 0}},
{ 27, 1, {40, 48, 0}},
{ 28, 1, {56, 64, 0}},
{ 29, 1, {104, 112, 120, 128, 136, 0}},
{ 30, 1, {153, 161, 0}},
{ 31, 1, {153, 161, 0}},
{ 32, 1, {1, 2, 3, 4, 5, 6, 7, 0}},
{ 33, 1, {5, 6, 7, 8, 9, 10, 11, 0}},
{ 0, 0, {0}} /* end */
};
UCHAR get_regulatory_class(RTMP_ADAPTER *pAd)
{
int i=0;
UCHAR regclass = 0;
do
{
if (reg_class[i].spacing == pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth)
{
int j=0;
do
{
if (reg_class[i].channelset[j] == pAd->CommonCfg.Channel)
{
regclass = reg_class[i].regclass;
break;
}
j++;
} while (reg_class[i].channelset[j] != 0);
}
i++;
} while (reg_class[i].regclass != 0);
ASSERT(regclass);
return regclass;
}
void build_ext_channel_switch_ie(
IN PRTMP_ADAPTER pAd,
IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE *pIE)
{
pIE->ID = IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT;
pIE->Length = 4;
pIE->ChannelSwitchMode = 1; /*no further frames */
pIE->NewRegClass = get_regulatory_class(pAd);
pIE->NewChannelNum = pAd->CommonCfg.Channel;
pIE->ChannelSwitchCount = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1);
}
#endif /* DOT11_N_SUPPORT */