/* ========================================================================== Description: Set Wireless Mode for MBSS Return: TRUE if all parameters are OK, FALSE otherwise ========================================================================== */ INT RT_CfgSetMbssWirelessMode(RTMP_ADAPTER *pAd, PSTRING arg) { INT cfg_mode; UCHAR wmode; RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; cfg_mode = simple_strtol(arg, 0, 10); wmode = cfgmode_2_wmode((UCHAR)cfg_mode); if ((wmode == WMODE_INVALID) || (!wmode_valid(pAd, wmode))) { DBGPRINT(RT_DEBUG_ERROR, ("%s(): Invalid wireless mode(%d, wmode=0x%x), ChipCap(%s)\n", __FUNCTION__, cfg_mode, wmode, BAND_STR[pAd->chipCap.phy_caps & 0x3])); return FALSE; } if (WMODE_CAP_5G(wmode) && WMODE_CAP_2G(wmode)) { DBGPRINT(RT_DEBUG_ERROR, ("AP cannot support 2.4G/5G band mxied mode!\n")); return FALSE; } #if defined(MT76x2) && defined(DOT11_VHT_AC) if (pChipCap->ac_off_mode && WMODE_CAP_AC(wmode)) { DBGPRINT(RT_DEBUG_ERROR, ("it doesn't support VHT AC!\n")); wmode &= ~(WMODE_AC); } #endif /* MT76x2 */ if (pAd->ApCfg.BssidNum > 1) { /* pAd->CommonCfg.PhyMode = maximum capability of all MBSS */ if (wmode_band_equal(pAd->CommonCfg.PhyMode, wmode) == TRUE) { wmode = RT_CfgMbssWirelessModeMaxGet(pAd); DBGPRINT(RT_DEBUG_TRACE, ("mbss> Maximum phy mode = %d!\n", wmode)); } else { UINT32 IdBss; /* replace all phy mode with the one with different band */ DBGPRINT(RT_DEBUG_TRACE, ("mbss> Different band with the current one!\n")); DBGPRINT(RT_DEBUG_TRACE, ("mbss> Reset band of all BSS to the new one!\n")); for(IdBss=0; IdBss<pAd->ApCfg.BssidNum; IdBss++) pAd->ApCfg.MBSSID[IdBss].wdev.PhyMode = wmode; } } pAd->CommonCfg.PhyMode = wmode; pAd->CommonCfg.cfg_wmode = wmode; return TRUE; }
BOOLEAN SetCommonVHT(RTMP_ADAPTER *pAd) { if (!WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) { /* Clear previous VHT information */ return FALSE; } RTMPSetVHT(pAd); pAd->CommonCfg.vht_cent_ch = vht_cent_ch_freq(pAd, pAd->CommonCfg.Channel); DBGPRINT(RT_DEBUG_TRACE, ("%s(): Config VHT parameters!cent_ch=0!vht_cent_ch = %d, vht_cent_ch2 = %d\n", __FUNCTION__, pAd->CommonCfg.vht_cent_ch, pAd->CommonCfg.vht_cent_ch2)); return TRUE; }
INT SetCommonVHT(struct rtmp_adapter*pAd) { u8 cent_ch = 0; if (!WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) { /* Clear previous VHT information */ return false; } pAd->CommonCfg.vht_cent_ch = vht_cent_ch_freq(pAd, pAd->CommonCfg.Channel); DBGPRINT(RT_DEBUG_TRACE, ("%s(): Config VHT parameters!cent_ch=%d!vht_cent_ch = %d, vht_cent_ch2 = %d\n", __FUNCTION__, cent_ch, pAd->CommonCfg.vht_cent_ch, pAd->CommonCfg.vht_cent_ch2)); return true; }
/* ========================================================================== Description: Set Wireless Mode Return: TRUE if all parameters are OK, FALSE otherwise ========================================================================== */ INT RT_CfgSetWirelessMode(RTMP_ADAPTER *pAd, PSTRING arg) { LONG cfg_mode; UCHAR wmode, *mode_str; RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; cfg_mode = simple_strtol(arg, 0, 10); /* check if chip support 5G band when WirelessMode is 5G band */ wmode = cfgmode_2_wmode((UCHAR)cfg_mode); if ((wmode == WMODE_INVALID) || (!wmode_valid(pAd, wmode))) { DBGPRINT(RT_DEBUG_ERROR, ("%s(): Invalid wireless mode(%ld, wmode=0x%x), ChipCap(%s)\n", __FUNCTION__, cfg_mode, wmode, BAND_STR[pAd->chipCap.phy_caps & 0x3])); return FALSE; } #if defined(MT76x2) && defined(DOT11_VHT_AC) if (pChipCap->ac_off_mode && WMODE_CAP_AC(wmode)) { DBGPRINT(RT_DEBUG_ERROR, ("it doesn't support VHT AC!\n")); wmode &= ~(WMODE_AC); } #endif /* MT76x2 */ if (wmode_band_equal(pAd->CommonCfg.PhyMode, wmode) == TRUE) DBGPRINT(RT_DEBUG_OFF, ("wmode_band_equal(): Band Equal!\n")); else DBGPRINT(RT_DEBUG_OFF, ("wmode_band_equal(): Band Not Equal!\n")); pAd->CommonCfg.PhyMode = wmode; pAd->CommonCfg.cfg_wmode = wmode; mode_str = wmode_2_str(wmode); if (mode_str) { DBGPRINT(RT_DEBUG_TRACE, ("%s(): Set WMODE=%s(0x%x)\n", __FUNCTION__, mode_str, wmode)); os_free_mem(NULL, mode_str); } return TRUE; }
/* ========================================================================== Description: mlme assoc req handling procedure Parameters: Adapter - Adapter pointer Elem - MLME Queue Element Pre: the station has been authenticated and the following information is stored in the config -# SSID -# supported rates and their length Post : -# An association request frame is generated and sent to the air -# Association timer starts -# Association state -> ASSOC_WAIT_RSP ========================================================================== */ static VOID ApCliMlmeAssocReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { NDIS_STATUS NStatus; BOOLEAN Cancelled; UCHAR ApAddr[6]; HEADER_802_11 AssocHdr; UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; USHORT ListenIntv; ULONG Timeout; USHORT CapabilityInfo; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0; ULONG tmp; UCHAR SsidIe = IE_SSID; UCHAR SupRateIe = IE_SUPP_RATES; UCHAR ExtRateIe = IE_EXT_SUPP_RATES; APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; USHORT ifIndex = (USHORT)(Elem->Priv); PULONG pCurrState = NULL; UCHAR RSNIe = IE_WPA; APCLI_STRUCT *apcli_entry; struct wifi_dev *wdev; #ifdef MAC_REPEATER_SUPPORT UCHAR CliIdx = 0xFF; #endif /* MAC_REPEATER_SUPPORT */ if ((ifIndex >= MAX_APCLI_NUM) #ifdef MAC_REPEATER_SUPPORT && (ifIndex < 64) #endif /* MAC_REPEATER_SUPPORT */ ) return; #ifdef MAC_REPEATER_SUPPORT if (ifIndex >= 64) { CliIdx = ((ifIndex - 64) % 16); ifIndex = ((ifIndex - 64) / 16); pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AssocCurrState; } else #endif /* MAC_REPEATER_SUPPORT */ pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; wdev = &apcli_entry->wdev; /* Block all authentication request durning WPA block period */ if (apcli_entry->bBlockAssoc == TRUE) { DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - Block Auth request durning WPA block period!\n")); *pCurrState = APCLI_ASSOC_IDLE; ApCliCtrlMsg.Status = MLME_STATE_MACHINE_REJECT; MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); } else if(MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) { //RTMPCancelTimer(&apcli_entry->MlmeAux.ApCliAssocTimer, &Cancelled); #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) RTMPCancelTimer(&apcli_entry->RepeaterCli[CliIdx].ApCliAssocTimer, &Cancelled); else #endif /* MAC_REPEATER_SUPPORT */ RTMPCancelTimer(&apcli_entry->MlmeAux.ApCliAssocTimer, &Cancelled); /* allocate and send out AssocRsp frame */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliMlmeAssocReqAction() allocate memory failed \n")); *pCurrState = APCLI_ASSOC_IDLE; ApCliCtrlMsg.Status = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); return; } DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - Send ASSOC request...\n")); ApCliMgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, ApAddr, ifIndex); #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) COPY_MAC_ADDR(AssocHdr.Addr2, apcli_entry->RepeaterCli[CliIdx].CurrentAddress); #endif /* MAC_REPEATER_SUPPORT */ /* Build basic frame first */ MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &AssocHdr, 2, &CapabilityInfo, 2, &ListenIntv, 1, &SsidIe, 1, &apcli_entry->MlmeAux.SsidLen, apcli_entry->MlmeAux.SsidLen, apcli_entry->MlmeAux.Ssid, 1, &SupRateIe, 1, &apcli_entry->MlmeAux.SupRateLen, apcli_entry->MlmeAux.SupRateLen, apcli_entry->MlmeAux.SupRate, END_OF_ARGS); if(apcli_entry->MlmeAux.ExtRateLen != 0) { MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 1, &ExtRateIe, 1, &apcli_entry->MlmeAux.ExtRateLen, apcli_entry->MlmeAux.ExtRateLen, apcli_entry->MlmeAux.ExtRate, END_OF_ARGS); FrameLen += tmp; } #ifdef DOT11_N_SUPPORT /* WFA recommend to restrict the encryption type in 11n-HT mode. So, the WEP and TKIP are not allowed in HT rate. */ if (pAd->CommonCfg.HT_DisallowTKIP && IS_INVALID_HT_SECURITY(wdev->WepStatus)) { /* Force to None-HT mode due to WiFi 11n policy */ apcli_entry->MlmeAux.HtCapabilityLen = 0; #ifdef DOT11_VHT_AC apcli_entry->MlmeAux.vht_cap_len = 0; #endif /* DOT11_VHT_AC */ DBGPRINT(RT_DEBUG_TRACE, ("%s : Force AP-client as Non-HT mode\n", __FUNCTION__)); } /* HT */ if ((apcli_entry->MlmeAux.HtCapabilityLen > 0) && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { ULONG TmpLen; HT_CAPABILITY_IE HtCapabilityTmp; NdisZeroMemory(&HtCapabilityTmp, sizeof(HT_CAPABILITY_IE)); NdisMoveMemory(&HtCapabilityTmp, &apcli_entry->MlmeAux.HtCapability, apcli_entry->MlmeAux.HtCapabilityLen); #ifdef DOT11N_SS3_SUPPORT HtCapabilityTmp.MCSSet[2] = (apcli_entry->MlmeAux.HtCapability.MCSSet[2] & apcli_entry->RxMcsSet[2]); #endif /* DOT11N_SS3_SUPPORT */ #ifdef RT_BIG_ENDIAN *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* RT_BIG_ENDINA */ MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &HtCapIe, 1, &apcli_entry->MlmeAux.HtCapabilityLen, apcli_entry->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, END_OF_ARGS); FrameLen += TmpLen; #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->CommonCfg.Channel > 14) && (apcli_entry->MlmeAux.vht_cap_len)) { FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer + FrameLen), SUBTYPE_ASSOC_REQ); } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ #ifdef AGGREGATION_SUPPORT /* add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION Case I: (Aggregation + Piggy-Back) 1. user enable aggregation, AND 2. Mac support piggy-back 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON Case II: (Aggregation) 1. user enable aggregation, AND 2. AP annouces it's AGGREGATION-capable in BEACON */ if (pAd->CommonCfg.bAggregationCapable) { #ifdef PIGGYBACK_SUPPORT if ((pAd->CommonCfg.bPiggyBackCapable) && ((apcli_entry->MlmeAux.APRalinkIe & 0x00000003) == 3)) { ULONG TmpLen; UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00}; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 9, RalinkIe, END_OF_ARGS); FrameLen += TmpLen; } else #endif /* PIGGYBACK_SUPPORT */ if (apcli_entry->MlmeAux.APRalinkIe & 0x00000001) { ULONG TmpLen; UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 9, RalinkIe, END_OF_ARGS); FrameLen += TmpLen; } } else { ULONG TmpLen; UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00}; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 9, RalinkIe, END_OF_ARGS); FrameLen += TmpLen; } #endif /* AGGREGATION_SUPPORT */ if (apcli_entry->MlmeAux.APEdcaParm.bValid) { if (apcli_entry->wdev.UapsdInfo.bAPSDCapable && apcli_entry->MlmeAux.APEdcaParm.bAPSDCapable) { QBSS_STA_INFO_PARM QosInfo; NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; WmeIe[8] |= *(PUCHAR)&QosInfo; } else { /* The Parameter Set Count is set to бз0би in the association request frames */ /* WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f); */ } MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 9, &WmeIe[0], END_OF_ARGS); FrameLen += tmp; } #if defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) || defined(CFG80211_MULTI_STA) apcli_entry->ReqVarIELen = 0; NdisZeroMemory(apcli_entry->ReqVarIEs, MAX_VIE_LEN); if ((apcli_entry->wpa_supplicant_info.WpaSupplicantUP & 0x7F ) == WPA_SUPPLICANT_ENABLE) { DBGPRINT(RT_DEBUG_TRACE,("%s:: APCLI WPA_ASSOC_IE FROM SUPPLICANT\n", __FUNCTION__)); ULONG TmpWpaAssocIeLen = 0; MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpWpaAssocIeLen, apcli_entry->wpa_supplicant_info.WpaAssocIeLen, apcli_entry->wpa_supplicant_info.pWpaAssocIe, END_OF_ARGS); FrameLen += TmpWpaAssocIeLen; VarIesOffset = 0; NdisMoveMemory(apcli_entry->ReqVarIEs + VarIesOffset, apcli_entry->wpa_supplicant_info.pWpaAssocIe, apcli_entry->wpa_supplicant_info.WpaAssocIeLen); VarIesOffset += apcli_entry->wpa_supplicant_info.WpaAssocIeLen; // Set Variable IEs Length apcli_entry->ReqVarIELen = VarIesOffset; } else #endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE || CFG80211_MULTI_STA */ /* Append RSN_IE when WPAPSK OR WPA2PSK, */ if (((wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) #ifdef WSC_AP_SUPPORT && ((apcli_entry->WscControl.WscConfMode == WSC_DISABLE) || ((apcli_entry->WscControl.WscConfMode != WSC_DISABLE) && !(apcli_entry->WscControl.bWscTrigger))) #endif /* WSC_AP_SUPPORT */ ) { RSNIe = IE_WPA; if ((wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) ) RSNIe = IE_WPA2; MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 1, &RSNIe, 1, &apcli_entry->RSNIE_Len, apcli_entry->RSNIE_Len, apcli_entry->RSN_IE, END_OF_ARGS); FrameLen += tmp; } #ifdef WSC_AP_SUPPORT /* Add WSC IE if we are connecting to WSC AP */ if ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger)) { UCHAR *pWscBuf = NULL, WscIeLen = 0; ULONG WscTmpLen = 0; os_alloc_mem(pAd, (UCHAR **) &pWscBuf, 512); /* if( (pWscBuf = kmalloc(512, GFP_ATOMIC)) != NULL) */ if (pWscBuf != NULL) { NdisZeroMemory(pWscBuf, 512); WscBuildAssocReqIE(&pAd->ApCfg.ApCliTab[ifIndex].WscControl, pWscBuf, &WscIeLen); MakeOutgoingFrame(pOutBuffer + FrameLen, &WscTmpLen, WscIeLen, pWscBuf, END_OF_ARGS); FrameLen += WscTmpLen; /* kfree(pWscBuf); */ os_free_mem(NULL, pWscBuf); } else DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__)); } #endif /* WSC_AP_SUPPORT */ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) RTMPSetTimer(&apcli_entry->RepeaterCli[CliIdx].ApCliAssocTimer, Timeout); else #endif /* MAC_REPEATER_SUPPORT */ RTMPSetTimer(&apcli_entry->MlmeAux.ApCliAssocTimer, Timeout); *pCurrState = APCLI_ASSOC_WAIT_RSP; } else { DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliMlmeAssocReqAction() sanity check failed. BUG!!!!!! \n")); *pCurrState = APCLI_ASSOC_IDLE; ApCliCtrlMsg.Status = MLME_INVALID_FORMAT; MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); } return; }
/* ========================================================================== 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) { UCHAR Addr2[MAC_ADDR_LEN]; CHAR Ssid[MAX_LEN_OF_SSID]; UCHAR SsidLen; 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; BOOLEAN bRequestRssi=FALSE; #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 */ if (! PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, Ssid, &SsidLen, &bRequestRssi)) return; for(apidx=0; apidx<pAd->ApCfg.BssidNum; apidx++) { RSNIe = IE_WPA; if ((pAd->ApCfg.MBSSID[apidx].MSSIDDev != NULL) && !(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].MSSIDDev))) { /* the interface is down, so we can not send probe response */ continue; } PhyMode = pAd->ApCfg.MBSSID[apidx].PhyMode; if (((SsidLen == 0) && (! pAd->ApCfg.MBSSID[apidx].bHideSsid)) || #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 */ ((SsidLen == 32) && MAC_ADDR_EQUAL(Addr3, pAd->ApCfg.MBSSID[apidx].Bssid) && (pAd->ApCfg.MBSSID[apidx].bHideSsid == 0)) || #endif /* WSC_AP_SUPPORT */ ((SsidLen == pAd->ApCfg.MBSSID[apidx].SsidLen) && NdisEqualMemory(Ssid, pAd->ApCfg.MBSSID[apidx].Ssid, (ULONG) SsidLen))) ; else continue; /* check next BSS */ #ifdef RT_CFG80211_SUPPORT if (pAd->Cfg80211RegisterProbeReqFrame) { UINT32 freq; MAP_CHANNEL_ID_TO_KHZ(Elem->Channel, freq); freq /= 1000; CFG80211OS_RxMgmt(pAd->ApCfg.MBSSID[apidx].MSSIDDev, freq, (PUCHAR)Elem->Msg, Elem->MsgLen); } #endif /* RT_CFG80211_SUPPORT */ #ifdef BAND_STEERING BND_STRG_CHECK_CONNECTION_REQ( pAd, NULL, Addr2, Elem->MsgType, Elem->Rssi0, Elem->Rssi1, Elem->Rssi2, NULL); #endif /* BAND_STEERING */ /* allocate and send out ProbeRsp frame */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) return; MgtMacHeaderInit(pAd, &ProbeRspHdr, SUBTYPE_PROBE_RSP, 0, Addr2, pAd->ApCfg.MBSSID[apidx].Bssid); if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; #ifdef WAPI_SUPPORT else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWAICERT) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWAIPSK)) RSNIe = IE_WAPI; #endif /* WAPI_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, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, 1, &SsidIe, 1, &pAd->ApCfg.MBSSID[apidx].SsidLen, pAd->ApCfg.MBSSID[apidx].SsidLen, pAd->ApCfg.MBSSID[apidx].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 DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, AddHtLen, NewExtLen; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif #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 */ 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 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, 1, &AddHtInfoIe, 1, &AddHtLen, sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, 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 */ 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 (pAd->ApCfg.MBSSID[apidx].AuthMode < Ndis802_11AuthModeWPA) ; /* enough information */ else if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &RSNIe, 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSN_IE[0], 1, &RSNIe2, 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1], pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1], pAd->ApCfg.MBSSID[apidx].RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &RSNIe, 1, &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0], pAd->ApCfg.MBSSID[apidx].RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } /* add WMM IE here */ if (pAd->ApCfg.MBSSID[apidx].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], &pAd->ApCfg.MBSSID[apidx].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; } #ifdef AP_QLOAD_SUPPORT if (pAd->FlgQloadEnable != 0) { FrameLen += QBSS_LoadElementAppend(pAd, pOutBuffer+FrameLen); } #endif /* AP_QLOAD_SUPPORT */ /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { 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 { ULONG TmpLen = 0; 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 */ os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #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) && (pAd->ApCfg.MBSSID[apidx].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].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 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 (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.AvgRssi0; RalinkSpecificIe[7] = (UCHAR)pEntry->RssiSample.AvgRssi1; RalinkSpecificIe[8] = (UCHAR)pEntry->RssiSample.AvgRssi2; } } #endif /* RSSI_FEEDBACK */ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 9, RalinkSpecificIe, 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; #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); FrameLen += TmpLen; } #endif /* DOT11_N_SUPPORT */ } #endif /* A_BAND_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 DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (pAd->ApCfg.MBSSID[apidx].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, pAd->CommonCfg.vht_max_mcs_cap); } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ #ifdef WSC_AP_SUPPORT /* for windows 7 logo test */ if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pAd->ApCfg.MBSSID[apidx].IEEE8021X == FALSE) && #endif /* DOT1X_SUPPORT */ (pAd->ApCfg.MBSSID[apidx].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 ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode > WSC_DISABLE) && (pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.ValueLen)) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pOutBuffer+FrameLen, &WscTmpLen, pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.ValueLen, pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.Value, END_OF_ARGS); FrameLen += WscTmpLen; } #endif /* WSC_AP_SUPPORT */ #ifdef RT_CFG80211_SUPPORT if (pAd->ApCfg.MBSSID[apidx].ProbRespExtraIeLen != 0) { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, pAd->ApCfg.MBSSID[apidx].ProbRespExtraIeLen, &pAd->ApCfg.MBSSID[apidx].ProbRespExtraIe[0], END_OF_ARGS); FrameLen += TmpLen; } #endif /* RT_CFG80211_SUPPORT */ /* 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); }
static int scan_active(RTMP_ADAPTER *pAd, UCHAR OpMode, UCHAR ScanType) { UCHAR *frm_buf = NULL; HEADER_802_11 Hdr80211; ULONG FrameLen = 0; UCHAR SsidLen = 0; if (MlmeAllocateMemory(pAd, &frm_buf) != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n")); #ifdef CONFIG_AP_SUPPORT if (OpMode == OPMODE_AP) pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; #endif /* CONFIG_AP_SUPPORT */ return FALSE; } #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 if (ScanType == SCAN_2040_BSS_COEXIST) { DBGPRINT(RT_DEBUG_INFO, ("SYNC - SCAN_2040_BSS_COEXIST !! Prepare to send Probe Request\n")); } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ /* There is no need to send broadcast probe request if active scan is in effect.*/ SsidLen = 0; if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) ) SsidLen = pAd->MlmeAux.SsidLen; { #ifdef CONFIG_AP_SUPPORT /*IF_DEV_CONFIG_OPMODE_ON_AP(pAd) */ if (OpMode == OPMODE_AP) { MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, pAd->ApCfg.MBSSID[0].Bssid); } #endif /* CONFIG_AP_SUPPORT */ MakeOutgoingFrame(frm_buf, &FrameLen, sizeof(HEADER_802_11), &Hdr80211, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, &pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, END_OF_ARGS); if (pAd->CommonCfg.ExtRateLen) { ULONG Tmp; MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += Tmp; } } #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { ULONG Tmp; UCHAR HtLen; UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; #endif if (pAd->bBroadComHT == TRUE) { HtLen = pAd->MlmeAux.HtCapabilityLen + 4; #ifdef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); *(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(frm_buf + FrameLen, &Tmp, 1, &WpaIe, 1, &HtLen, 4, &BROADCOM[0], pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, END_OF_ARGS); #else MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &WpaIe, 1, &HtLen, 4, &BROADCOM[0], pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, END_OF_ARGS); #endif /* RT_BIG_ENDIAN */ } else { HtLen = sizeof(HT_CAPABILITY_IE); #ifdef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE); *(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(frm_buf + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, END_OF_ARGS); #else MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &pAd->CommonCfg.HtCapability, END_OF_ARGS); #endif /* RT_BIG_ENDIAN */ } FrameLen += Tmp; #ifdef DOT11N_DRAFT3 if ((pAd->MlmeAux.Channel <= 14) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) { ULONG Tmp; HtLen = 1; MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &ExtHtCapIe, 1, &HtLen, 1, &pAd->CommonCfg.BSSCoexist2040.word, END_OF_ARGS); FrameLen += Tmp; } #endif /* DOT11N_DRAFT3 */ } #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->MlmeAux.Channel > 14)) { FrameLen += build_vht_ies(pAd, (UCHAR *)(frm_buf + FrameLen), SUBTYPE_PROBE_REQ); } #endif /* DOT11_VHT_AC */ MiniportMMRequest(pAd, 0, frm_buf, FrameLen); MlmeFreeMemory(pAd, frm_buf); return TRUE; }
/* ========================================================================== Description: Pre-build a BEACON frame in the shared memory ========================================================================== */ VOID APMakeBssBeacon(RTMP_ADAPTER *pAd, INT apidx) { UCHAR DsLen = 1, SsidLen; HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; ULONG FrameLen = 0; PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; UCHAR *ptr; UINT i; UINT32 longValue, reg_base; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ UCHAR PhyMode, SupRateLen; UINT8 TXWISize = pAd->chipCap.TXWISize; if(!BeaconTransmitRequired(pAd, apidx, &pAd->ApCfg.MBSSID[apidx])) return; PhyMode = pAd->ApCfg.MBSSID[apidx].PhyMode; if (pAd->ApCfg.MBSSID[apidx].bHideSsid) SsidLen = 0; else SsidLen = pAd->ApCfg.MBSSID[apidx].SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pAd->ApCfg.MBSSID[apidx].Bssid); /* for update framelen to TxWI later. */ SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == WMODE_B) SupRateLen = 4; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pAd->ApCfg.MBSSID[apidx].CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->ApCfg.MBSSID[apidx].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)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR *TmpFrame = NULL; UCHAR CountryIe = IE_COUNTRY; 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 */ /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11_N_SUPPORT /* AP Channel Report */ { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; /* 802.11n D2.0 Annex J, USA regulatory class 32, channel set 1~7 class 33, channel set 5-11 */ UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; /*sizeof(rclass32); */ if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, FrameLen, PID_MGMT, 0, 0,IFS_HTTXOP, FALSE, &BeaconTransmit); /* step 6. move BEACON TXD and frame content to on-chip memory */ ptr = (PUCHAR)&pAd->BeaconTxWI; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); #endif reg_base = pAd->BeaconOffset[pAd->ApCfg.MBSSID[apidx].BcnBufIdx]; for (i=0; i < TXWISize; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } /* update BEACON frame content. start right after the TXWI field. */ ptr = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif reg_base = pAd->BeaconOffset[pAd->ApCfg.MBSSID[apidx].BcnBufIdx] + TXWISize; for (i= 0; i< FrameLen; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon = (UCHAR)FrameLen; pAd->ApCfg.MBSSID[apidx].CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; } /* ========================================================================== Description: Update the BEACON frame in the shared memory. Because TIM IE is variable length. other IEs after TIM has to shift and total frame length may change for each BEACON period. Output: pAd->ApCfg.MBSSID[apidx].CapabilityInfo pAd->ApCfg.ErpIeContent ========================================================================== */ VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx) { UCHAR *pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; UCHAR *ptr; ULONG FrameLen = pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon; ULONG UpdatePos = pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; UCHAR ID_1B, TimFirst, TimLast, *pTim; MULTISSID_STRUCT *pMbss; COMMON_CONFIG *pComCfg; UCHAR PhyMode; BOOLEAN bHasWpsIE = FALSE; UINT i; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ pMbss = &pAd->ApCfg.MBSSID[apidx]; pComCfg = &pAd->CommonCfg; PhyMode = pMbss->PhyMode; if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; /* step 1 - update BEACON's Capability */ ptr = pBeaconFrame + pMbss->CapabilityInfoLocationInBeacon; *ptr = (UCHAR)(pMbss->CapabilityInfo & 0x00ff); *(ptr+1) = (UCHAR)((pMbss->CapabilityInfo & 0xff00) >> 8); /* step 2 - update TIM IE TODO: enlarge TIM bitmap to support up to 64 STAs TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time */ ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; *ptr = IE_TIM; *(ptr + 2) = pAd->ApCfg.DtimCount; *(ptr + 3) = pAd->ApCfg.DtimPeriod; /* find the smallest AID (PS mode) */ TimFirst = 0; /* record first TIM byte != 0x00 */ TimLast = 0; /* record last TIM byte != 0x00 */ pTim = pMbss->TimBitmaps; for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++) { /* get the TIM indicating PS packets for 8 stations */ UCHAR tim_1B = pTim[ID_1B]; if (ID_1B == 0) tim_1B &= 0xfe; /* skip bit0 bc/mc */ if (tim_1B == 0) continue; /* find next 1B */ if (TimFirst == 0) TimFirst = ID_1B; TimLast = ID_1B; } /* fill TIM content to beacon buffer */ if (TimFirst & 0x01) TimFirst --; /* find the even offset byte */ *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */ *(ptr + 4) = TimFirst; for(i=TimFirst; i<=TimLast; i++) *(ptr + 5 + i - TimFirst) = pTim[i]; /* bit0 means backlogged mcast/bcast */ if (pAd->ApCfg.DtimCount == 0) *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); /* adjust BEACON length according to the new TIM */ FrameLen += (2 + *(ptr+1)); #ifdef HOSTAPD_SUPPORT if ( pAd->ApCfg.MBSSID[apidx].HostapdWPS && (pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen)) bHasWpsIE = TRUE; #endif #ifdef WSC_AP_SUPPORT /* add Simple Config Information Element */ if (((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode >= 1) && (pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen))) { bHasWpsIE = TRUE; } #endif /* WSC_AP_SUPPORT */ if (bHasWpsIE) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen, pAd->ApCfg.MBSSID[apidx].WscIEBeacon.Value, END_OF_ARGS); FrameLen += WscTmpLen; } #ifdef WSC_AP_SUPPORT if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pAd->ApCfg.MBSSID[apidx].IEEE8021X == FALSE) && #endif /* DOT1X_SUPPORT */ (pAd->ApCfg.MBSSID[apidx].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 TempLen = 0; UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TempLen, 7, PROVISION_SERVICE_IE, END_OF_ARGS); FrameLen += TempLen; } #endif /* WSC_AP_SUPPORT */ /* Update ERP */ if ((pComCfg->ExtRateLen) && (PhyMode != WMODE_B)) { /* fill ERP IE */ ptr = (UCHAR *)pBeaconFrame + FrameLen; /* pTxD->DataByteCnt; */ *ptr = IE_ERP; *(ptr + 1) = 1; *(ptr + 2) = pAd->ApCfg.ErpIeContent; FrameLen += 3; } #ifdef A_BAND_SUPPORT /* fill up Channel Switch Announcement Element */ if ((pComCfg->Channel > 14) && (pComCfg->bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { ptr = pBeaconFrame + FrameLen; *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; *(ptr + 1) = 3; *(ptr + 2) = 1; *(ptr + 3) = pComCfg->Channel; *(ptr + 4) = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); ptr += 5; FrameLen += 5; #ifdef DOT11_N_SUPPORT /* Extended Channel Switch Announcement Element */ if (pComCfg->bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); NdisMoveMemory(ptr, &HtExtChannelSwitchIe, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE)); ptr += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); FrameLen += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); } #endif /* DOT11_N_SUPPORT */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT /* step 5. Update HT. Since some fields might change in the same BSS. */ if (WMODE_CAP_N(PhyMode) && (pMbss->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; /*UCHAR i; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; /* USHORT b2lTmp, b2lTmp2; // no use */ #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &pComCfg->HtCapability, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->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) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if ((pComCfg->Channel <= 14) && (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11N_DRAFT3 */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pComCfg->Channel > 14)) { int _len = build_vht_ies(pAd, (UCHAR *)(pBeaconFrame+FrameLen), SUBTYPE_BEACON); FrameLen += _len; } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ #if defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_SUPPORT) /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen, infoPos; PUCHAR pInfo; UCHAR extInfoLen; BOOLEAN bNeedAppendExtIE = FALSE; EXT_CAP_INFO_ELEMENT extCapInfo; 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 (WMODE_CAP_N(PhyMode) && (pComCfg->Channel <= 14) && (pMbss->DesiredHtPhyInfo.bHtEnable) && (pComCfg->bBssCoexEnable == TRUE) ) { extCapInfo.BssCoexistMgmtSupport = 1; } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ pInfo = (PUCHAR)(&extCapInfo); for (infoPos = 0; infoPos < extInfoLen; infoPos++) { if (pInfo[infoPos] != 0) { bNeedAppendExtIE = TRUE; break; } } if (bNeedAppendExtIE == TRUE) { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* defined(DOT11N_DRAFT3) || defined(DOT11V_WNM_SUPPORT) */ if ((pMbss->AuthMode == Ndis802_11AuthModeWPA) || (pMbss->AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((pMbss->AuthMode == Ndis802_11AuthModeWPA2) || (pMbss->AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; #ifdef WAPI_SUPPORT else if ((pMbss->AuthMode == Ndis802_11AuthModeWAICERT) || (pMbss->AuthMode == Ndis802_11AuthModeWAIPSK)) RSNIe = IE_WAPI; #endif /* WAPI_SUPPORT */ /* Append RSN_IE when WPA OR WPAPSK, */ if ((pMbss->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pMbss->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], 1, &RSNIe2, 1, &pMbss->RSNIE_Len[1], pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else if (pMbss->AuthMode >= Ndis802_11AuthModeWPA) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } /* add WMM IE here */ if (pMbss->bWmmCapable) { ULONG TmpLen; UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; UINT8 AIFSN[4]; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->UapsdInfo); #endif /* UAPSD_SUPPORT */ NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); 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 */ (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(pBeaconFrame+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->FlgQloadEnable != 0) { FrameLen += QBSS_LoadElementAppend(pAd, pBeaconFrame+FrameLen); } #endif /* AP_QLOAD_SUPPORT */ #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 (((pComCfg->Channel > 14) && pComCfg->bIEEE80211H == TRUE) ) { ULONG TmpLen; UINT8 PwrConstraintIE = IE_POWER_CONSTRAINT; UINT8 PwrConstraintLen = 1; UINT8 PwrConstraint = pComCfg->PwrConstraint; /* prepare power constraint IE */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &PwrConstraintIE, 1, &PwrConstraintLen, 1, &PwrConstraint, END_OF_ARGS); FrameLen += TmpLen; } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (pMbss->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; /*UCHAR i; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; /* USHORT b2lTmp, b2lTmp2;*/ /* no use */ #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->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(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pComCfg->HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->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) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = HtLen1 + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pComCfg->bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pComCfg->bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pComCfg->bRdg) RalinkSpecificIe[5] |= 0x4; #endif /* DOT11_N_SUPPORT */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* step 6. Since FrameLen may change, update TXWI. */ #ifdef A_BAND_SUPPORT if (pAd->CommonCfg.Channel > 14) { BeaconTransmit.field.MODE = MODE_OFDM; BeaconTransmit.field.MCS = MCS_RATE_6; } #endif /* A_BAND_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen, PID_MGMT, QID_MGMT, 0, IFS_HTTXOP, FALSE, &BeaconTransmit); /* step 7. move BEACON TXWI and frame content to on-chip memory */ RT28xx_UpdateBeaconToAsic(pAd, apidx, FrameLen, UpdatePos); }
/* ======================================================================== Routine Description: Caller ensures we has 802.11n support. Calls at setting HT from AP/STASetinformation Arguments: pAd - Pointer to our adapter phymode - ======================================================================== */ VOID RTMPSetIndividualHT( IN RTMP_ADAPTER *pAd, IN UCHAR apidx) { RT_PHY_INFO *pDesired_ht_phy = NULL; UCHAR TxStream = pAd->CommonCfg.TxStream; UCHAR DesiredMcs = MCS_AUTO; UCHAR encrypt_mode = Ndis802_11EncryptionDisabled; do { #ifdef CONFIG_AP_SUPPORT #ifdef APCLI_SUPPORT if (apidx >= MIN_NET_DEVICE_FOR_APCLI) { UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI; if (idx < MAX_APCLI_NUM) { pDesired_ht_phy = &pAd->ApCfg.ApCliTab[idx].DesiredHtPhyInfo; DesiredMcs = pAd->ApCfg.ApCliTab[idx].DesiredTransmitSetting.field.MCS; encrypt_mode = pAd->ApCfg.ApCliTab[idx].WepStatus; pAd->ApCfg.ApCliTab[idx].bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; break; } else { DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid idx(%d)\n", 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) { pDesired_ht_phy = &pAd->WdsTab.WdsEntry[idx].DesiredHtPhyInfo; DesiredMcs = pAd->WdsTab.WdsEntry[idx].DesiredTransmitSetting.field.MCS; /*encrypt_mode = pAd->WdsTab.WdsEntry[idx].WepStatus;*/ pAd->WdsTab.WdsEntry[idx].bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; break; } else { DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); return; } } #endif /* WDS_SUPPORT */ if ((apidx < pAd->ApCfg.BssidNum) && (apidx < MAX_MBSSID_NUM(pAd)) && (apidx < HW_BEACON_MAX_NUM)) { pDesired_ht_phy = &pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo; DesiredMcs = pAd->ApCfg.MBSSID[apidx].DesiredTransmitSetting.field.MCS; encrypt_mode = pAd->ApCfg.MBSSID[apidx].WepStatus; pAd->ApCfg.MBSSID[apidx].bWmmCapable = TRUE; pAd->ApCfg.MBSSID[apidx].bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE; break; } DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); return; } #endif /* CONFIG_AP_SUPPORT */ } while (FALSE); if (pDesired_ht_phy == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); return; } RTMPZeroMemory(pDesired_ht_phy, sizeof(RT_PHY_INFO)); DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetIndividualHT : Desired MCS = %d\n", DesiredMcs)); /* Check the validity of MCS */ if ((TxStream == 1) && ((DesiredMcs >= MCS_8) && (DesiredMcs <= MCS_15))) { DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS(%d) is invalid in 1S, reset it as MCS_7\n", DesiredMcs)); DesiredMcs = MCS_7; } if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_20) && (DesiredMcs == MCS_32)) { DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS_32 is only supported in 40-MHz, reset it as MCS_0\n")); DesiredMcs = MCS_0; } /* WFA recommend to restrict the encryption type in 11n-HT mode. So, the WEP and TKIP are not allowed in HT rate. */ if (pAd->CommonCfg.HT_DisallowTKIP && IS_INVALID_HT_SECURITY(encrypt_mode)) { DBGPRINT(RT_DEBUG_WARN, ("%s : Use legacy rate in WEP/TKIP encryption mode (apidx=%d)\n", __FUNCTION__, apidx)); return; } if (pAd->CommonCfg.HT_Disable) { DBGPRINT(RT_DEBUG_TRACE, ("%s : HT is disabled\n", __FUNCTION__)); return; } pDesired_ht_phy->bHtEnable = TRUE; /* Decide desired Tx MCS*/ switch (TxStream) { case 1: if (DesiredMcs == MCS_AUTO) pDesired_ht_phy->MCSSet[0]= 0xff; else if (DesiredMcs <= MCS_7) pDesired_ht_phy->MCSSet[0]= 1<<DesiredMcs; break; case 2: if (DesiredMcs == MCS_AUTO) { pDesired_ht_phy->MCSSet[0]= 0xff; pDesired_ht_phy->MCSSet[1]= 0xff; } else if (DesiredMcs <= MCS_15) { ULONG mode; mode = DesiredMcs / 8; if (mode < 2) pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); } break; case 3: if (DesiredMcs == MCS_AUTO) { /* MCS0 ~ MCS23, 3 bytes */ pDesired_ht_phy->MCSSet[0]= 0xff; pDesired_ht_phy->MCSSet[1]= 0xff; pDesired_ht_phy->MCSSet[2]= 0xff; } else if (DesiredMcs <= MCS_23) { ULONG mode; mode = DesiredMcs / 8; if (mode < 3) pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); } break; } if(pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_40) { if (DesiredMcs == MCS_AUTO || DesiredMcs == MCS_32) pDesired_ht_phy->MCSSet[4] = 0x1; } /* update HT Rate setting */ if (pAd->OpMode == OPMODE_STA) { MlmeUpdateHtTxRates(pAd, BSS0); } else MlmeUpdateHtTxRates(pAd, apidx); #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) { pDesired_ht_phy->bVhtEnable = TRUE; rtmp_set_vht(pAd, pDesired_ht_phy); } #endif /* DOT11_VHT_AC */ }
/* ========================================================================== Description: Pre-build a BEACON frame in the shared memory ========================================================================== */ VOID APMakeBssBeacon(RTMP_ADAPTER *pAd, INT apidx) { BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; UCHAR DsLen = 1, SsidLen; HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; ULONG FrameLen = 0; UCHAR *pBeaconFrame, *tmac_info; #if defined(DOT11_N_SUPPORT) && defined(DOT11K_RRM_SUPPORT) UINT i; #endif HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at HT rate. */ UCHAR PhyMode, SupRateLen; UINT8 TXWISize = pAd->chipCap.TXWISize; UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; if (pMbss->bcn_buf.BeaconPkt == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid BeaconPkt for MBSS[%d]\n", __FUNCTION__, apidx)); return; } #ifdef MT_MAC if (pAd->chipCap.hif_type == HIF_MT) { return; //Carter, 20140306 for MT7603, merge MakeAllBeacon into UpdateAllBeacon } #endif tmac_info = (UCHAR *)GET_OS_PKT_DATAPTR(pMbss->bcn_buf.BeaconPkt); if (pAd->chipCap.hif_type == HIF_MT) { pBeaconFrame = (UCHAR *)(tmac_info + tx_hw_hdr_len); } else { pBeaconFrame = (UCHAR *)(tmac_info + TXWISize); } PhyMode = pMbss->wdev.PhyMode; SsidLen = (pMbss->bHideSsid) ? 0 : pMbss->SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pMbss->wdev.if_addr, pMbss->wdev.bssid); /* for update framelen to TxWI later. */ SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == WMODE_B) SupRateLen = 4; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pMbss->CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pMbss->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)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR *TmpFrame = NULL; UCHAR CountryIe = IE_COUNTRY; 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 */ /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11_N_SUPPORT /* AP Channel Report */ { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; /* 802.11n D2.0 Annex J, USA regulatory class 32, channel set 1~7 class 33, channel set 5-11 */ UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; /*sizeof(rclass32); */ if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ BeaconTransmit.word = 0; write_tmac_info_beacon(pAd, apidx, tmac_info, &BeaconTransmit, FrameLen); /* step 6. move BEACON TXD and frame content to on-chip memory */ asic_write_bcn_buf(pAd, tmac_info, TXWISize, pBeaconFrame, FrameLen, pAd->BeaconOffset[pMbss->bcn_buf.BcnBufIdx]); pMbss->TimIELocationInBeacon = (UCHAR)FrameLen; pMbss->bcn_buf.cap_ie_pos = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; //pMbss->bcn_buf.bcn_state = BCN_TX_IDLE; //+++Add by shiang for debug //---Add by shiang for debug } /* ========================================================================== Description: Update the BEACON frame in the shared memory. Because TIM IE is variable length. other IEs after TIM has to shift and total frame length may change for each BEACON period. Output: pAd->ApCfg.MBSSID[apidx].CapabilityInfo pAd->ApCfg.ErpIeContent ========================================================================== */ VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx) { UCHAR *pBeaconFrame, *tmac_info; UCHAR *ptr; ULONG FrameLen; ULONG UpdatePos = 0; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; UCHAR ID_1B, TimFirst, TimLast, *pTim; BSS_STRUCT *pMbss; COMMON_CONFIG *pComCfg; BOOLEAN bHasWpsIE = FALSE; UINT i; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ struct wifi_dev *wdev; UCHAR tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; UINT8 TXWISize = pAd->chipCap.TXWISize; UCHAR DsLen = 1, SsidLen; HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; UCHAR PhyMode = 0, SupRateLen; pComCfg = &pAd->CommonCfg; pMbss = &pAd->ApCfg.MBSSID[apidx]; wdev = &pMbss->wdev; if (!pMbss || !pMbss->bcn_buf.BeaconPkt) return; tmac_info = (UCHAR *)GET_OS_PKT_DATAPTR(pMbss->bcn_buf.BeaconPkt); if (pAd->chipCap.hif_type == HIF_MT) { pBeaconFrame = (UCHAR *)(tmac_info + tx_hw_hdr_len); } else { pBeaconFrame = (UCHAR *)(tmac_info + TXWISize); } if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; #ifdef CONFIG_FPGA_MODE if (pAd->fpga_ctl.fpga_on & 0x1) { if (pAd->fpga_ctl.tx_kick_cnt == 0) return; } #ifdef MT_MAC if (pAd->fpga_ctl.no_bcn) { DBGPRINT(RT_DEBUG_OFF, ("%s():Bcn Tx is blocked!\n", __FUNCTION__)); return; } #endif /* MT_MAC */ #endif /* CONFIG_FPGA_MODE */ #ifdef MT_MAC if (pAd->chipCap.hif_type == HIF_MT) { BOOLEAN is_pretbtt_int = FALSE; #ifdef RTMP_PCI_SUPPORT USHORT FreeNum = GET_BCNRING_FREENO(pAd); if (FreeNum <= 0) { DBGPRINT(RT_DEBUG_ERROR, ("%s()=>BSS%d:BcnRing FreeNum is not enough!\n", __FUNCTION__, apidx)); return; } #endif /* RTMP_PCI_SUPPORT */ if (pMbss->bcn_buf.bcn_state != BCN_TX_IDLE) { #ifdef RTMP_PCI_SUPPORT APCheckBcnQHandler(pAd, apidx, &is_pretbtt_int); #endif /* RTMP_PCI_SUPPORT */ if (is_pretbtt_int == FALSE) return; } PhyMode = pMbss->wdev.PhyMode; SsidLen = (pMbss->bHideSsid) ? 0 : pMbss->SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pMbss->wdev.if_addr, pMbss->wdev.bssid); /* for update framelen to TxWI later. */ SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == WMODE_B) SupRateLen = 4; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pMbss->CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pMbss->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)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR *TmpFrame = NULL; UCHAR CountryIe = IE_COUNTRY; 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 */ /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11_N_SUPPORT /* AP Channel Report */ { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; /* 802.11n D2.0 Annex J, USA regulatory class 32, channel set 1~7 class 33, channel set 5-11 */ UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; /*sizeof(rclass32); */ if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ BeaconTransmit.word = 0; //write_tmac_info_beacon(pAd, apidx, tmac_info, &BeaconTransmit, FrameLen); pMbss->TimIELocationInBeacon = (UCHAR)FrameLen; pMbss->bcn_buf.cap_ie_pos = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; FrameLen = UpdatePos = pMbss->TimIELocationInBeacon; PhyMode = wdev->PhyMode; } #endif /* MT_MAC */ /* step 1 - update BEACON's Capability */ ptr = pBeaconFrame + pMbss->bcn_buf.cap_ie_pos; //prevent little/big endian issue. and let asic_write_bcn_buf() handle it. *(UINT16 *)ptr = pMbss->CapabilityInfo; /* step 2 - update TIM IE TODO: enlarge TIM bitmap to support up to 64 STAs TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time */ ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; *ptr = IE_TIM; *(ptr + 2) = pAd->ApCfg.DtimCount; *(ptr + 3) = pAd->ApCfg.DtimPeriod; /* find the smallest AID (PS mode) */ TimFirst = 0; /* record first TIM byte != 0x00 */ TimLast = 0; /* record last TIM byte != 0x00 */ pTim = pMbss->TimBitmaps; for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++) { /* get the TIM indicating PS packets for 8 stations */ UCHAR tim_1B = pTim[ID_1B]; if (ID_1B == 0) tim_1B &= 0xfe; /* skip bit0 bc/mc */ if (tim_1B == 0) continue; /* find next 1B */ if (TimFirst == 0) TimFirst = ID_1B; TimLast = ID_1B; } /* fill TIM content to beacon buffer */ if (TimFirst & 0x01) TimFirst --; /* find the even offset byte */ *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */ *(ptr + 4) = TimFirst; for(i=TimFirst; i<=TimLast; i++) *(ptr + 5 + i - TimFirst) = pTim[i]; /* bit0 means backlogged mcast/bcast */ if (pAd->ApCfg.DtimCount == 0) *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); /* adjust BEACON length according to the new TIM */ FrameLen += (2 + *(ptr+1)); /* move RSN IE from below to here for Ralink Win7 v3.0.0.61 version parse beacon issue. */ /* sync the order with BRCM's AP. */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; #ifdef WAPI_SUPPORT else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) RSNIe = IE_WAPI; #endif /* WAPI_SUPPORT */ /* Append RSN_IE when WPA OR WPAPSK, */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], 1, &RSNIe2, 1, &pMbss->RSNIE_Len[1], pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else if (wdev->AuthMode >= Ndis802_11AuthModeWPA) { ULONG TmpLen; { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } } #ifdef HOSTAPD_SUPPORT if (pMbss->HostapdWPS && (pMbss->WscIEBeacon.ValueLen)) bHasWpsIE = TRUE; #endif #ifdef WSC_AP_SUPPORT /* add Simple Config Information Element */ if (((pMbss->WscControl.WscConfMode >= 1) && (pMbss->WscIEBeacon.ValueLen))) bHasWpsIE = TRUE; #endif /* WSC_AP_SUPPORT */ if (bHasWpsIE) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, pMbss->WscIEBeacon.ValueLen, pMbss->WscIEBeacon.Value, END_OF_ARGS); FrameLen += WscTmpLen; } #ifdef WSC_AP_SUPPORT if ((pMbss->WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pMbss->wdev.IEEE8021X == FALSE) && #endif /* DOT1X_SUPPORT */ (pMbss->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 TempLen = 0; UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TempLen, 7, PROVISION_SERVICE_IE, END_OF_ARGS); FrameLen += TempLen; } #endif /* WSC_AP_SUPPORT */ /* Update ERP */ if ((pComCfg->ExtRateLen) && (PhyMode != WMODE_B)) { /* fill ERP IE */ ptr = (UCHAR *)pBeaconFrame + FrameLen; /* pTxD->DataByteCnt; */ *ptr = IE_ERP; *(ptr + 1) = 1; *(ptr + 2) = pAd->ApCfg.ErpIeContent; FrameLen += 3; } #ifdef A_BAND_SUPPORT /* fill up Channel Switch Announcement Element */ if ((pComCfg->Channel > 14) && (pComCfg->bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { ptr = pBeaconFrame + FrameLen; *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; *(ptr + 1) = 3; *(ptr + 2) = 1; *(ptr + 3) = pComCfg->Channel; *(ptr + 4) = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); ptr += 5; FrameLen += 5; #ifdef DOT11_N_SUPPORT /* Extended Channel Switch Announcement Element */ if (pComCfg->bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); NdisMoveMemory(ptr, &HtExtChannelSwitchIe, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE)); ptr += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); FrameLen += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); } #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode)) { INT tp_len, wb_len = 0; UCHAR *ch_sw_wrapper; VHT_TXPWR_ENV_IE txpwr_env; *ptr = IE_CH_SWITCH_WRAPPER; ch_sw_wrapper = (UCHAR *)(ptr + 1); // reserve for length ptr += 2; // skip len if (pComCfg->RegTransmitSetting.field.BW == BW_40) { WIDE_BW_CH_SWITCH_ELEMENT wb_info; *ptr = IE_WIDE_BW_CH_SWITCH; *(ptr + 1) = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); ptr += 2; NdisZeroMemory(&wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); if (pComCfg->vht_bw == VHT_BW_2040) wb_info.new_ch_width = 0; else wb_info.new_ch_width = 1; if (pComCfg->vht_bw == VHT_BW_80) { wb_info.center_freq_1 = vht_cent_ch_freq(pAd, pComCfg->Channel); wb_info.center_freq_2 = 0; } NdisMoveMemory(ptr, &wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); wb_len = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); ptr += wb_len; wb_len += 2; } *ptr = IE_VHT_TXPWR_ENV; NdisZeroMemory(&txpwr_env, sizeof(VHT_TXPWR_ENV_IE)); tp_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); *(ptr + 1) = tp_len; ptr += 2; NdisMoveMemory(ptr, &txpwr_env, tp_len); ptr += tp_len; tp_len += 2; *ch_sw_wrapper = wb_len + tp_len; FrameLen += (2 + wb_len + tp_len); } #endif /* DOT11_VHT_AC */ #endif /* DOT11_N_SUPPORT */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT /* step 5. Update HT. Since some fields might change in the same BSS. */ if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; /*UCHAR i; */ HT_CAPABILITY_IE HtCapabilityTmp; #ifdef RT_BIG_ENDIAN ADD_HT_INFO_IE addHTInfoTmp; /* USHORT b2lTmp, b2lTmp2; // no use */ #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); #ifndef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); HtCapabilityTmp.HtCapInfo.ChannelWidth = pComCfg->AddHTInfo.AddHtInfo.RecomWidth; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); HtCapabilityTmp.HtCapInfo.ChannelWidth = pComCfg->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) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if ((pComCfg->Channel <= 14) && (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11N_DRAFT3 */ #ifdef CONFIG_HOTSPOT if (pMbss->HotSpotCtrl.HotSpotEnable) { ULONG TmpLen; /* Indication element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.HSIndicationIELen, pMbss->HotSpotCtrl.HSIndicationIE, END_OF_ARGS); FrameLen += TmpLen; /* Interworking element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.InterWorkingIELen, pMbss->HotSpotCtrl.InterWorkingIE, END_OF_ARGS); FrameLen += TmpLen; /* Advertisement Protocol element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.AdvertisementProtoIELen, pMbss->HotSpotCtrl.AdvertisementProtoIE, END_OF_ARGS); FrameLen += TmpLen; /* Roaming Consortium element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.RoamingConsortiumIELen, pMbss->HotSpotCtrl.RoamingConsortiumIE, END_OF_ARGS); FrameLen += TmpLen; /* P2P element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.P2PIELen, pMbss->HotSpotCtrl.P2PIE, END_OF_ARGS); FrameLen += TmpLen; } #endif #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pComCfg->Channel > 14)) { int _len = build_vht_ies(pAd, (UCHAR *)(pBeaconFrame+FrameLen), SUBTYPE_BEACON); FrameLen += _len; } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen, infoPos; PUCHAR pInfo; UCHAR extInfoLen; BOOLEAN bNeedAppendExtIE = FALSE; EXT_CAP_INFO_ELEMENT extCapInfo; 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 (WMODE_CAP_N(PhyMode) && (pComCfg->Channel <= 14) && (pMbss->wdev.DesiredHtPhyInfo.bHtEnable) && (pComCfg->bBssCoexEnable == TRUE) ) { extCapInfo.BssCoexistMgmtSupport = 1; } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ #ifdef CONFIG_DOT11V_WNM if (pMbss->WNMCtrl.ProxyARPEnable) extCapInfo.proxy_arp = 1; #endif /* CONFIG_DOT11V_WNM */ #ifdef CONFIG_HOTSPOT if (pMbss->HotSpotCtrl.HotSpotEnable) extCapInfo.interworking = 1; #endif /* CONFIG_HOTSPOT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pAd->CommonCfg.Channel > 14)) extCapInfo.operating_mode_notification = 1; #endif /* DOT11_VHT_AC */ pInfo = (PUCHAR)(&extCapInfo); for (infoPos = 0; infoPos < extInfoLen; infoPos++) { if (pInfo[infoPos] != 0) { bNeedAppendExtIE = TRUE; break; } } if (bNeedAppendExtIE == TRUE) { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #ifdef WFA_VHT_PF if (pAd->force_vht_op_mode == TRUE) { ULONG TmpLen; UCHAR operating_ie = IE_OPERATING_MODE_NOTIFY, operating_len = 1; OPERATING_MODE operating_mode; operating_mode.rx_nss_type = 0; operating_mode.rx_nss = (pAd->vht_pf_op_ss - 1); operating_mode.ch_width = pAd->vht_pf_op_bw; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &operating_ie, 1, &operating_len, 1, &operating_mode, END_OF_ARGS); FrameLen += TmpLen; } #endif /* WFA_VHT_PF */ /* add WMM IE here */ if (pMbss->wdev.bWmmCapable) { ULONG TmpLen; UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; UINT8 AIFSN[4]; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->wdev.UapsdInfo); #endif /* UAPSD_SUPPORT */ NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); 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 */ (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(pBeaconFrame+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->phy_ctrl.FlgQloadEnable != 0) { FrameLen += QBSS_LoadElementAppend(pAd, pBeaconFrame+FrameLen); } #endif /* AP_QLOAD_SUPPORT */ #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 (((pComCfg->Channel > 14) && pComCfg->bIEEE80211H == TRUE) ) { ULONG TmpLen; UINT8 PwrConstraintIE = IE_POWER_CONSTRAINT; UINT8 PwrConstraintLen = 1; UINT8 PwrConstraint = pComCfg->PwrConstraint; /* prepare power constraint IE */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &PwrConstraintIE, 1, &PwrConstraintLen, 1, &PwrConstraint, 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(pBeaconFrame+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 */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->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(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pComCfg->HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->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) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = HtLen1 + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pComCfg->bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pComCfg->bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pComCfg->bRdg) RalinkSpecificIe[5] |= 0x4; #endif /* DOT11_N_SUPPORT */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* step 6. Since FrameLen may change, update TXWI. */ #ifdef A_BAND_SUPPORT if (pAd->CommonCfg.Channel > 14) { BeaconTransmit.field.MODE = MODE_OFDM; BeaconTransmit.field.MCS = MCS_RATE_6; } #endif /* A_BAND_SUPPORT */ write_tmac_info_beacon(pAd, apidx, tmac_info, &BeaconTransmit, FrameLen); /* step 6. move BEACON TXD and frame content to on-chip memory */ asic_write_bcn_buf(pAd, tmac_info, TXWISize, pBeaconFrame, FrameLen, pAd->BeaconOffset[pMbss->bcn_buf.BcnBufIdx]); #if defined(MT7603_FPGA) || defined(MT7628_FPGA) // TODO: shiang-7603, we use different way to update beacon packet! if (0)//IS_MT7603(pAd)) { hex_dump("Beacon_TMAC_INFO", (UCHAR *)tmac_info, tx_hw_hdr_len); dump_tmac_info(pAd, tmac_info); hex_dump("BeaconFrame", pBeaconFrame, FrameLen); } #endif /* MT7603_FPGA */ /* step 7. move BEACON TXWI and frame content to on-chip memory */ RT28xx_UpdateBeaconToAsic(pAd, apidx, FrameLen, UpdatePos); { UINT32 Lowpart, Highpart; AsicGetTsfTime(pAd, &Highpart, &Lowpart); pMbss->WriteBcnDoneTime[pMbss->timer_loop] = Lowpart; } }
/* ========================================================================== Description: ========================================================================== */ static VOID ApCliEnqueueProbeRequest( IN PRTMP_ADAPTER pAd, IN UCHAR SsidLen, IN PCHAR Ssid, IN PCHAR Bssid, IN USHORT ifIndex) { NDIS_STATUS NState; PUCHAR pOutBuffer; ULONG FrameLen = 0; HEADER_802_11 Hdr80211; UCHAR SsidIe = IE_SSID; UCHAR SupRateIe = IE_SUPP_RATES; UCHAR ssidLen; CHAR ssid[MAX_LEN_OF_SSID]; APCLI_STRUCT *pApCliEntry = NULL; BOOLEAN bHasWscIe = FALSE; UCHAR PhyMode = pAd->CommonCfg.PhyMode; DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n")); if (ifIndex >= MAX_APCLI_NUM) return; pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; #ifdef APCLI_AUTO_BW_SUPPORT PhyMode = pApCliEntry->wdev.PhyMode; #endif /* APCLI_AUTO_BW_SUPPORT */ NState = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ if(NState != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("EnqueueProbeRequest() allocate memory fail\n")); return; } else { if(MAC_ADDR_EQUAL(Bssid, ZERO_MAC_ADDR)) ApCliMgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR, ifIndex); else ApCliMgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, Bssid, Bssid, ifIndex); ssidLen = SsidLen; NdisZeroMemory(ssid, MAX_LEN_OF_SSID); NdisMoveMemory(ssid, Ssid, ssidLen); /* this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse */ MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &Hdr80211, 1, &SsidIe, 1, &ssidLen, ssidLen, ssid, 1, &SupRateIe, 1, &pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.SupRate, END_OF_ARGS); /* Add the extended rate IE */ if (pApCliEntry->MlmeAux.ExtRateLen != 0) { ULONG tmp; MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 1, &ExtRateIe, 1, &pApCliEntry->MlmeAux.ExtRateLen, pApCliEntry->MlmeAux.ExtRateLen, pApCliEntry->MlmeAux.ExtRate, END_OF_ARGS); FrameLen += tmp; } #ifdef SMART_MESH SMART_MESH_INSERT_IE(pApCliEntry->SmartMeshCfg, pOutBuffer, FrameLen, SM_IE_PROBE_REQ); #endif /* SMART_MESH */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pAd->CommonCfg.Channel > 14)) { build_vht_cap_ie(pAd, (UCHAR *)&pApCliEntry->MlmeAux.vht_cap); pApCliEntry->MlmeAux.vht_cap_len = sizeof(VHT_CAP_IE); FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer + FrameLen), SUBTYPE_PROBE_REQ); } #endif /* DOT11_VHT_AC */ #ifdef WSC_AP_SUPPORT /* Append WSC information in probe request if WSC state is running */ if ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger)) { bHasWscIe = TRUE; } #ifdef WSC_V2_SUPPORT else if (pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscV2Info.bEnableWpsV2) { bHasWscIe = TRUE; } #endif /* WSC_V2_SUPPORT */ #ifdef WSC_AP_SUPPORT #ifdef SMART_MESH_HIDDEN_WPS if(pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg.bSupportHiddenWPS) bHasWscIe = FALSE; #endif /* SMART_MESH_HIDDEN_WPS */ #endif /* WSC_AP_SUPPORT */ if (bHasWscIe) { UCHAR /* WscBuf[256], */ WscIeLen = 0; UCHAR *WscBuf = NULL; ULONG WscTmpLen = 0; /* allocate memory */ os_alloc_mem(NULL, (UCHAR **)&WscBuf, 512); if (WscBuf != NULL) { NdisZeroMemory(WscBuf, 512); WscBuildProbeReqIE(pAd, STA_MODE, WscBuf, &WscIeLen); MakeOutgoingFrame(pOutBuffer + FrameLen, &WscTmpLen, WscIeLen, WscBuf, END_OF_ARGS); FrameLen += WscTmpLen; os_free_mem(NULL, WscBuf); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #endif /*WSC_AP_SUPPORT*/ #ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && (pAd->cfg80211_ctrl.ExtraIeLen != 0)) { ULONG ExtraIeTmpLen = 0; MakeOutgoingFrame(pOutBuffer + FrameLen, &ExtraIeTmpLen, pAd->cfg80211_ctrl.ExtraIeLen, pAd->cfg80211_ctrl.pExtraIe, END_OF_ARGS); FrameLen += ExtraIeTmpLen; } #endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE*/ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } return; }
/* ========================================================================== Description: Update the BEACON frame in the shared memory. Because TIM IE is variable length. other IEs after TIM has to shift and total frame length may change for each BEACON period. Output: pAd->ApCfg.MBSSID[apidx].CapabilityInfo pAd->ApCfg.ErpIeContent ========================================================================== */ VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx) { UCHAR *pBeaconFrame; UCHAR *ptr; ULONG FrameLen; ULONG UpdatePos; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; UCHAR ID_1B, TimFirst, TimLast, *pTim; MULTISSID_STRUCT *pMbss; COMMON_CONFIG *pComCfg; UCHAR PhyMode; BOOLEAN bHasWpsIE = FALSE; UINT i; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ struct wifi_dev *wdev; #ifdef SPECIFIC_TX_POWER_SUPPORT UCHAR TxPwrAdj = 0; #endif /* SPECIFIC_TX_POWER_SUPPORT */ pComCfg = &pAd->CommonCfg; pMbss = &pAd->ApCfg.MBSSID[apidx]; wdev = &pMbss->wdev; pBeaconFrame = (UCHAR *)&pMbss->BeaconBuf[0]; FrameLen = UpdatePos = pMbss->TimIELocationInBeacon; PhyMode = wdev->PhyMode; if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; /* step 1 - update BEACON's Capability */ ptr = pBeaconFrame + pMbss->CapabilityInfoLocationInBeacon; *ptr = (UCHAR)(pMbss->CapabilityInfo & 0x00ff); *(ptr+1) = (UCHAR)((pMbss->CapabilityInfo & 0xff00) >> 8); /* step 2 - update TIM IE TODO: enlarge TIM bitmap to support up to 64 STAs TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time */ ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; *ptr = IE_TIM; *(ptr + 2) = pAd->ApCfg.DtimCount; *(ptr + 3) = pAd->ApCfg.DtimPeriod; /* find the smallest AID (PS mode) */ TimFirst = 0; /* record first TIM byte != 0x00 */ TimLast = 0; /* record last TIM byte != 0x00 */ pTim = pMbss->TimBitmaps; for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++) { /* get the TIM indicating PS packets for 8 stations */ UCHAR tim_1B = pTim[ID_1B]; if (ID_1B == 0) tim_1B &= 0xfe; /* skip bit0 bc/mc */ if (tim_1B == 0) continue; /* find next 1B */ if (TimFirst == 0) TimFirst = ID_1B; TimLast = ID_1B; } /* fill TIM content to beacon buffer */ if (TimFirst & 0x01) TimFirst --; /* find the even offset byte */ *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */ *(ptr + 4) = TimFirst; for(i=TimFirst; i<=TimLast; i++) *(ptr + 5 + i - TimFirst) = pTim[i]; /* bit0 means backlogged mcast/bcast */ if (pAd->ApCfg.DtimCount == 0) *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); /* adjust BEACON length according to the new TIM */ FrameLen += (2 + *(ptr+1)); /* move RSN IE from below to here for Ralink Win7 v3.0.0.61 version parse beacon issue. */ /* sync the order with BRCM's AP. */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; #ifdef WAPI_SUPPORT else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) RSNIe = IE_WAPI; #endif /* WAPI_SUPPORT */ /* Append RSN_IE when WPA OR WPAPSK, */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], 1, &RSNIe2, 1, &pMbss->RSNIE_Len[1], pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else if (wdev->AuthMode >= Ndis802_11AuthModeWPA) { ULONG TmpLen; #ifdef CONFIG_HOTSPOT_R2 extern UCHAR OSEN_IE[]; extern UCHAR OSEN_IELEN; if ((pMbss->HotSpotCtrl.HotSpotEnable == 0) && (pMbss->HotSpotCtrl.bASANEnable == 1) && (pMbss->wdev.AuthMode == Ndis802_11AuthModeWPA2)) { RSNIe = IE_WPA; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &OSEN_IELEN, OSEN_IELEN, OSEN_IE, END_OF_ARGS); FrameLen += TmpLen; } else #endif /* CONFIG_HOTSPOT_R2 */ { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } } #ifdef HOSTAPD_SUPPORT if (pMbss->HostapdWPS && (pMbss->WscIEBeacon.ValueLen)) bHasWpsIE = TRUE; #endif #ifdef WSC_AP_SUPPORT /* add Simple Config Information Element */ if (((pMbss->WscControl.WscConfMode >= 1) && (pMbss->WscIEBeacon.ValueLen))) bHasWpsIE = TRUE; #endif /* WSC_AP_SUPPORT */ if (bHasWpsIE) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, pMbss->WscIEBeacon.ValueLen, pMbss->WscIEBeacon.Value, END_OF_ARGS); FrameLen += WscTmpLen; } #ifdef WSC_AP_SUPPORT if ((pMbss->WscControl.WscConfMode != WSC_DISABLE) && #ifdef DOT1X_SUPPORT (pMbss->wdev.IEEE8021X == FALSE) && #endif /* DOT1X_SUPPORT */ (pMbss->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 TempLen = 0; UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TempLen, 7, PROVISION_SERVICE_IE, END_OF_ARGS); FrameLen += TempLen; } #endif /* WSC_AP_SUPPORT */ /* Update ERP */ if ((pComCfg->ExtRateLen) && (PhyMode != WMODE_B)) { /* fill ERP IE */ ptr = (UCHAR *)pBeaconFrame + FrameLen; /* pTxD->DataByteCnt; */ *ptr = IE_ERP; *(ptr + 1) = 1; *(ptr + 2) = pAd->ApCfg.ErpIeContent; FrameLen += 3; } #ifdef A_BAND_SUPPORT /* fill up Channel Switch Announcement Element */ if (((pComCfg->Channel > 14) && (pComCfg->bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) #ifdef CUSTOMER_DCC_FEATURE || (pComCfg->channelSwitch.CHSWMode == CHANNEL_SWITCHING_MODE) #endif ) { ptr = pBeaconFrame + FrameLen; *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; *(ptr + 1) = 3; *(ptr + 2) = 1; *(ptr + 3) = pComCfg->Channel; #ifdef CUSTOMER_DCC_FEATURE if(pComCfg->channelSwitch.CHSWMode == CHANNEL_SWITCHING_MODE) *(ptr + 4) = (pComCfg->channelSwitch.CHSWPeriod - pComCfg->channelSwitch.CHSWCount); else #endif *(ptr + 4) = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); ptr += 5; FrameLen += 5; #ifdef DOT11_N_SUPPORT /* Extended Channel Switch Announcement Element */ if (pComCfg->bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); NdisMoveMemory(ptr, &HtExtChannelSwitchIe, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE)); ptr += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); FrameLen += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); } #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode)) { INT tp_len, wb_len = 0; UCHAR *ch_sw_wrapper; VHT_TXPWR_ENV_IE txpwr_env; *ptr = IE_CH_SWITCH_WRAPPER; ch_sw_wrapper = (UCHAR *)(ptr + 1); // reserve for length ptr += 2; // skip len if (pComCfg->RegTransmitSetting.field.BW == BW_40) { WIDE_BW_CH_SWITCH_ELEMENT wb_info; *ptr = IE_WIDE_BW_CH_SWITCH; //*(ptr + 1) = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); *(ptr + 1) = 3; ptr += 2; NdisZeroMemory(&wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); if (pComCfg->vht_bw == VHT_BW_2040) wb_info.new_ch_width = 0; else wb_info.new_ch_width = 1; if (pComCfg->vht_bw == VHT_BW_80) { wb_info.center_freq_1 = vht_cent_ch_freq(pAd, pComCfg->Channel); wb_info.center_freq_2 = 0; } NdisMoveMemory(ptr, &wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); //wb_len = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); wb_len = 3; ptr += wb_len; wb_len += 2; } *ptr = IE_VHT_TXPWR_ENV; NdisZeroMemory(&txpwr_env, sizeof(VHT_TXPWR_ENV_IE)); tp_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); *(ptr + 1) = tp_len; ptr += 2; NdisMoveMemory(ptr, &txpwr_env, tp_len); ptr += tp_len; tp_len += 2; *ch_sw_wrapper = wb_len + tp_len; FrameLen += (2 + wb_len + tp_len); } #endif /* DOT11_VHT_AC */ #endif /* DOT11_N_SUPPORT */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT /* step 5. Update HT. Since some fields might change in the same BSS. */ if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; /*UCHAR i; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; /* USHORT b2lTmp, b2lTmp2; // no use */ #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &pComCfg->HtCapability, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->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) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if ((pComCfg->Channel <= 14) && (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11N_DRAFT3 */ #ifdef CONFIG_HOTSPOT if (pMbss->HotSpotCtrl.HotSpotEnable) { ULONG TmpLen; /* Indication element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.HSIndicationIELen, pMbss->HotSpotCtrl.HSIndicationIE, END_OF_ARGS); FrameLen += TmpLen; /* Interworking element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.InterWorkingIELen, pMbss->HotSpotCtrl.InterWorkingIE, END_OF_ARGS); FrameLen += TmpLen; /* Advertisement Protocol element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.AdvertisementProtoIELen, pMbss->HotSpotCtrl.AdvertisementProtoIE, END_OF_ARGS); FrameLen += TmpLen; /* Roaming Consortium element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.RoamingConsortiumIELen, pMbss->HotSpotCtrl.RoamingConsortiumIE, END_OF_ARGS); FrameLen += TmpLen; /* P2P element */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, pMbss->HotSpotCtrl.P2PIELen, pMbss->HotSpotCtrl.P2PIE, END_OF_ARGS); FrameLen += TmpLen; } #endif #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pComCfg->Channel > 14)) { int _len = build_vht_ies(pAd, (UCHAR *)(pBeaconFrame+FrameLen), SUBTYPE_BEACON); FrameLen += _len; } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen, infoPos; PUCHAR pInfo; UCHAR extInfoLen; BOOLEAN bNeedAppendExtIE = FALSE; EXT_CAP_INFO_ELEMENT extCapInfo; 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 (WMODE_CAP_N(PhyMode) && (pComCfg->Channel <= 14) && (pMbss->wdev.DesiredHtPhyInfo.bHtEnable) && (pComCfg->bBssCoexEnable == TRUE) ) { extCapInfo.BssCoexistMgmtSupport = 1; } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ #ifdef CONFIG_DOT11V_WNM if (pMbss->WNMCtrl.ProxyARPEnable) extCapInfo.proxy_arp = 1; #ifdef CONFIG_HOTSPOT_R2 if (pMbss->WNMCtrl.WNMNotifyEnable) extCapInfo.wnm_notification = 1; if (pMbss->HotSpotCtrl.QosMapEnable) extCapInfo.qosmap= 1; #endif /* CONFIG_HOTSPOT_R2 */ #endif /* CONFIG_DOT11V_WNM */ #ifdef CONFIG_HOTSPOT if (pMbss->HotSpotCtrl.HotSpotEnable) extCapInfo.interworking = 1; #endif /* CONFIG_HOTSPOT */ #ifdef DOT11V_WNM_SUPPORT if (IS_BSS_TRANSIT_MANMT_SUPPORT(pAd, apidx)) { extCapInfo.BssTransitionManmt = 1; } if (IS_WNMDMS_SUPPORT(pAd, apidx)) { extCapInfo.DMSSupport = 1; } #endif /* DOT11V_WNM_SUPPORT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pAd->CommonCfg.Channel > 14)) extCapInfo.operating_mode_notification = 1; #endif /* DOT11_VHT_AC */ pInfo = (PUCHAR)(&extCapInfo); for (infoPos = 0; infoPos < extInfoLen; infoPos++) { if (pInfo[infoPos] != 0) { bNeedAppendExtIE = TRUE; break; } } if (bNeedAppendExtIE == TRUE) { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #ifdef WFA_VHT_PF if (pAd->force_vht_op_mode == TRUE) { ULONG TmpLen; UCHAR operating_ie = IE_OPERATING_MODE_NOTIFY, operating_len = 1; OPERATING_MODE operating_mode; operating_mode.rx_nss_type = 0; operating_mode.rx_nss = (pAd->vht_pf_op_ss - 1); operating_mode.ch_width = pAd->vht_pf_op_bw; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &operating_ie, 1, &operating_len, 1, &operating_mode, END_OF_ARGS); FrameLen += TmpLen; } #endif /* WFA_VHT_PF */ /* add WMM IE here */ if (pMbss->wdev.bWmmCapable) { ULONG TmpLen; UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; UINT8 AIFSN[4]; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->UapsdInfo); #endif /* UAPSD_SUPPORT */ NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); 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 */ (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(pBeaconFrame+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->phy_ctrl.FlgQloadEnable != 0) { #ifdef CONFIG_HOTSPOT_R2 if (pMbss->HotSpotCtrl.QLoadTestEnable == 1) FrameLen += QBSS_LoadElementAppend_HSTEST(pAd, pBeaconFrame+FrameLen, apidx); else if (pMbss->HotSpotCtrl.QLoadTestEnable == 0) #endif FrameLen += QBSS_LoadElementAppend(pAd, pBeaconFrame+FrameLen); } #endif /* AP_QLOAD_SUPPORT */ #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 (((pComCfg->Channel > 14) && pComCfg->bIEEE80211H == TRUE) #ifdef DOT11K_RRM_SUPPORT || IS_RRM_ENABLE(pAd, apidx) #endif /* DOT11K_RRM_SUPPORT */ ) { ULONG TmpLen; UINT8 PwrConstraintIE = IE_POWER_CONSTRAINT; UINT8 PwrConstraintLen = 1; UINT8 PwrConstraint = pComCfg->PwrConstraint; /* prepare power constraint IE */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &PwrConstraintIE, 1, &PwrConstraintLen, 1, &PwrConstraint, 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(pBeaconFrame+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 */ #ifdef DOT11K_RRM_SUPPORT if (IS_RRM_ENABLE(pAd, apidx)) { PRRM_QUIET_CB pQuietCB = &pMbss->RrmCfg.QuietCB; RRM_InsertQuietIE(pAd, pBeaconFrame+FrameLen, &FrameLen, pQuietCB->QuietCnt ,pQuietCB->QuietPeriod, pQuietCB->QuietDuration, pQuietCB->QuietOffset); #ifndef APPLE_11K_IOT /* Insert BSS AC Access Delay IE. */ RRM_InsertBssACDelayIE(pAd, pBeaconFrame+FrameLen, &FrameLen); /* Insert BSS Available Access Capacity IE. */ RRM_InsertBssAvailableACIE(pAd, pBeaconFrame+FrameLen, &FrameLen); #endif /* !APPLE_11K_IOT */ } #endif /* DOT11K_RRM_SUPPORT */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->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(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pComCfg->HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->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) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = HtLen1 + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pComCfg->bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pComCfg->bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pComCfg->bRdg) RalinkSpecificIe[5] |= 0x4; #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (pComCfg->b256QAM_2G && WMODE_2G_ONLY(pComCfg->PhyMode)) RalinkSpecificIe[5] |= 0x8; #endif /* DOT11_VHT_AC */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* add Mediatek-specific IE here */ { ULONG TmpLen = 0; UCHAR MediatekSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0xe7, 0x00, 0x00, 0x00, 0x00}; #ifdef DOT11_VHT_AC if (pComCfg->b256QAM_2G && WMODE_2G_ONLY(pComCfg->PhyMode)) MediatekSpecificIe[5] |= 0x8; #endif /* DOT11_VHT_AC */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 9, MediatekSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* step 6. Since FrameLen may change, update TXWI. */ #ifdef A_BAND_SUPPORT if (pAd->CommonCfg.Channel > 14) { BeaconTransmit.field.MODE = MODE_OFDM; BeaconTransmit.field.MCS = MCS_RATE_6; } #endif /* A_BAND_SUPPORT */ #ifdef SPECIFIC_TX_POWER_SUPPORT /* Specific Power for Long-Range Beacon */ if ((pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && (BeaconTransmit.field.MODE == MODE_CCK)*/) { TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; } #endif /* SPECIFIC_TX_POWER_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, RESERVED_WCID, FrameLen, PID_MGMT, 0 /*QID_MGMT*/, 0, IFS_HTTXOP, &BeaconTransmit); #ifdef SPECIFIC_TX_POWER_SUPPORT #ifdef RTMP_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RTMP)) pAd->BeaconTxWI.TXWI_O.TxPwrAdj = TxPwrAdj; #endif /* RTMP_MAC */ #ifdef RLT_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RLT)) pAd->BeaconTxWI.TXWI_N.TxPwrAdj = TxPwrAdj; #endif /* RLT_MAC */ #endif /* SPECIFIC_TX_POWER_SUPPORT */ /* step 7. move BEACON TXWI and frame content to on-chip memory */ RT28xx_UpdateBeaconToAsic(pAd, apidx, FrameLen, UpdatePos); #ifdef CUSTOMER_DCC_FEATURE { HTTRANSMIT_SETTING HTSetting; UINT32 Index; MULTISSID_STRUCT *pMbss = NULL; NdisZeroMemory(&HTSetting, sizeof(HTTRANSMIT_SETTING)); HTSetting.field.MODE = BeaconTransmit.field.MODE; HTSetting.field.BW = BeaconTransmit.field.BW; HTSetting.field.ShortGI = BeaconTransmit.field.ShortGI; HTSetting.field.MCS = BeaconTransmit.field.MCS; if ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev != NULL) && (RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].wdev.if_dev))) { pMbss = &pAd->ApCfg.MBSSID[apidx]; GetMultShiftFactorIndex(HTSetting, &Index); RTMPCalculateAPTxRxActivityTime(pAd, Index, FrameLen, pMbss, NULL); } } #endif }
/* ======================================================================== Routine Description: Caller ensures we has 802.11n support. Calls at setting HT from AP/STASetinformation Arguments: pAd - Pointer to our adapter phymode - ======================================================================== */ VOID RTMPSetIndividualHT(struct rtmp_adapter *pAd, u8 apidx) { RT_PHY_INFO *pDesired_ht_phy = NULL; u8 TxStream = pAd->CommonCfg.TxStream; u8 DesiredMcs = MCS_AUTO; u8 encrypt_mode = Ndis802_11EncryptionDisabled; struct rtmp_wifi_dev *wdev; do { #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { if ((apidx < pAd->ApCfg.BssidNum) && (apidx < MAX_MBSSID_NUM(pAd)) && (apidx < HW_BEACON_MAX_NUM)) { wdev = &pAd->ApCfg.MBSSID[apidx].wdev; pDesired_ht_phy = &wdev->DesiredHtPhyInfo; DesiredMcs = wdev->DesiredTransmitSetting.field.MCS; #ifdef WFA_VHT_PF // TODO: Sigma, this code segment used to work around for Sigma Automation! if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (DesiredMcs != MCS_AUTO)) { DesiredMcs += ((TxStream - 1) << 4); pAd->ApCfg.MBSSID[apidx].DesiredTransmitSetting.field.FixedTxMode = FIXED_TXMODE_VHT; RT_CfgSetAutoFallBack(pAd, "0"); } else { RT_CfgSetAutoFallBack(pAd, "1"); } #endif /* WFA_VHT_PF */ encrypt_mode = wdev->WepStatus; pAd->ApCfg.MBSSID[apidx].wdev.bWmmCapable = true; wdev->bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? true : false; break; } DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); return; } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { wdev = &pAd->StaCfg.wdev; pDesired_ht_phy = &wdev->DesiredHtPhyInfo; DesiredMcs = wdev->DesiredTransmitSetting.field.MCS; encrypt_mode = wdev->WepStatus; break; } #endif /* CONFIG_STA_SUPPORT */ } while (false); if (pDesired_ht_phy == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx)); return; } RTMPZeroMemory(pDesired_ht_phy, sizeof(RT_PHY_INFO)); DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetIndividualHT : Desired MCS = %d\n", DesiredMcs)); /* Check the validity of MCS */ if ((TxStream == 1) && ((DesiredMcs >= MCS_8) && (DesiredMcs <= MCS_15))) { DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS(%d) is invalid in 1S, reset it as MCS_7\n", DesiredMcs)); DesiredMcs = MCS_7; } if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_20) && (DesiredMcs == MCS_32)) { DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS_32 is only supported in 40-MHz, reset it as MCS_0\n")); DesiredMcs = MCS_0; } #ifdef CONFIG_STA_SUPPORT if ((pAd->OpMode == OPMODE_STA) && (pAd->StaCfg.BssType == BSS_INFRA) && (apidx == MIN_NET_DEVICE_FOR_MBSSID)) ; else #endif /* CONFIG_STA_SUPPORT */ /* WFA recommend to restrict the encryption type in 11n-HT mode. So, the WEP and TKIP are not allowed in HT rate. */ if (pAd->CommonCfg.HT_DisallowTKIP && IS_INVALID_HT_SECURITY(encrypt_mode)) { #ifdef CONFIG_STA_SUPPORT pAd->StaCfg.bAdhocN = false; #endif /* CONFIG_STA_SUPPORT */ DBGPRINT(RT_DEBUG_WARN, ("%s : Use legacy rate in WEP/TKIP encryption mode (apidx=%d)\n", __FUNCTION__, apidx)); return; } if (pAd->CommonCfg.HT_Disable) { #ifdef CONFIG_STA_SUPPORT pAd->StaCfg.bAdhocN = false; #endif /* CONFIG_STA_SUPPORT */ DBGPRINT(RT_DEBUG_TRACE, ("%s : HT is disabled\n", __FUNCTION__)); return; } pDesired_ht_phy->bHtEnable = true; /* Decide desired Tx MCS*/ switch (TxStream) { case 1: if (DesiredMcs == MCS_AUTO) pDesired_ht_phy->MCSSet[0]= 0xff; else if (DesiredMcs <= MCS_7) pDesired_ht_phy->MCSSet[0]= 1<<DesiredMcs; break; case 2: if (DesiredMcs == MCS_AUTO) { pDesired_ht_phy->MCSSet[0]= 0xff; pDesired_ht_phy->MCSSet[1]= 0xff; } else if (DesiredMcs <= MCS_15) { ULONG mode; mode = DesiredMcs / 8; if (mode < 2) pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); } break; case 3: if (DesiredMcs == MCS_AUTO) { /* MCS0 ~ MCS23, 3 bytes */ pDesired_ht_phy->MCSSet[0]= 0xff; pDesired_ht_phy->MCSSet[1]= 0xff; pDesired_ht_phy->MCSSet[2]= 0xff; } else if (DesiredMcs <= MCS_23) { ULONG mode; mode = DesiredMcs / 8; if (mode < 3) pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8)); } break; } if(pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_40) { if (DesiredMcs == MCS_AUTO || DesiredMcs == MCS_32) pDesired_ht_phy->MCSSet[4] = 0x1; } /* update HT Rate setting */ if (pAd->OpMode == OPMODE_STA) { MlmeUpdateHtTxRates(pAd, BSS0); } else MlmeUpdateHtTxRates(pAd, apidx); if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) { pDesired_ht_phy->bVhtEnable = true; rtmp_set_vht(pAd, pDesired_ht_phy); } }
/* ========================================================================== Description: peer sends assoc rsp back Parameters: Elme - MLME message containing the received frame ========================================================================== */ static VOID ApCliPeerAssocRspAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { BOOLEAN Cancelled; USHORT CapabilityInfo, Status, Aid; UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; UCHAR Addr2[MAC_ADDR_LEN]; EDCA_PARM EdcaParm; UCHAR CkipFlag; APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; HT_CAPABILITY_IE HtCapability; ADD_HT_INFO_IE AddHtInfo; /* AP might use this additional ht info IE */ UCHAR HtCapabilityLen; UCHAR AddHtInfoLen; UCHAR NewExtChannelOffset = 0xff; USHORT ifIndex = (USHORT)(Elem->Priv); ULONG *pCurrState = NULL; #ifdef DOT11_VHT_AC PAPCLI_STRUCT pApCliEntry = NULL; #endif /* DOT11_VHT_AC */ #ifdef MAC_REPEATER_SUPPORT UCHAR CliIdx = 0xFF; #endif /* MAC_REPEATER_SUPPORT */ IE_LISTS *ie_list = NULL; if ((ifIndex >= MAX_APCLI_NUM) #ifdef MAC_REPEATER_SUPPORT && (ifIndex < 64) #endif /* MAC_REPEATER_SUPPORT */ ) return; #ifdef MAC_REPEATER_SUPPORT if (ifIndex >= 64) { CliIdx = ((ifIndex - 64) % 16); ifIndex = ((ifIndex - 64) / 16); pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AssocCurrState; } else #endif /* MAC_REPEATER_SUPPORT */ pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; #ifdef DOT11_VHT_AC pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; #endif /* DOT11_VHT_AC */ os_alloc_mem(pAd, (UCHAR **)&ie_list, sizeof(IE_LISTS)); if (ie_list == NULL) { DBGPRINT(RT_DEBUG_OFF, ("%s():mem alloc failed!\n", __FUNCTION__)); return; } NdisZeroMemory((UCHAR *)ie_list, sizeof(IE_LISTS)); if (ApCliPeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, &HtCapability, &AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag, ie_list)) { /* The frame is for me ? */ if(MAC_ADDR_EQUAL(Addr2, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid)) { DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status)); #if defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) || defined(CFG80211_MULTI_STA) /* Store the AssocRsp Frame to wpa_supplicant via CFG80211 */ NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].ResVarIEs, MAX_VIE_LEN); pAd->ApCfg.ApCliTab[ifIndex].ResVarIELen = 0; PFRAME_802_11 pFrame = (PFRAME_802_11) (Elem->Msg); pAd->ApCfg.ApCliTab[ifIndex].ResVarIELen = Elem->MsgLen - 6 - sizeof (HEADER_802_11); NdisCopyMemory(pAd->ApCfg.ApCliTab[ifIndex].ResVarIEs, &pFrame->Octet[6], pAd->ApCfg.ApCliTab[ifIndex].ResVarIELen); #endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE || CFG80211_MULTI_STA */ #ifdef MAC_REPEATER_SUPPORT if (CliIdx != 0xFF) RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAssocTimer, &Cancelled); else #endif /* MAC_REPEATER_SUPPORT */ RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.ApCliAssocTimer, &Cancelled); if(Status == MLME_SUCCESS) { /* go to procedure listed on page 376 */ #ifdef MAC_REPEATER_SUPPORT if (CliIdx == 0xFF) #endif /* MAC_REPEATER_SUPPORT */ { ApCliAssocPostProc(pAd, Addr2, CapabilityInfo, ifIndex, SupRate, SupRateLen, ExtRate, ExtRateLen, &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo); #ifdef DOT11_VHT_AC RTMPZeroMemory(&pApCliEntry->MlmeAux.vht_cap, sizeof(VHT_CAP_IE)); RTMPZeroMemory(&pApCliEntry->MlmeAux.vht_op, sizeof(VHT_OP_IE)); pApCliEntry->MlmeAux.vht_cap_len = 0; pApCliEntry->MlmeAux.vht_op_len = 0; if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && ie_list->vht_cap_len && ie_list->vht_op_len) { DBGPRINT(RT_DEBUG_TRACE, ("There is vht le at Assoc Rsp ifIndex=%d vht_cap_len=%d\n", ifIndex,ie_list->vht_cap_len)); NdisMoveMemory(&pApCliEntry->MlmeAux.vht_cap, &(ie_list->vht_cap), ie_list->vht_cap_len); pApCliEntry->MlmeAux.vht_cap_len = ie_list->vht_cap_len; NdisMoveMemory(&pApCliEntry->MlmeAux.vht_op, &(ie_list->vht_op), ie_list->vht_op_len); pApCliEntry->MlmeAux.vht_op_len = ie_list->vht_op_len; } #endif /* DOT11_VHT_AC */ } ApCliCtrlMsg.Status = MLME_SUCCESS; #ifdef MAC_REPEATER_SUPPORT ApCliCtrlMsg.BssIdx = ifIndex; ApCliCtrlMsg.CliIdx = CliIdx; ifIndex = (USHORT)(Elem->Priv); #endif /* MAC_REPEATER_SUPPORT */ MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); } else { ApCliCtrlMsg.Status = Status; MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); } *pCurrState = APCLI_ASSOC_IDLE; } } else { DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliPeerAssocRspAction() sanity check fail\n")); } if (ie_list) os_free_mem(pAd, ie_list); return; }
/* ========================================================================== Description: Pre-build a BEACON frame in the shared memory ========================================================================== */ VOID APMakeBssBeacon(RTMP_ADAPTER *pAd, INT apidx) { UCHAR DsLen = 1, SsidLen; HEADER_802_11 BcnHdr; LARGE_INTEGER FakeTimestamp; ULONG FrameLen = 0; PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[apidx].BeaconBuf; UCHAR *ptr; UINT i; UINT32 longValue, reg_base; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ UCHAR PhyMode, SupRateLen; UINT8 TXWISize = pAd->chipCap.TXWISize; MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; #ifdef SPECIFIC_TX_POWER_SUPPORT UCHAR TxPwrAdj = 0; #endif /* SPECIFIC_TX_POWER_SUPPORT */ if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; PhyMode = pMbss->wdev.PhyMode; if (pMbss->bHideSsid) SsidLen = 0; else SsidLen = pMbss->SsidLen; MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pMbss->wdev.if_addr, pMbss->wdev.bssid); /* for update framelen to TxWI later. */ SupRateLen = pAd->CommonCfg.SupRateLen; if (PhyMode == WMODE_B) SupRateLen = 4; MakeOutgoingFrame(pBeaconFrame, &FrameLen, sizeof(HEADER_802_11), &BcnHdr, TIMESTAMP_LEN, &FakeTimestamp, 2, &pAd->CommonCfg.BeaconPeriod, 2, &pMbss->CapabilityInfo, 1, &SsidIe, 1, &SsidLen, SsidLen, pMbss->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)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add country IE, power constraint IE */ if (pAd->CommonCfg.bCountryFlag) { ULONG TmpLen, TmpLen2=0; UCHAR *TmpFrame = NULL; UCHAR CountryIe = IE_COUNTRY; 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 */ /* need to do the padding bit check, and concatenate it */ if ((TmpLen2%2) == 0) { UCHAR TmpLen3 = TmpLen2+4; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2+1, TmpFrame, END_OF_ARGS); } else { UCHAR TmpLen3 = TmpLen2+3; MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &CountryIe, 1, &TmpLen3, 3, pAd->CommonCfg.CountryCode, TmpLen2, TmpFrame, END_OF_ARGS); } FrameLen += TmpLen; os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #ifdef DOT11_N_SUPPORT /* AP Channel Report */ { UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; ULONG TmpLen; /* 802.11n D2.0 Annex J, USA regulatory class 32, channel set 1~7 class 33, channel set 5-11 */ UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; UCHAR rclasslen = 8; /*sizeof(rclass32); */ if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) { MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass32, 1, &APChannelReportIe, 1, &rclasslen, rclasslen, rclass33, END_OF_ARGS); FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ BeaconTransmit.word = 0; #ifdef SPECIFIC_TX_POWER_SUPPORT /* Specific Power for Long-Range Beacon */ if ((pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && (BeaconTransmit.field.MODE == MODE_CCK)*/) { TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; } #endif /* SPECIFIC_TX_POWER_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, FrameLen, PID_MGMT, 0, 0,IFS_HTTXOP, &BeaconTransmit); #ifdef SPECIFIC_TX_POWER_SUPPORT #ifdef RTMP_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RTMP)) pAd->BeaconTxWI.TXWI_O.TxPwrAdj = TxPwrAdj; #endif /* RTMP_MAC */ #ifdef RLT_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RLT)) pAd->BeaconTxWI.TXWI_N.TxPwrAdj = TxPwrAdj; #endif /* RLT_MAC */ #endif /* SPECIFIC_TX_POWER_SUPPORT */ /* step 6. move BEACON TXD and frame content to on-chip memory */ ptr = (PUCHAR)&pAd->BeaconTxWI; #ifdef RT_BIG_ENDIAN RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); #endif reg_base = pAd->BeaconOffset[pMbss->BcnBufIdx]; for (i=0; i < TXWISize; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } /* update BEACON frame content. start right after the TXWI field. */ ptr = (PUCHAR)pMbss->BeaconBuf; #ifdef RT_BIG_ENDIAN RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); #endif reg_base = pAd->BeaconOffset[pMbss->BcnBufIdx] + TXWISize; for (i= 0; i< FrameLen; i+=4) { longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); ptr += 4; } pMbss->TimIELocationInBeacon = (UCHAR)FrameLen; pMbss->CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; } /* ========================================================================== Description: Update the BEACON frame in the shared memory. Because TIM IE is variable length. other IEs after TIM has to shift and total frame length may change for each BEACON period. Output: pAd->ApCfg.MBSSID[apidx].CapabilityInfo pAd->ApCfg.ErpIeContent ========================================================================== */ VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx) { UCHAR *pBeaconFrame; UCHAR *ptr; ULONG FrameLen; ULONG UpdatePos; UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; UCHAR ID_1B, TimFirst, TimLast, *pTim; MULTISSID_STRUCT *pMbss; COMMON_CONFIG *pComCfg; UCHAR PhyMode; BOOLEAN bHasWpsIE = FALSE; UINT i; HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ struct wifi_dev *wdev; #ifdef SPECIFIC_TX_POWER_SUPPORT UCHAR TxPwrAdj = 0; #endif /* SPECIFIC_TX_POWER_SUPPORT */ pComCfg = &pAd->CommonCfg; pMbss = &pAd->ApCfg.MBSSID[apidx]; wdev = &pMbss->wdev; pBeaconFrame = (UCHAR *)&pMbss->BeaconBuf[0]; FrameLen = UpdatePos = pMbss->TimIELocationInBeacon; PhyMode = wdev->PhyMode; if(!BeaconTransmitRequired(pAd, apidx, pMbss)) return; /* step 1 - update BEACON's Capability */ ptr = pBeaconFrame + pMbss->CapabilityInfoLocationInBeacon; *ptr = (UCHAR)(pMbss->CapabilityInfo & 0x00ff); *(ptr+1) = (UCHAR)((pMbss->CapabilityInfo & 0xff00) >> 8); /* step 2 - update TIM IE TODO: enlarge TIM bitmap to support up to 64 STAs TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time */ ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; *ptr = IE_TIM; *(ptr + 2) = pAd->ApCfg.DtimCount; *(ptr + 3) = pAd->ApCfg.DtimPeriod; /* find the smallest AID (PS mode) */ TimFirst = 0; /* record first TIM byte != 0x00 */ TimLast = 0; /* record last TIM byte != 0x00 */ pTim = pMbss->TimBitmaps; for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++) { /* get the TIM indicating PS packets for 8 stations */ UCHAR tim_1B = pTim[ID_1B]; if (ID_1B == 0) tim_1B &= 0xfe; /* skip bit0 bc/mc */ if (tim_1B == 0) continue; /* find next 1B */ if (TimFirst == 0) TimFirst = ID_1B; TimLast = ID_1B; } /* fill TIM content to beacon buffer */ if (TimFirst & 0x01) TimFirst --; /* find the even offset byte */ *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */ *(ptr + 4) = TimFirst; for(i=TimFirst; i<=TimLast; i++) *(ptr + 5 + i - TimFirst) = pTim[i]; /* bit0 means backlogged mcast/bcast */ if (pAd->ApCfg.DtimCount == 0) *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); /* adjust BEACON length according to the new TIM */ FrameLen += (2 + *(ptr+1)); /* move RSN IE from below to here for Ralink Win7 v3.0.0.61 version parse beacon issue. */ /* sync the order with BRCM's AP. */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) RSNIe = IE_WPA; else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) RSNIe = IE_WPA2; /* Append RSN_IE when WPA OR WPAPSK, */ if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], 1, &RSNIe2, 1, &pMbss->RSNIE_Len[1], pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], END_OF_ARGS); FrameLen += TmpLen; } else if (wdev->AuthMode >= Ndis802_11AuthModeWPA) { ULONG TmpLen; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &RSNIe, 1, &pMbss->RSNIE_Len[0], pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } #ifdef HOSTAPD_SUPPORT if (pMbss->HostapdWPS && (pMbss->WscIEBeacon.ValueLen)) bHasWpsIE = TRUE; #endif if (bHasWpsIE) { ULONG WscTmpLen = 0; MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, pMbss->WscIEBeacon.ValueLen, pMbss->WscIEBeacon.Value, END_OF_ARGS); FrameLen += WscTmpLen; } /* Update ERP */ if ((pComCfg->ExtRateLen) && (PhyMode != WMODE_B)) { /* fill ERP IE */ ptr = (UCHAR *)pBeaconFrame + FrameLen; /* pTxD->DataByteCnt; */ *ptr = IE_ERP; *(ptr + 1) = 1; *(ptr + 2) = pAd->ApCfg.ErpIeContent; FrameLen += 3; } #ifdef A_BAND_SUPPORT /* fill up Channel Switch Announcement Element */ if ((pComCfg->Channel > 14) && (pComCfg->bIEEE80211H == 1) && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) { ptr = pBeaconFrame + FrameLen; *ptr = IE_CHANNEL_SWITCH_ANNOUNCEMENT; *(ptr + 1) = 3; *(ptr + 2) = 1; *(ptr + 3) = pComCfg->Channel; *(ptr + 4) = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); ptr += 5; FrameLen += 5; #ifdef DOT11_N_SUPPORT /* Extended Channel Switch Announcement Element */ if (pComCfg->bExtChannelSwitchAnnouncement) { HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); NdisMoveMemory(ptr, &HtExtChannelSwitchIe, sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE)); ptr += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); FrameLen += sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE); } #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode)) { INT tp_len, wb_len = 0; UCHAR *ch_sw_wrapper; VHT_TXPWR_ENV_IE txpwr_env; *ptr = IE_CH_SWITCH_WRAPPER; ch_sw_wrapper = (UCHAR *)(ptr + 1); // reserve for length ptr += 2; // skip len if (pComCfg->RegTransmitSetting.field.BW == BW_40) { WIDE_BW_CH_SWITCH_ELEMENT wb_info; *ptr = IE_WIDE_BW_CH_SWITCH; *(ptr + 1) = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); ptr += 2; NdisZeroMemory(&wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); if (pComCfg->vht_bw == VHT_BW_2040) wb_info.new_ch_width = 0; else wb_info.new_ch_width = 1; if (pComCfg->vht_bw == VHT_BW_80) { wb_info.center_freq_1 = vht_cent_ch_freq(pAd, pComCfg->Channel); wb_info.center_freq_2 = 0; } NdisMoveMemory(ptr, &wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); wb_len = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); ptr += wb_len; wb_len += 2; } *ptr = IE_VHT_TXPWR_ENV; NdisZeroMemory(&txpwr_env, sizeof(VHT_TXPWR_ENV_IE)); tp_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); *(ptr + 1) = tp_len; ptr += 2; NdisMoveMemory(ptr, &txpwr_env, tp_len); ptr += tp_len; tp_len += 2; *ch_sw_wrapper = wb_len + tp_len; FrameLen += (2 + wb_len + tp_len); } #endif /* DOT11_VHT_AC */ #endif /* DOT11_N_SUPPORT */ } #endif /* A_BAND_SUPPORT */ #ifdef DOT11_N_SUPPORT /* step 5. Update HT. Since some fields might change in the same BSS. */ if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; /*UCHAR i; */ #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; /* USHORT b2lTmp, b2lTmp2; // no use */ #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->AddHTInfo); #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &pComCfg->HtCapability, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->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) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, 1, &AddHtInfoIe, 1, &HtLen1, HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; #ifdef DOT11N_DRAFT3 /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ if ((pComCfg->Channel <= 14) && (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) { OVERLAP_BSS_SCAN_IE OverlapScanParam; ULONG TmpLen; UCHAR OverlapScanIE, ScanIELen; OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; ScanIELen = 14; OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &OverlapScanIE, 1, &ScanIELen, ScanIELen, &OverlapScanParam, END_OF_ARGS); FrameLen += TmpLen; } #endif /* DOT11N_DRAFT3 */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pComCfg->Channel > 14)) { int _len = build_vht_ies(pAd, (UCHAR *)(pBeaconFrame+FrameLen), SUBTYPE_BEACON); FrameLen += _len; } #endif /* DOT11_VHT_AC */ } #endif /* DOT11_N_SUPPORT */ /* 7.3.2.27 Extended Capabilities IE */ { ULONG TmpLen, infoPos; PUCHAR pInfo; UCHAR extInfoLen; BOOLEAN bNeedAppendExtIE = FALSE; EXT_CAP_INFO_ELEMENT extCapInfo; 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 (WMODE_CAP_N(PhyMode) && (pComCfg->Channel <= 14) && (pMbss->wdev.DesiredHtPhyInfo.bHtEnable) && (pComCfg->bBssCoexEnable == TRUE) ) { extCapInfo.BssCoexistMgmtSupport = 1; } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(PhyMode) && (pAd->CommonCfg.Channel > 14)) extCapInfo.operating_mode_notification = 1; #endif /* DOT11_VHT_AC */ pInfo = (PUCHAR)(&extCapInfo); for (infoPos = 0; infoPos < extInfoLen; infoPos++) { if (pInfo[infoPos] != 0) { bNeedAppendExtIE = TRUE; break; } } if (bNeedAppendExtIE == TRUE) { MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &ExtCapIe, 1, &extInfoLen, extInfoLen, &extCapInfo, END_OF_ARGS); FrameLen += TmpLen; } } #ifdef WFA_VHT_PF if (pAd->force_vht_op_mode == TRUE) { ULONG TmpLen; UCHAR operating_ie = IE_OPERATING_MODE_NOTIFY, operating_len = 1; OPERATING_MODE operating_mode; operating_mode.rx_nss_type = 0; operating_mode.rx_nss = (pAd->vht_pf_op_ss - 1); operating_mode.ch_width = pAd->vht_pf_op_bw; MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &operating_ie, 1, &operating_len, 1, &operating_mode, END_OF_ARGS); FrameLen += TmpLen; } #endif /* WFA_VHT_PF */ /* add WMM IE here */ if (pMbss->wdev.bWmmCapable) { ULONG TmpLen; UCHAR i; UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; UINT8 AIFSN[4]; WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; #ifdef UAPSD_SUPPORT UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->UapsdInfo); #endif /* UAPSD_SUPPORT */ NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); 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 */ (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(pBeaconFrame+FrameLen, &TmpLen, 26, WmeParmIe, END_OF_ARGS); FrameLen += TmpLen; } #ifdef AP_QLOAD_SUPPORT if (pAd->phy_ctrl.FlgQloadEnable != 0) FrameLen += QBSS_LoadElementAppend(pAd, pBeaconFrame+FrameLen); #endif /* AP_QLOAD_SUPPORT */ #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 (((pComCfg->Channel > 14) && pComCfg->bIEEE80211H == TRUE) ) { ULONG TmpLen; UINT8 PwrConstraintIE = IE_POWER_CONSTRAINT; UINT8 PwrConstraintLen = 1; UINT8 PwrConstraint = pComCfg->PwrConstraint; /* prepare power constraint IE */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 1, &PwrConstraintIE, 1, &PwrConstraintLen, 1, &PwrConstraint, 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(pBeaconFrame+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 */ #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) { ULONG TmpLen; UCHAR HtLen, HtLen1; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif /* add HT Capability IE */ HtLen = sizeof(pComCfg->HtCapability); HtLen1 = sizeof(pComCfg->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(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &pComCfg->HtCapability, END_OF_ARGS); #else NdisMoveMemory(&HtCapabilityTmp, &pComCfg->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) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); #endif /* UNALIGNMENT_SUPPORT */ MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_HTC[0], HtLen, &HtCapabilityTmp, END_OF_ARGS); #endif FrameLen += TmpLen; epigram_ie_len = HtLen1 + 4; #ifndef RT_BIG_ENDIAN MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &pComCfg->AddHTInfo, END_OF_ARGS); #else NdisMoveMemory(&addHTInfoTmp, &pComCfg->AddHTInfo, HtLen1); *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, 1, &WpaIe, 1, &epigram_ie_len, 4, &BROADCOM_AHTINFO[0], HtLen1, &addHTInfoTmp, END_OF_ARGS); #endif FrameLen += TmpLen; } } #endif /* DOT11_N_SUPPORT */ /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ { ULONG TmpLen; UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00}; if (pComCfg->bAggregationCapable) RalinkSpecificIe[5] |= 0x1; if (pComCfg->bPiggyBackCapable) RalinkSpecificIe[5] |= 0x2; #ifdef DOT11_N_SUPPORT if (pComCfg->bRdg) RalinkSpecificIe[5] |= 0x4; #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (pComCfg->b256QAM_2G && WMODE_2G_ONLY(pComCfg->PhyMode)) RalinkSpecificIe[5] |= 0x8; #endif /* DOT11_VHT_AC */ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* step 6. Since FrameLen may change, update TXWI. */ #ifdef A_BAND_SUPPORT if (pAd->CommonCfg.Channel > 14) { BeaconTransmit.field.MODE = MODE_OFDM; BeaconTransmit.field.MCS = MCS_RATE_6; } #endif /* A_BAND_SUPPORT */ #ifdef SPECIFIC_TX_POWER_SUPPORT /* Specific Power for Long-Range Beacon */ if ((pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) /* && (BeaconTransmit.field.MODE == MODE_CCK)*/) { TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; } #endif /* SPECIFIC_TX_POWER_SUPPORT */ RTMPWriteTxWI(pAd, &pAd->BeaconTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, RESERVED_WCID, FrameLen, PID_MGMT, 0 /*QID_MGMT*/, 0, IFS_HTTXOP, &BeaconTransmit); #ifdef SPECIFIC_TX_POWER_SUPPORT #ifdef RTMP_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RTMP)) pAd->BeaconTxWI.TXWI_O.TxPwrAdj = TxPwrAdj; #endif /* RTMP_MAC */ #ifdef RLT_MAC if ((IS_RT6352(pAd) || IS_MT76x2(pAd)) && (pAd->chipCap.hif_type == HIF_RLT)) pAd->BeaconTxWI.TXWI_N.TxPwrAdj = TxPwrAdj; #endif /* RLT_MAC */ #endif /* SPECIFIC_TX_POWER_SUPPORT */ /* step 7. move BEACON TXWI and frame content to on-chip memory */ RT28xx_UpdateBeaconToAsic(pAd, apidx, FrameLen, UpdatePos); }
/* ========================================================================== Description: ========================================================================== */ static VOID ApCliEnqueueProbeRequest( IN PRTMP_ADAPTER pAd, IN UCHAR SsidLen, OUT PCHAR Ssid, IN USHORT ifIndex) { NDIS_STATUS NState; PUCHAR pOutBuffer; ULONG FrameLen = 0; HEADER_802_11 Hdr80211; UCHAR SsidIe = IE_SSID; UCHAR SupRateIe = IE_SUPP_RATES; UCHAR ssidLen; CHAR ssid[MAX_LEN_OF_SSID]; APCLI_STRUCT *pApCliEntry = NULL; BOOLEAN bHasWscIe = FALSE; DBGPRINT(RT_DEBUG_TRACE, ("force out a ProbeRequest ...\n")); if (ifIndex >= MAX_APCLI_NUM) return; pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; NState = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ if(NState != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("EnqueueProbeRequest() allocate memory fail\n")); return; } else { if(MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, ZERO_MAC_ADDR)) ApCliMgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR, ifIndex); else ApCliMgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, pAd->ApCfg.ApCliTab[ifIndex].CfgApCliBssid, ifIndex); ssidLen = SsidLen; NdisZeroMemory(ssid, MAX_LEN_OF_SSID); NdisMoveMemory(ssid, Ssid, ssidLen); /* this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse */ MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &Hdr80211, 1, &SsidIe, 1, &ssidLen, ssidLen, ssid, 1, &SupRateIe, 1, &pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.SupRate, END_OF_ARGS); /* Add the extended rate IE */ if (pApCliEntry->MlmeAux.ExtRateLen != 0) { ULONG tmp; MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, 1, &ExtRateIe, 1, &pApCliEntry->MlmeAux.ExtRateLen, pApCliEntry->MlmeAux.ExtRateLen, pApCliEntry->MlmeAux.ExtRate, END_OF_ARGS); FrameLen += tmp; } #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->CommonCfg.Channel > 14)) { build_vht_cap_ie(pAd, (UCHAR *)&pApCliEntry->MlmeAux.vht_cap); pApCliEntry->MlmeAux.vht_cap_len = sizeof(VHT_CAP_IE); FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer + FrameLen), SUBTYPE_PROBE_REQ); } #endif /* DOT11_VHT_AC */ #ifdef RT_CFG80211_P2P_CONCURRENT_DEVICE if ((pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && (pAd->cfg80211_ctrl.ExtraIeLen != 0)) { ULONG ExtraIeTmpLen = 0; MakeOutgoingFrame(pOutBuffer + FrameLen, &ExtraIeTmpLen, pAd->cfg80211_ctrl.ExtraIeLen, pAd->cfg80211_ctrl.pExtraIe, END_OF_ARGS); FrameLen += ExtraIeTmpLen; } #endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE*/ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } return; }
VOID ap_cmm_peer_assoc_req_action( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem, IN BOOLEAN isReassoc) { IE_LISTS *ie_list = NULL; HEADER_802_11 AssocRspHdr; USHORT CapabilityInfoForAssocResp; USHORT StatusCode = MLME_SUCCESS; USHORT Aid; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen = 0; UCHAR MaxSupportedRate = 0; UCHAR SupRateLen, PhyMode, FlgIs11bSta; UCHAR i; MAC_TABLE_ENTRY *pEntry; #ifdef DBG UCHAR *sAssoc = isReassoc ? (PUCHAR)"ReASSOC" : (PUCHAR)"ASSOC"; #endif /* DBG */ UCHAR SubType; BOOLEAN bACLReject = FALSE; #ifdef DOT1X_SUPPORT PUINT8 pPmkid = NULL; UINT8 pmkid_count = 0; #endif /* DOT1X_SUPPORT */ MULTISSID_STRUCT *wdev; /* allocate memory */ os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(IE_LISTS)); if (ie_list == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("%s(): mem alloc failed\n", __FUNCTION__)); return; } NdisZeroMemory(ie_list, sizeof(IE_LISTS)); if (!PeerAssocReqCmmSanity(pAd, isReassoc, Elem->Msg, Elem->MsgLen, ie_list)) goto LabelOK; /* check if AP address is same as us */ /* TODO */ /* goto label_err; */ pEntry = MacTableLookup(pAd, ie_list->Addr2); if (!pEntry) { DBGPRINT(RT_DEBUG_ERROR, ("NoAuth MAC - %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(ie_list->Addr2))); goto LabelOK; } if (!VALID_MBSS(pAd, pEntry->apidx)) { DBGPRINT(RT_DEBUG_ERROR, ("%s():pEntry bounding invalid wdev(apidx=%d)\n", __FUNCTION__, pEntry->apidx)); goto LabelOK; } wdev = &pAd->ApCfg.MBSSID[pEntry->apidx]; PhyMode = wdev->PhyMode; FlgIs11bSta = 1; for(i=0; i<ie_list->SupportedRatesLen; i++) { if (((ie_list->SupportedRates[i] & 0x7F) != 2) && ((ie_list->SupportedRates[i] & 0x7F) != 4) && ((ie_list->SupportedRates[i] & 0x7F) != 11) && ((ie_list->SupportedRates[i] & 0x7F) != 22)) { FlgIs11bSta = 0; break; } } /* clear the previous Pairwise key table */ if(pEntry->Aid != 0 && (pEntry->WepStatus >= Ndis802_11Encryption2Enabled #ifdef DOT1X_SUPPORT || wdev->IEEE8021X #endif /* DOT1X_SUPPORT */ )) { /* clear GTK state */ pEntry->GTKState = REKEY_NEGOTIATING; NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); /* clear this entry as no-security mode */ AsicRemovePairwiseKeyEntry(pAd, pEntry->Aid); #ifdef DOT1X_SUPPORT /* Notify 802.1x daemon to clear this sta info */ if (pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPA2 || wdev->IEEE8021X) DOT1X_InternalCmdAction(pAd, pEntry, DOT1X_DISCONNECT_ENTRY); #endif /* DOT1X_SUPPORT */ } /* for hidden SSID sake, SSID in AssociateRequest should be fully verified */ if ((ie_list->SsidLen != wdev->SsidLen) || (NdisEqualMemory(ie_list->Ssid, wdev->Ssid, ie_list->SsidLen)==0)) goto LabelOK; /* set a flag for sending Assoc-Fail response to unwanted STA later. */ if (! ApCheckAccessControlList(pAd, ie_list->Addr2, pEntry->apidx)) bACLReject = TRUE; DBGPRINT(RT_DEBUG_TRACE, ("%s - MBSS(%d), receive %s request from %02x:%02x:%02x:%02x:%02x:%02x\n", sAssoc, pEntry->apidx, sAssoc, PRINT_MAC(ie_list->Addr2))); /* supported rates array may not be sorted. sort it and find the maximum rate */ for (i=0; i<ie_list->SupportedRatesLen; i++) { if (MaxSupportedRate < (ie_list->SupportedRates[i] & 0x7f)) MaxSupportedRate = ie_list->SupportedRates[i] & 0x7f; } /* Assign RateLen here or we will select wrong rate table in APBuildAssociation() when 11N compile option is disabled. */ pEntry->RateLen = ie_list->SupportedRatesLen; RTMPSetSupportMCS(pAd, OPMODE_AP, pEntry, ie_list->SupportedRates, ie_list->SupportedRatesLen, NULL, 0, #ifdef DOT11_VHT_AC ie_list->vht_cap_len, &ie_list->vht_cap, #endif /* DOT11_VHT_AC */ &ie_list->HTCapability, ie_list->ht_cap_len); /* 2. qualify this STA's auth_asoc status in the MAC table, decide StatusCode */ StatusCode = APBuildAssociation(pAd, pEntry, ie_list, MaxSupportedRate, &Aid); #ifdef DOT11_VHT_AC if (ie_list->vht_cap_len) { VHT_CAP_INFO *vht_cap = &ie_list->vht_cap.vht_cap; //+++Add by shiang for debug if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) { DBGPRINT(RT_DEBUG_TRACE, ("%s():Peer is VHT capable device!\n", __FUNCTION__)); //dump_vht_cap(pAd, &ie_list->vht_cap); } //---Add by shiang for debug } #endif /* DOT11_VHT_AC */ if (StatusCode == MLME_ASSOC_REJ_DATA_RATE) RTMPSendWirelessEvent(pAd, IW_STA_MODE_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0); /* 3. send Association Response */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) goto LabelOK; DBGPRINT(RT_DEBUG_TRACE, ("%s - Send %s response (Status=%d)...\n", sAssoc, sAssoc, StatusCode)); Aid |= 0xc000; /* 2 most significant bits should be ON */ SubType = isReassoc ? SUBTYPE_REASSOC_RSP : SUBTYPE_ASSOC_RSP; CapabilityInfoForAssocResp = wdev->CapabilityInfo; /*use AP's cability */ /* fail in ACL checking => send an Assoc-Fail resp. */ SupRateLen = pAd->CommonCfg.SupRateLen; /* TODO: need to check rate in support rate element, not number */ if (FlgIs11bSta == 1) SupRateLen = 4; if (bACLReject == TRUE) { MgtMacHeaderInit(pAd, &AssocRspHdr, SubType, 0, ie_list->Addr2, wdev->Bssid); StatusCode = MLME_UNSPECIFY_FAIL; MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &AssocRspHdr, 2, &CapabilityInfoForAssocResp, 2, &StatusCode, 2, &Aid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, END_OF_ARGS); MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, (PVOID) pOutBuffer); RTMPSendWirelessEvent(pAd, IW_MAC_FILTER_LIST_EVENT_FLAG, ie_list->Addr2, pEntry->apidx, 0); goto LabelOK; } MgtMacHeaderInit(pAd, &AssocRspHdr, SubType, 0, ie_list->Addr2, wdev->Bssid); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &AssocRspHdr, 2, &CapabilityInfoForAssocResp, 2, &StatusCode, 2, &Aid, 1, &SupRateIe, 1, &SupRateLen, SupRateLen, pAd->CommonCfg.SupRate, END_OF_ARGS); if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B) && (FlgIs11bSta == 0)) { ULONG TmpLen; MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += TmpLen; } /* add WMM IE here */ if (wdev->bWmmCapable && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) { ULONG TmpLen; 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], &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; }
static INT scan_active(RTMP_ADAPTER *pAd, UCHAR OpMode, UCHAR ScanType) { UCHAR *frm_buf = NULL; HEADER_802_11 Hdr80211; ULONG FrameLen = 0; UCHAR SsidLen = 0; if (MlmeAllocateMemory(pAd, &frm_buf) != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("%s():allocate memory fail\n", __FUNCTION__)); #ifdef CONFIG_AP_SUPPORT if (OpMode == OPMODE_AP) pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; #endif /* CONFIG_AP_SUPPORT */ return FALSE; } #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 if (ScanType == SCAN_2040_BSS_COEXIST) { DBGPRINT(RT_DEBUG_INFO, ("SYNC - SCAN_2040_BSS_COEXIST !! Prepare to send Probe Request\n")); } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ /* There is no need to send broadcast probe request if active scan is in effect.*/ SsidLen = 0; if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) #ifdef WSC_STA_SUPPORT || ((ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_STA)) #endif /* WSC_STA_SUPPORT */ ) SsidLen = pAd->ScanCtrl.SsidLen; //CFG_TODO { #ifdef CONFIG_AP_SUPPORT /*IF_DEV_CONFIG_OPMODE_ON_AP(pAd) */ if (OpMode == OPMODE_AP) { MgtMacHeaderInitExt(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, pAd->ApCfg.MBSSID[0].wdev.bssid, BROADCAST_ADDR); } #endif /* CONFIG_AP_SUPPORT */ MakeOutgoingFrame(frm_buf, &FrameLen, sizeof(HEADER_802_11), &Hdr80211, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->ScanCtrl.Ssid, 1, &SupRateIe, 1, &pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, END_OF_ARGS); if (pAd->CommonCfg.ExtRateLen) { ULONG Tmp; MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += Tmp; } } #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { ULONG Tmp; UCHAR HtLen; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; #endif { HtLen = sizeof(HT_CAPABILITY_IE); #ifdef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE); *(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(frm_buf + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, END_OF_ARGS); #else MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &pAd->CommonCfg.HtCapability, END_OF_ARGS); #endif /* RT_BIG_ENDIAN */ } FrameLen += Tmp; #ifdef DOT11N_DRAFT3 if ((pAd->ScanCtrl.Channel <= 14) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) { ULONG Tmp; HtLen = 1; MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &ExtHtCapIe, 1, &HtLen, 1, &pAd->CommonCfg.BSSCoexist2040.word, END_OF_ARGS); FrameLen += Tmp; } #endif /* DOT11N_DRAFT3 */ } #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->ScanCtrl.Channel > 14)) { FrameLen += build_vht_ies(pAd, (UCHAR *)(frm_buf + FrameLen), SUBTYPE_PROBE_REQ); } #endif /* DOT11_VHT_AC */ #ifdef WSC_STA_SUPPORT if (OpMode == OPMODE_STA) { BOOLEAN bHasWscIe = FALSE; /* Append WSC information in probe request if WSC state is running */ if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && (pAd->StaCfg.WscControl.bWscTrigger == TRUE)) bHasWscIe = TRUE; #ifdef WSC_V2_SUPPORT else if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && (pAd->StaCfg.WscControl.WscV2Info.bEnableWpsV2)) bHasWscIe = TRUE; #endif /* WSC_V2_SUPPORT */ if (bHasWscIe) { UCHAR *pWscBuf = NULL, WscIeLen = 0; ULONG WscTmpLen = 0; os_alloc_mem(NULL, (UCHAR **)&pWscBuf, 512); if (pWscBuf != NULL) { NdisZeroMemory(pWscBuf, 512); WscBuildProbeReqIE(pAd, STA_MODE, pWscBuf, &WscIeLen); MakeOutgoingFrame(frm_buf + FrameLen, &WscTmpLen, WscIeLen, pWscBuf, END_OF_ARGS); FrameLen += WscTmpLen; os_free_mem(NULL, pWscBuf); } else DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__)); } } #endif /* WSC_STA_SUPPORT */ #ifdef RT_CFG80211_SUPPORT if ((OpMode == OPMODE_STA) && (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && CFG80211DRV_OpsScanRunning(pAd)) { ULONG ExtraIeTmpLen = 0; MakeOutgoingFrame(frm_buf + FrameLen, &ExtraIeTmpLen, pAd->cfg80211_ctrl.ExtraIeLen, pAd->cfg80211_ctrl.pExtraIe, END_OF_ARGS); FrameLen += ExtraIeTmpLen; } #endif /* RT_CFG80211_SUPPORT */ MiniportMMRequest(pAd, 0, frm_buf, FrameLen); MlmeFreeMemory(pAd, frm_buf); return TRUE; }
static USHORT update_associated_mac_entry( IN RTMP_ADAPTER *pAd, IN MAC_TABLE_ENTRY *pEntry, IN IE_LISTS *ie_list, IN UCHAR MaxSupportedRate) { MULTISSID_STRUCT *wdev; #ifdef TXBF_SUPPORT BOOLEAN supportsETxBF = FALSE; #endif // TXBF_SUPPORT // wdev = &pAd->ApCfg.MBSSID[pEntry->apidx]; /* Update auth, wep, legacy transmit rate setting . */ pEntry->Sst = SST_ASSOC; pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); set_entry_phy_cfg(pAd, pEntry); pEntry->CapabilityInfo = ie_list->CapabilityInfo; if ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) { pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; pEntry->WpaState = AS_INITPSK; } #ifdef DOT1X_SUPPORT else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->IEEE8021X == TRUE)) { pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; pEntry->WpaState = AS_AUTHENTICATION; } #endif /* DOT1X_SUPPORT */ /*if (ClientRalinkIe & 0x00000004) */ if (ie_list->RalinkIe != 0x0) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); else CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); /* Ralink proprietary Piggyback and Aggregation support for legacy RT61 chip */ CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); #ifdef AGGREGATION_SUPPORT if ((pAd->CommonCfg.bAggregationCapable) && (ie_list->RalinkIe & 0x00000001)) { CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE); DBGPRINT(RT_DEBUG_TRACE, ("ASSOC -RaAggregate= 1\n")); } #endif /* AGGREGATION_SUPPORT */ #ifdef PIGGYBACK_SUPPORT if ((pAd->CommonCfg.bPiggyBackCapable) && (ie_list->RalinkIe & 0x00000002)) { CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE); DBGPRINT(RT_DEBUG_TRACE, ("ASSOC -PiggyBack= 1\n")); } #endif /* PIGGYBACK_SUPPORT */ /* In WPA or 802.1x mode, the port is not secured, otherwise is secued. */ if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) #ifdef DOT1X_SUPPORT || (wdev->IEEE8021X == TRUE) #endif /* DOT1X_SUPPORT */ ) pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; else pEntry->PortSecured = WPA_802_1X_PORT_SECURED; #ifdef SOFT_ENCRYPT /* There are some situation to need to encryption by software 1. The Client support PMF. It shall ony support AES cipher. 2. The Client support WAPI. If use RT3883 or later, HW can handle the above. */ #endif /* SOFT_ENCRYPT */ #ifdef DOT11_N_SUPPORT /* WFA recommend to restrict the encryption type in 11n-HT mode. So, the WEP and TKIP are not allowed in HT rate. */ if (pAd->CommonCfg.HT_DisallowTKIP && IS_INVALID_HT_SECURITY(pEntry->WepStatus)) { /* Force to None-HT mode due to WiFi 11n policy */ ie_list->ht_cap_len = 0; DBGPRINT(RT_DEBUG_TRACE, ("%s : Force the STA as Non-HT mode\n", __FUNCTION__)); } /* If this Entry supports 802.11n, upgrade to HT rate. */ if ((ie_list->ht_cap_len != 0) && (wdev->DesiredHtPhyInfo.bHtEnable) && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { ht_mode_adjust(pAd, pEntry, &ie_list->HTCapability, &pAd->CommonCfg.DesiredHtPhy); #ifdef DOT11N_DRAFT3 if (ie_list->ExtCapInfo.BssCoexistMgmtSupport) pEntry->BSS2040CoexistenceMgmtSupport = 1; #endif /* DOT11N_DRAFT3 */ /* 40Mhz BSS Width Trigger events */ if (ie_list->HTCapability.HtCapInfo.Forty_Mhz_Intolerant) { #ifdef DOT11N_DRAFT3 pEntry->bForty_Mhz_Intolerant = TRUE; pAd->MacTab.fAnyStaFortyIntolerant = TRUE; if(((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (pAd->CommonCfg.Channel <=14)) && ((pAd->CommonCfg.bBssCoexEnable == TRUE) && (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth != 0) && (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset != 0)) ) { pAd->CommonCfg.LastBSSCoexist2040.field.BSS20WidthReq = 1; pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0; pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_SYNC; } DBGPRINT(RT_DEBUG_TRACE, ("pEntry set 40MHz Intolerant as 1\n")); #endif /* DOT11N_DRAFT3 */ Handle_BSS_Width_Trigger_Events(pAd); } #ifdef TXBF_SUPPORT supportsETxBF = clientSupportsETxBF(pAd, &ie_list->HtCapability.TxBFCap); #endif /* TXBF_SUPPORT */ /* find max fixed rate */ pEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &wdev->DesiredHtPhyInfo.MCSSet[0], &ie_list->HTCapability.MCSSet[0]); if (wdev->DesiredTransmitSetting.field.MCS != MCS_AUTO) { DBGPRINT(RT_DEBUG_TRACE, ("@@@ IF-ra%d DesiredTransmitSetting.field.MCS = %d\n", pEntry->apidx, wdev->DesiredTransmitSetting.field.MCS)); set_ht_fixed_mcs(pAd, pEntry, wdev->DesiredTransmitSetting.field.MCS, wdev->HTPhyMode.field.MCS); } pEntry->MaxHTPhyMode.field.STBC = (ie_list->HTCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); // TODO: shiang-6590, check if this is necessary here, perforce didn't have this if (ie_list->HTCapability.HtCapParm.MpduDensity < 5) ie_list->HTCapability.HtCapParm.MpduDensity = 5; pEntry->MpduDensity = ie_list->HTCapability.HtCapParm.MpduDensity; pEntry->MaxRAmpduFactor = ie_list->HTCapability.HtCapParm.MaxRAmpduFactor; pEntry->MmpsMode = (UCHAR)ie_list->HTCapability.HtCapInfo.MimoPs; pEntry->AMsduSize = (UCHAR)ie_list->HTCapability.HtCapInfo.AMsduSize; if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED); if (ie_list->HTCapability.HtCapInfo.ShortGIfor20) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE); if (ie_list->HTCapability.HtCapInfo.ShortGIfor40) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE); if (ie_list->HTCapability.HtCapInfo.TxSTBC) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE); if (ie_list->HTCapability.HtCapInfo.RxSTBC) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE); if (ie_list->HTCapability.ExtHtCapInfo.PlusHTC) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE); if (pAd->CommonCfg.bRdg && ie_list->HTCapability.ExtHtCapInfo.RDGSupport) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE); if (ie_list->HTCapability.ExtHtCapInfo.MCSFeedback == 0x03) CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE); /* Record the received capability from association request */ NdisMoveMemory(&pEntry->HTCapability, &ie_list->HTCapability, sizeof(HT_CAPABILITY_IE)); #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->CommonCfg.Channel > 14) && ie_list->vht_cap_len) { pEntry->MaxHTPhyMode.field.MODE = MODE_VHT; if ((pEntry->MaxHTPhyMode.field.BW== BW_40) && (wdev->DesiredHtPhyInfo.vht_bw)) pEntry->MaxHTPhyMode.field.BW = BW_80; NdisMoveMemory(&pEntry->vht_cap_ie, &ie_list->vht_cap, sizeof(VHT_CAP_IE)); } #endif /* DOT11_VHT_AC */ } else { pAd->MacTab.fAnyStationIsLegacy = TRUE; NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); } #endif /* DOT11_N_SUPPORT */ pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; pEntry->CurrTxRate = pEntry->MaxSupportedRate; #ifdef MFB_SUPPORT pEntry->lastLegalMfb = 0; pEntry->isMfbChanged = FALSE; pEntry->fLastChangeAccordingMfb = FALSE; pEntry->toTxMrq = TRUE; pEntry->msiToTx = 0;/*has to increment whenever a mrq is sent */ pEntry->mrqCnt = 0; pEntry->pendingMfsi = 0; pEntry->toTxMfb = FALSE; pEntry->mfbToTx = 0; pEntry->mfb0 = 0; pEntry->mfb1 = 0; #endif /* MFB_SUPPORT */ pEntry->freqOffsetValid = FALSE; #ifdef TXBF_SUPPORT if (pAd->chipCap.FlgHwTxBfCap) TxBFInit(pAd, pEntry, supportsETxBF); #endif // TXBF_SUPPORT // // Initialize Rate Adaptation MlmeRAInit(pAd, pEntry); /* Set asic auto fall back */ if (wdev->bAutoTxRateSwitch == TRUE) { UCHAR TableSize = 0; MlmeSelectTxRateTable(pAd, pEntry, &pEntry->pTable, &TableSize, &pEntry->CurrTxRateIndex); MlmeNewTxRate(pAd, pEntry); pEntry->bAutoTxRateSwitch = TRUE; #ifdef NEW_RATE_ADAPT_SUPPORT if (! ADAPT_RATE_TABLE(pEntry->pTable)) #endif /* NEW_RATE_ADAPT_SUPPORT */ pEntry->HTPhyMode.field.ShortGI = GI_800; } else { pEntry->HTPhyMode.field.MCS = wdev->HTPhyMode.field.MCS; pEntry->bAutoTxRateSwitch = FALSE; /* If the legacy mode is set, overwrite the transmit setting of this entry. */ RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pEntry); } if (pEntry->AuthMode < Ndis802_11AuthModeWPA) ApLogEvent(pAd, pEntry->Addr, EVENT_ASSOCIATED); APUpdateCapabilityAndErpIe(pAd); #ifdef DOT11_N_SUPPORT APUpdateOperationMode(pAd); #endif /* DOT11_N_SUPPORT */ pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; #ifdef HOSTAPD_SUPPORT if((wdev->Hostapd == TRUE) && ((wdev->AuthMode >= Ndis802_11AuthModeWPA) || wdev->IEEE8021X)) { RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_EXPIRED, -1, pEntry->Addr, NULL, 0, ((pEntry->CapabilityInfo & 0x0010) == 0 ? 0xFFFD : 0xFFFC)); } #endif /*HOSTAPD_SUPPORT*/ return MLME_SUCCESS; }
static INT scan_active(RTMP_ADAPTER *pAd, UCHAR OpMode, UCHAR ScanType) { UCHAR *frm_buf = NULL; HEADER_802_11 Hdr80211; ULONG FrameLen = 0; UCHAR SsidLen = 0; #ifdef CONFIG_STA_SUPPORT USHORT Status; #endif /* CONFIG_STA_SUPPORT */ if (MlmeAllocateMemory(pAd, &frm_buf) != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n")); #ifdef CONFIG_STA_SUPPORT if (OpMode == OPMODE_STA) { pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE; Status = MLME_FAIL_NO_RESOURCE; MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status, 0); } #endif /* CONFIG_STA_SUPPORT */ #ifdef CONFIG_AP_SUPPORT if (OpMode == OPMODE_AP) pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; #endif /* CONFIG_AP_SUPPORT */ return FALSE; } #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 if (ScanType == SCAN_2040_BSS_COEXIST) { DBGPRINT(RT_DEBUG_INFO, ("SYNC - SCAN_2040_BSS_COEXIST !! Prepare to send Probe Request\n")); } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ /* There is no need to send broadcast probe request if active scan is in effect.*/ SsidLen = 0; if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) #ifdef WSC_STA_SUPPORT || ((ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_STA)) #endif /* WSC_STA_SUPPORT */ ) SsidLen = pAd->MlmeAux.SsidLen; #ifdef P2P_SUPPORT if ((pAd->MlmeAux.ScanType == SCAN_P2P) || (pAd->MlmeAux.ScanType == SCAN_P2P_SEARCH) #ifdef P2P_APCLI_SUPPORT || ((pAd->MlmeAux.ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_AP) && (P2P_CLI_ON(pAd))) #endif /* P2P_APCLI_SUPPORT */ ) { PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg; UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; UCHAR SupRateLen = 0; SsidLen = WILDP2PSSIDLEN; /* Use Wildword SSID */ 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; /* P2P scan must use P2P mac address. */ MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, pP2PCtrl->CurrentAddress, BROADCAST_ADDR); MakeOutgoingFrame(frm_buf, &FrameLen, sizeof(HEADER_802_11), &Hdr80211, 1, &SsidIe, 1, &SsidLen, SsidLen, &WILDP2PSSID[0], 1, &SupRateIe, 1, &SupRateLen, SupRateLen, SupRate, END_OF_ARGS); } else #endif /* P2P_SUPPORT */ { #ifdef CONFIG_AP_SUPPORT /*IF_DEV_CONFIG_OPMODE_ON_AP(pAd) */ if (OpMode == OPMODE_AP) { MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, #ifdef P2P_SUPPORT pAd->ApCfg.MBSSID[0].Bssid, #endif /* P2P_SUPPORT */ pAd->ApCfg.MBSSID[0].Bssid); } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT /*IF_DEV_CONFIG_OPMODE_ON_STA(pAd) */ if (OpMode == OPMODE_STA) { MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, #ifdef P2P_SUPPORT pAd->CurrentAddress, #endif /* P2P_SUPPORT */ BROADCAST_ADDR); } #endif /* CONFIG_STA_SUPPORT */ MakeOutgoingFrame(frm_buf, &FrameLen, sizeof(HEADER_802_11), &Hdr80211, 1, &SsidIe, 1, &SsidLen, SsidLen, pAd->MlmeAux.Ssid, 1, &SupRateIe, 1, &pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, END_OF_ARGS); if (pAd->CommonCfg.ExtRateLen) { ULONG Tmp; MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &ExtRateIe, 1, &pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, END_OF_ARGS); FrameLen += Tmp; } } #ifdef DOT11_N_SUPPORT if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) { ULONG Tmp; UCHAR HtLen; UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33}; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; #endif if (pAd->bBroadComHT == TRUE) { HtLen = pAd->MlmeAux.HtCapabilityLen + 4; #ifdef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE); *(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(frm_buf + FrameLen, &Tmp, 1, &WpaIe, 1, &HtLen, 4, &BROADCOM[0], pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, END_OF_ARGS); #else MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &WpaIe, 1, &HtLen, 4, &BROADCOM[0], pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability, END_OF_ARGS); #endif /* RT_BIG_ENDIAN */ } else { HtLen = sizeof(HT_CAPABILITY_IE); #ifdef RT_BIG_ENDIAN NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE); *(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(frm_buf + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &HtCapabilityTmp, END_OF_ARGS); #else MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &HtCapIe, 1, &HtLen, HtLen, &pAd->CommonCfg.HtCapability, END_OF_ARGS); #endif /* RT_BIG_ENDIAN */ } FrameLen += Tmp; #ifdef DOT11N_DRAFT3 if ((pAd->MlmeAux.Channel <= 14) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) { ULONG Tmp; HtLen = 1; MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, 1, &ExtHtCapIe, 1, &HtLen, 1, &pAd->CommonCfg.BSSCoexist2040.word, END_OF_ARGS); FrameLen += Tmp; } #endif /* DOT11N_DRAFT3 */ } #endif /* DOT11_N_SUPPORT */ #ifdef DOT11_VHT_AC if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && (pAd->MlmeAux.Channel > 14)) { FrameLen += build_vht_ies(pAd, (UCHAR *)(frm_buf + FrameLen), SUBTYPE_PROBE_REQ); } #endif /* DOT11_VHT_AC */ #ifdef WSC_STA_SUPPORT if (OpMode == OPMODE_STA) { BOOLEAN bHasWscIe = FALSE; /* Append WSC information in probe request if WSC state is running */ if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && (pAd->StaCfg.WscControl.bWscTrigger == TRUE)) bHasWscIe = TRUE; #ifdef WSC_V2_SUPPORT else if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && (pAd->StaCfg.WscControl.WscV2Info.bEnableWpsV2)) bHasWscIe = TRUE; #endif /* WSC_V2_SUPPORT */ #ifdef P2P_SUPPORT /* P2pMakeProbeReqIE will build WSC IE for P2P, it is not good to append normal WSC IE into P2P probe request frame here. */ if ((pAd->MlmeAux.ScanType == SCAN_P2P) || (pAd->MlmeAux.ScanType == SCAN_P2P_SEARCH) || ((pAd->MlmeAux.ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_AP) && (P2P_CLI_ON(pAd)))) bHasWscIe = FALSE; #endif /* P2P_SUPPORT */ if (bHasWscIe) { UCHAR *pWscBuf = NULL, WscIeLen = 0; ULONG WscTmpLen = 0; os_alloc_mem(NULL, (UCHAR **)&pWscBuf, 512); if (pWscBuf != NULL) { NdisZeroMemory(pWscBuf, 512); WscBuildProbeReqIE(pAd, STA_MODE, pWscBuf, &WscIeLen); MakeOutgoingFrame(frm_buf + FrameLen, &WscTmpLen, WscIeLen, pWscBuf, END_OF_ARGS); FrameLen += WscTmpLen; os_free_mem(NULL, pWscBuf); } else DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__)); } } #endif /* WSC_STA_SUPPORT */ #ifdef WPA_SUPPLICANT_SUPPORT if ((OpMode == OPMODE_STA) && (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) && (pAd->StaCfg.WpsProbeReqIeLen != 0)) { ULONG WpsTmpLen = 0; MakeOutgoingFrame(frm_buf + FrameLen, &WpsTmpLen, pAd->StaCfg.WpsProbeReqIeLen, pAd->StaCfg.pWpsProbeReqIe, END_OF_ARGS); FrameLen += WpsTmpLen; } #endif /* WPA_SUPPLICANT_SUPPORT */ #ifdef P2P_SUPPORT if ((pAd->MlmeAux.ScanType == SCAN_P2P) || (pAd->MlmeAux.ScanType == SCAN_P2P_SEARCH) #ifdef P2P_APCLI_SUPPORT || ((pAd->MlmeAux.ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_AP) && (P2P_CLI_ON(pAd))) #endif /* P2P_APCLI_SUPPORT */ ) { ULONG P2PIeLen; UCHAR tmp_len; PUCHAR ptr; ptr = frm_buf + FrameLen; P2pMakeProbeReqIE(pAd, ptr, &tmp_len); FrameLen += tmp_len; /* Put P2P IE to the last. */ ptr = frm_buf + FrameLen; P2pMakeP2pIE(pAd, SUBTYPE_PROBE_REQ, ptr, &P2PIeLen); FrameLen += P2PIeLen; } #endif /* P2P_SUPPORT */ MiniportMMRequest(pAd, 0, frm_buf, FrameLen); #ifdef CONFIG_STA_SUPPORT if (OpMode == OPMODE_STA) { /* To prevent data lost. Send an NULL data with turned PSM bit on to current associated AP when SCAN in the channel where associated AP located. */ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd)) && (pAd->CommonCfg.Channel == pAd->MlmeAux.Channel)) { RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE), PWR_SAVE); DBGPRINT(RT_DEBUG_TRACE, ("ScanNextChannel():Send PWA NullData frame to notify the associated AP!\n")); } } #if 0//def RT_CFG80211_SUPPORT if (pAd->ApCfg.ApCliTab[MAIN_MBSSID].Valid && RTMP_CFG80211_VIF_P2P_CLI_ON(pAd) && (pAd->CommonCfg.Channel == pAd->MlmeAux.Channel)) { DBGPRINT(RT_DEBUG_TRACE, ("CFG80211_NULL: PWR_SAVE SCANNING\n")); RT_CFG80211_P2P_CLI_SEND_NULL_FRAME(pAd, PWR_SAVE); } #endif /* RT_CFG80211_SUPPORT */ #endif /* CONFIG_STA_SUPPORT */ MlmeFreeMemory(pAd, frm_buf); return TRUE; }
/* ========================================================================== 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; MULTISSID_STRUCT *mbss; struct wifi_dev *wdev; CHAR rssi = 0, idx = 0; if (! PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, &ProbeReqParam)) return; 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))) ) ) ; else continue; /* check next BSS */ rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, (CHAR)Elem->Rssi0, RSSI_0), ConvertToRssi(pAd, (CHAR)Elem->Rssi1, RSSI_1), ConvertToRssi(pAd, (CHAR)Elem->Rssi2, RSSI_2)); if ((mbss->ProbeRspRssiThreshold != 0) && (rssi < mbss->ProbeRspRssiThreshold)) { DBGPRINT(RT_DEBUG_INFO, ("%s: PROBE_RSP Threshold = %d , PROBE RSSI = %d\n", wdev->if_dev->name, mbss->ProbeRspRssiThreshold, rssi)); continue; } /* allocate and send out ProbeRsp frame */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) return; 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)) RSNIe = IE_WPA2; { 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; #ifdef RT_BIG_ENDIAN HT_CAPABILITY_IE HtCapabilityTmp; ADD_HT_INFO_IE addHTInfoTmp; #endif /* YF@20120419: Fix IOT Issue with Atheros STA on Windows 7 When IEEE80211H flag turn on. */ 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 MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, 1, &HtCapIe, 1, &HtLen, sizeof(HT_CAPABILITY_IE), &pAd->CommonCfg.HtCapability, 1, &AddHtInfoIe, 1, &AddHtLen, sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, 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 */ 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 { MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 1, &RSNIe, 1, &mbss->RSNIE_Len[0], mbss->RSNIE_Len[0], mbss->RSN_IE[0], END_OF_ARGS); FrameLen += TmpLen; } /* 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 */ 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) { 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->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) { ULONG TmpLen, 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 */ os_free_mem(NULL, TmpFrame); } else DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); } #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 */ /* 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 DOT11_VHT_AC if (pAd->CommonCfg.b256QAM_2G && WMODE_2G_ONLY(pAd->CommonCfg.PhyMode)) RalinkSpecificIe[5] |= 0x8; #endif /* DOT11_VHT_AC */ #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.AvgRssi0; RalinkSpecificIe[7] = (UCHAR)pEntry->RssiSample.AvgRssi1; RalinkSpecificIe[8] = (UCHAR)pEntry->RssiSample.AvgRssi2; } } #endif /* RSSI_FEEDBACK */ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, 9, RalinkSpecificIe, END_OF_ARGS); FrameLen += TmpLen; } /* 802.11n 11.1.3.2.2 active scanning. sending probe response with MCS rate is */ for (idx = 0; idx < mbss->ProbeRspTimes; idx++) MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); }