VOID CFG80211_UpdateBeacon( VOID *pAdOrg, UCHAR *beacon_head_buf, UINT32 beacon_head_len, UCHAR *beacon_tail_buf, UINT32 beacon_tail_len, BOOLEAN isAllUpdate) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdOrg; PCFG80211_CTRL pCfg80211_ctrl = &pAd->cfg80211_ctrl; HTTRANSMIT_SETTING BeaconTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ PUCHAR pBeaconFrame = (PUCHAR)pAd->ApCfg.MBSSID[MAIN_MBSSID].BeaconBuf; TXWI_STRUC *pTxWI = &pAd->BeaconTxWI; UCHAR New_Tim_Len; UINT32 beacon_len; /* Invoke From CFG80211 OPS For setting Beacon buffer */ if (isAllUpdate) { /* 1. Update the Before TIM IE */ NdisCopyMemory(pBeaconFrame, beacon_head_buf, beacon_head_len); /* 2. Update the TIM IE */ pAd->ApCfg.MBSSID[MAIN_MBSSID].TimIELocationInBeacon = beacon_head_len; /* 3. Store the Tail Part For appending later */ if (pCfg80211_ctrl->beacon_tail_buf != NULL) os_free_mem(NULL, pCfg80211_ctrl->beacon_tail_buf); os_alloc_mem(NULL, (UCHAR **)&pCfg80211_ctrl->beacon_tail_buf, beacon_tail_len); if (pCfg80211_ctrl->beacon_tail_buf != NULL) { NdisCopyMemory(pCfg80211_ctrl->beacon_tail_buf, beacon_tail_buf, beacon_tail_len); pCfg80211_ctrl->beacon_tail_len = beacon_tail_len; } else { pCfg80211_ctrl->beacon_tail_len = 0; DBGPRINT(RT_DEBUG_ERROR, ("CFG80211 Beacon: MEM ALLOC ERROR\n")); } return; } else /* Invoke From Beacon Timer */ { if (pAd->ApCfg.DtimCount == 0) pAd->ApCfg.DtimCount = pAd->ApCfg.DtimPeriod - 1; else pAd->ApCfg.DtimCount -= 1; } /* 4. Update the TIM IE */ New_Tim_Len = CFG80211DRV_UpdateTimIE(pAd, MAIN_MBSSID, pBeaconFrame, pAd->ApCfg.MBSSID[MAIN_MBSSID].TimIELocationInBeacon); /* 5. Update the AFTER TIM IE */ if (pCfg80211_ctrl->beacon_tail_buf != NULL) { NdisCopyMemory(pAd->ApCfg.MBSSID[MAIN_MBSSID].BeaconBuf + pAd->ApCfg.MBSSID[MAIN_MBSSID].TimIELocationInBeacon + New_Tim_Len, pCfg80211_ctrl->beacon_tail_buf, pCfg80211_ctrl->beacon_tail_len); beacon_len = pAd->ApCfg.MBSSID[MAIN_MBSSID].TimIELocationInBeacon + pCfg80211_ctrl->beacon_tail_len + New_Tim_Len; } else { DBGPRINT(RT_DEBUG_ERROR, ("BEACON ====> CFG80211_UpdateBeacon OOPS\n")); return; } BeaconTransmit.word = 0; #ifdef RT_CFG80211_P2P_SUPPORT /* Should be Find the P2P IE Then Set Basic Rate to 6M */ if (RTMP_CFG80211_VIF_P2P_GO_ON(pAd)) BeaconTransmit.field.MODE = MODE_OFDM; /* Use 6Mbps */ else #endif BeaconTransmit.field.MODE = MODE_CCK; BeaconTransmit.field.MCS = MCS_RATE_6; //YF RTMPWriteTxWI(pAd, (UCHAR *)pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, BSS0Mcast_WCID, beacon_len, PID_MGMT, 0, 0, IFS_HTTXOP, &BeaconTransmit); updateAllBeacon(pAd, MAIN_MBSSID, beacon_len); }
/* ========================================================================== 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; #if defined(DOT11_N_SUPPORT) && defined(DOT11K_RRM_SUPPORT) UINT i; #endif /* defined(DOT11_N_SUPPORT) && defined(DOT11K_RRM_SUPPORT) */ HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ UCHAR PhyMode, SupRateLen; 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 */ #ifdef DOT11K_RRM_SUPPORT if (IS_RRM_ENABLE(pAd, apidx) && (pAd->CommonCfg.RegulatoryClass[0] != 0)) { TmpLen2 = 0; NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); RguClass_BuildBcnChList(pAd, TmpFrame, &TmpLen2); } #endif /* DOT11K_RRM_SUPPORT */ /* 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 DOT11K_RRM_SUPPORT if (IS_RRM_ENABLE(pAd, apidx)) { InsertTpcReportIE(pAd, pBeaconFrame+FrameLen, &FrameLen, RTMP_GetTxPwr(pAd, pAd->CommonCfg.MlmeTransmit), 0); RRM_InsertRRMEnCapIE(pAd, pBeaconFrame+FrameLen, &FrameLen, apidx); } #endif /* DOT11K_RRM_SUPPORT */ #ifdef DOT11_N_SUPPORT /* AP Channel Report */ #ifdef DOT11K_RRM_SUPPORT for (i=0; i<MAX_NUM_OF_REGULATORY_CLASS; i++) { if (pAd->CommonCfg.RegulatoryClass[i] == 0) break; InsertChannelRepIE(pAd, pBeaconFrame+FrameLen, &FrameLen, (PSTRING)pAd->CommonCfg.CountryCode, pAd->CommonCfg.RegulatoryClass[i]); } #else { 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 #endif /* DOT11_N_SUPPORT */ #ifdef DOT11R_FT_SUPPORT /* The Mobility Domain information element (MDIE) is present in Beacon ** frame when dot11FastBssTransitionEnable is set to true. */ if (pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable) { PFT_CFG pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; FT_CAP_AND_POLICY FtCap; NdisZeroMemory(&FtCap, sizeof(FT_CAP_AND_POLICY)); FtCap.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; FtCap.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; FT_InsertMdIE(pAd, pBeaconFrame + FrameLen, &FrameLen, pFtCfg->FtMdId, FtCap); } #endif /* DOT11R_FT_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 */ updateAllBeacon(pAd, apidx, FrameLen); pMbss->TimIELocationInBeacon = (UCHAR)FrameLen; pMbss->CapabilityInfoLocationInBeacon = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; } void updateAllBeacon(RTMP_ADAPTER *pAd, INT apidx, ULONG FrameLen) { UCHAR *ptr = NULL; MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; UINT32 longValue, reg_base; UINT i = 0; UINT8 TXWISize = pAd->chipCap.TXWISize; 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; } }