/**************************************************************************** * Ralink Tech Inc. * 4F, No. 2 Technology 5th Rd. * Science-based Industrial Park * Hsin-chu, Taiwan, R.O.C. * (c) Copyright 2002, Ralink Technology, Inc. * * All rights reserved. Ralink's source code is an unpublished work and the * use of a copyright notice does not imply otherwise. This source code * contains confidential trade secret material of Ralink Tech. Any attemp * or participation in deciphering, decoding, reverse engineering or in any * way altering the source code is stricitly prohibited, unless the prior * written consent of Ralink Technology, Inc. is obtained. **************************************************************************** Module Name: action.c Abstract: Handle association related requests either from WSTA or from local MLME Revision History: Who When What -------- ---------- ---------------------------------------------- Jan Lee 2006 created for rt2860 */ #include "rt_config.h" #include "action.h" extern UCHAR ZeroSsid[32]; #ifdef IWSC_SUPPORT extern UCHAR IWSC_ACTION_OUI[]; #endif // IWSC_SUPPORT // #ifdef P2P_SUPPORT /* Group Formation Action */ extern VOID P2pPeerGoNegoReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem); extern VOID P2pPeerGoNegoRspAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem); extern VOID P2pPeerGoNegoConfirmAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem); extern VOID P2pPeerProvisionReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem); extern VOID P2pPeerProvisionRspAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem); extern VOID P2pPeerDeviceDiscRspAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem); extern VOID P2pPeerInvitesReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem); extern VOID P2pPeerInvitesRspAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem); extern VOID P2pPeerDevDiscoverReqAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem); #endif /* P2P_SUPPORT */ static VOID ReservedAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem); /* ========================================================================== Description: association state machine init, including state transition and timer init Parameters: S - pointer to the association state machine Note: The state machine looks like the following ASSOC_IDLE MT2_MLME_DISASSOC_REQ mlme_disassoc_req_action MT2_PEER_DISASSOC_REQ peer_disassoc_action MT2_PEER_ASSOC_REQ drop MT2_PEER_REASSOC_REQ drop MT2_CLS3ERR cls3err_action ========================================================================== */ VOID ActionStateMachineInit( IN PRTMP_ADAPTER pAd, IN STATE_MACHINE *S, OUT STATE_MACHINE_FUNC Trans[]) { StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_ACT_STATE, MAX_ACT_MSG, (STATE_MACHINE_FUNC)Drop, ACT_IDLE, ACT_MACHINE_BASE); StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, (STATE_MACHINE_FUNC)PeerSpectrumAction); StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, (STATE_MACHINE_FUNC)PeerQOSAction); StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)ReservedAction); #ifdef QOS_DLS_SUPPORT StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)PeerDLSAction); #endif /* QOS_DLS_SUPPORT */ #ifdef DOT11_N_SUPPORT StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, (STATE_MACHINE_FUNC)PeerBAAction); StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, (STATE_MACHINE_FUNC)PeerHTAction); StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, (STATE_MACHINE_FUNC)MlmeADDBAAction); StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); #endif /* DOT11_N_SUPPORT */ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, (STATE_MACHINE_FUNC)PeerPublicAction); StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, (STATE_MACHINE_FUNC)PeerRMAction); StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, (STATE_MACHINE_FUNC)MlmeQOSAction); StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, (STATE_MACHINE_FUNC)MlmeDLSAction); StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, (STATE_MACHINE_FUNC)MlmeInvalidAction); #ifdef CONFIG_AP_SUPPORT #endif /* CONFIG_AP_SUPPORT */ } #ifdef DOT11_N_SUPPORT VOID MlmeADDBAAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { MLME_ADDBA_REQ_STRUCT *pInfo; UCHAR Addr[6]; PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG Idx; FRAME_ADDBA_REQ Frame; ULONG FrameLen; BA_ORI_ENTRY *pBAEntry = NULL; #ifdef CONFIG_AP_SUPPORT UCHAR apidx; #endif /* CONFIG_AP_SUPPORT */ #ifdef P2P_SUPPORT MAC_TABLE_ENTRY *pEntry = NULL; #endif /* P2P_SUPPORT */ pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg; NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ)); if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr) && VALID_WCID(pInfo->Wcid)) { NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory*/ if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n")); return; } /* 1. find entry */ Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; if (Idx == 0) { MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n")); return; } else { pBAEntry =&pAd->BATable.BAOriEntry[Idx]; } #ifdef P2P_SUPPORT /*if (VALID_WCID(pInfo->Wcid))*/ { pEntry = &pAd->MacTab.Content[pInfo->Wcid]; if (pEntry) { #ifdef CONFIG_STA_SUPPORT if (ADHOC_ON(pAd) #ifdef QOS_DLS_SUPPORT || (IS_ENTRY_DLS(&pAd->MacTab.Content[pInfo->Wcid])) #endif /* QOS_DLS_SUPPORT */ #ifdef DOT11Z_TDLS_SUPPORT || (IS_ENTRY_TDLS(&pAd->MacTab.Content[pInfo->Wcid])) #endif /* DOT11Z_TDLS_SUPPORT */ ) { ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); } else #endif /* CONFIG_STA_SUPPORT */ { ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pEntry->HdrAddr2, pEntry->HdrAddr3); } } } #else #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { #ifdef APCLI_SUPPORT if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pInfo->Wcid])) { apidx = pAd->MacTab.Content[pInfo->Wcid].MatchAPCLITabIdx; ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pInfo->pAddr); } else #endif /* APCLI_SUPPORT */ { apidx = pAd->MacTab.Content[pInfo->Wcid].apidx; ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); } } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { if (ADHOC_ON(pAd) #ifdef QOS_DLS_SUPPORT || (IS_ENTRY_DLS(&pAd->MacTab.Content[pInfo->Wcid])) #endif /* QOS_DLS_SUPPORT */ #ifdef DOT11Z_TDLS_SUPPORT || (IS_ENTRY_TDLS(&pAd->MacTab.Content[pInfo->Wcid])) #endif /* DOT11Z_TDLS_SUPPORT */ ) ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); else ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pInfo->pAddr); } #endif /* CONFIG_STA_SUPPORT */ #endif /* P2P_SUPPORT */ Frame.Category = CATEGORY_BA; Frame.Action = ADDBA_REQ; Frame.BaParm.AMSDUSupported = 0; Frame.BaParm.BAPolicy = IMMED_BA; Frame.BaParm.TID = pInfo->TID; Frame.BaParm.BufSize = pInfo->BaBufSize; Frame.Token = pInfo->Token; Frame.TimeOutValue = pInfo->TimeOutValue; Frame.BaStartSeq.field.FragNum = 0; Frame.BaStartSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; #ifdef UNALIGNMENT_SUPPORT { BA_PARM tmpBaParm; NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&Frame.BaParm), sizeof(BA_PARM)); *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); NdisMoveMemory((PUCHAR)(&Frame.BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); } #else *(USHORT *)(&(Frame.BaParm)) = cpu2le16((*(USHORT *)(&(Frame.BaParm)))); #endif /* UNALIGNMENT_SUPPORT */ Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue); Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_ADDBA_REQ), &Frame, END_OF_ARGS); MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | MapUserPriorityToAccessCategory[pInfo->TID]), pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize)); } } /* ========================================================================== Description: send DELBA and delete BaEntry if any Parametrs: Elem - MLME message MLME_DELBA_REQ_STRUCT IRQL = DISPATCH_LEVEL ========================================================================== */ VOID MlmeDELBAAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { MLME_DELBA_REQ_STRUCT *pInfo; PUCHAR pOutBuffer = NULL; PUCHAR pOutBuffer2 = NULL; NDIS_STATUS NStatus; ULONG Idx; FRAME_DELBA_REQ Frame; ULONG FrameLen; FRAME_BAR FrameBar; #ifdef CONFIG_AP_SUPPORT UCHAR apidx; #endif /* CONFIG_AP_SUPPORT */ #ifdef P2P_SUPPORT MAC_TABLE_ENTRY *pEntry = NULL; #endif /* P2P_SUPPORT */ pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg; /* must send back DELBA */ NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ)); DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator)); if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen) && VALID_WCID(pInfo->Wcid)) { NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n")); return; } NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); /*Get an unused nonpaged memory*/ if(NStatus != NDIS_STATUS_SUCCESS) { MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n")); return; } /* SEND BAR (Send BAR to refresh peer reordering buffer.) */ Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID]; #ifdef P2P_SUPPORT /*if (VALID_WCID(pInfo->Wcid)) */ { pEntry = &pAd->MacTab.Content[pInfo->Wcid]; if (pEntry) BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pEntry->HdrAddr2); } #else #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { #ifdef APCLI_SUPPORT if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pInfo->Wcid])) { apidx = pAd->MacTab.Content[pInfo->Wcid].MatchAPCLITabIdx; BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress); } else #endif /* APCLI_SUPPORT */ { apidx = pAd->MacTab.Content[pInfo->Wcid].apidx; BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid); } } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress); #endif /* CONFIG_STA_SUPPORT */ #endif /* P2P_SUPPORT */ FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL funciton.*/ FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; /* make sure sequence not clear in DEL funciton.*/ FrameBar.BarControl.TID = pInfo->TID; /* make sure sequence not clear in DEL funciton.*/ FrameBar.BarControl.ACKPolicy = IMMED_BA; /* make sure sequence not clear in DEL funciton.*/ FrameBar.BarControl.Compressed = 1; /* make sure sequence not clear in DEL funciton.*/ FrameBar.BarControl.MTID = 0; /* make sure sequence not clear in DEL funciton.*/ MakeOutgoingFrame(pOutBuffer2, &FrameLen, sizeof(FRAME_BAR), &FrameBar, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); MlmeFreeMemory(pAd, pOutBuffer2); DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n")); /* SEND DELBA FRAME*/ FrameLen = 0; #ifdef P2P_SUPPORT if (VALID_WCID(pInfo->Wcid)) { pEntry = &pAd->MacTab.Content[pInfo->Wcid]; if (pEntry) { #ifdef CONFIG_STA_SUPPORT if (ADHOC_ON(pAd) #ifdef QOS_DLS_SUPPORT || (IS_ENTRY_DLS(&pAd->MacTab.Content[pInfo->Wcid])) #endif /* QOS_DLS_SUPPORT */ #ifdef DOT11Z_TDLS_SUPPORT || (IS_ENTRY_TDLS(&pAd->MacTab.Content[pInfo->Wcid])) #endif /* DOT11Z_TDLS_SUPPORT */ ) { ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); } else #endif /* CONFIG_STA_SUPPORT */ { ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pEntry->HdrAddr2, pEntry->HdrAddr3); } } } #else #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { #ifdef APCLI_SUPPORT if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pInfo->Wcid])) { apidx = pAd->MacTab.Content[pInfo->Wcid].MatchAPCLITabIdx; ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr); } else #endif /* APCLI_SUPPORT */ { apidx = pAd->MacTab.Content[pInfo->Wcid].apidx; ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); } } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { if (ADHOC_ON(pAd) #ifdef QOS_DLS_SUPPORT || (IS_ENTRY_DLS(&pAd->MacTab.Content[pInfo->Wcid])) #endif /* QOS_DLS_SUPPORT */ #ifdef DOT11Z_TDLS_SUPPORT || (IS_ENTRY_TDLS(&pAd->MacTab.Content[pInfo->Wcid])) #endif /* DOT11Z_TDLS_SUPPORT */ ) ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); else ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr); } #endif /* CONFIG_STA_SUPPORT */ #endif /* P2P_SUPPORT */ Frame.Category = CATEGORY_BA; Frame.Action = DELBA; Frame.DelbaParm.Initiator = pInfo->Initiator; Frame.DelbaParm.TID = pInfo->TID; Frame.ReasonCode = 39; /* Time Out*/ *(USHORT *)(&Frame.DelbaParm) = cpu2le16(*(USHORT *)(&Frame.DelbaParm)); Frame.ReasonCode = cpu2le16(Frame.ReasonCode); MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_DELBA_REQ), &Frame, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator)); } } #endif /* DOT11_N_SUPPORT */ VOID MlmeQOSAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { } VOID MlmeDLSAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { } VOID MlmeInvalidAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { /*PUCHAR pOutBuffer = NULL;*/ /*Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11*/ } VOID PeerQOSAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { } #ifdef QOS_DLS_SUPPORT VOID PeerDLSAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Action = Elem->Msg[LENGTH_802_11+1]; switch(Action) { case ACTION_DLS_REQUEST: #ifdef CONFIG_AP_SUPPORT #ifndef P2P_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) APPeerDlsReqAction(pAd, Elem); #endif /* P2P_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) PeerDlsReqAction(pAd, Elem); #endif /* CONFIG_STA_SUPPORT */ break; case ACTION_DLS_RESPONSE: #ifdef CONFIG_AP_SUPPORT #ifndef P2P_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) APPeerDlsRspAction(pAd, Elem); #endif /* P2P_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) PeerDlsRspAction(pAd, Elem); #endif /* CONFIG_STA_SUPPORT */ break; case ACTION_DLS_TEARDOWN: #ifdef CONFIG_AP_SUPPORT #ifndef P2P_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) APPeerDlsTearDownAction(pAd, Elem); #endif /* P2P_SUPPORT */ #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) PeerDlsTearDownAction(pAd, Elem); #endif /* CONFIG_STA_SUPPORT */ break; } } #endif /* QOS_DLS_SUPPORT */ #ifdef DOT11_N_SUPPORT VOID PeerBAAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Action = Elem->Msg[LENGTH_802_11+1]; switch(Action) { case ADDBA_REQ: PeerAddBAReqAction(pAd,Elem); break; case ADDBA_RESP: PeerAddBARspAction(pAd,Elem); break; case DELBA: PeerDelBAAction(pAd,Elem); break; } } #ifdef DOT11N_DRAFT3 #ifdef CONFIG_AP_SUPPORT extern UCHAR get_regulatory_class(IN PRTMP_ADAPTER pAd); VOID ApPublicAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Action = Elem->Msg[LENGTH_802_11+1]; BSS_2040_COEXIST_IE BssCoexist; /* Format as in IEEE 7.4.7.2*/ if (Action == ACTION_BSS_2040_COEXIST) { BssCoexist.word = Elem->Msg[LENGTH_802_11+2]; } } VOID SendBSS2040CoexistMgmtAction( IN PRTMP_ADAPTER pAd, IN UCHAR Wcid, IN UCHAR apidx, IN UCHAR InfoReq) { PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; FRAME_ACTION_HDR Frame; ULONG FrameLen; BSS_2040_COEXIST_ELEMENT BssCoexistInfo; BSS_2040_INTOLERANT_CH_REPORT BssIntolerantInfo; PUCHAR pAddr1; DBGPRINT(RT_DEBUG_TRACE, ("SendBSS2040CoexistMgmtAction(): Wcid=%d, apidx=%d, InfoReq=%d!\n", Wcid, apidx, InfoReq)); NdisZeroMemory((PUCHAR)&BssCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT)); NdisZeroMemory((PUCHAR)&BssIntolerantInfo, sizeof(BSS_2040_INTOLERANT_CH_REPORT)); BssCoexistInfo.ElementID = IE_2040_BSS_COEXIST; BssCoexistInfo.Len = 1; BssCoexistInfo.BssCoexistIe.word = pAd->CommonCfg.LastBSSCoexist2040.word; BssCoexistInfo.BssCoexistIe.field.InfoReq = InfoReq; BssIntolerantInfo.ElementID = IE_2040_BSS_INTOLERANT_REPORT; BssIntolerantInfo.Len = 1; BssIntolerantInfo.RegulatoryClass = get_regulatory_class(pAd); NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR,("ACT - SendBSS2040CoexistMgmtAction() allocate memory failed \n")); return; } if (Wcid == MCAST_WCID) pAddr1 = &BROADCAST_ADDR[0]; else pAddr1 = pAd->MacTab.Content[Wcid].Addr; ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); Frame.Category = CATEGORY_PUBLIC; Frame.Action = ACTION_BSS_2040_COEXIST; MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_ACTION_HDR), &Frame, sizeof(BSS_2040_COEXIST_ELEMENT), &BssCoexistInfo, sizeof(BSS_2040_INTOLERANT_CH_REPORT), &BssIntolerantInfo, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_ERROR,("ACT - SendBSS2040CoexistMgmtAction( BSSCoexist2040 = 0x%x ) \n", BssCoexistInfo.BssCoexistIe.word)); } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT VOID StaPublicAction( IN PRTMP_ADAPTER pAd, IN BSS_2040_COEXIST_IE *pBssCoexIE) { MLME_SCAN_REQ_STRUCT ScanReq; DBGPRINT(RT_DEBUG_TRACE,("ACTION - StaPeerPublicAction Bss2040Coexist = %x\n", *((PUCHAR)pBssCoexIE))); /* AP asks Station to return a 20/40 BSS Coexistence mgmt frame. So we first starts a scan, then send back 20/40 BSS Coexistence mgmt frame */ if ((pBssCoexIE->field.InfoReq == 1) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))) { /* Clear record first. After scan , will update those bit and send back to transmiter.*/ pAd->CommonCfg.BSSCoexist2040.field.InfoReq = 1; pAd->CommonCfg.BSSCoexist2040.field.Intolerant40 = 0; pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 0; /* Clear Trigger event table*/ TriEventInit(pAd); /* Fill out stuff for scan request and kick to scan*/ ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_2040_BSS_COEXIST); MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; RTMP_MLME_HANDLER(pAd); } } /* Description : Build Intolerant Channel Rerpot from Trigger event table. return : how many bytes copied. */ ULONG BuildIntolerantChannelRep( IN PRTMP_ADAPTER pAd, IN PUCHAR pDest) { ULONG FrameLen = 0; ULONG ReadOffset = 0; UCHAR i, j, k, idx = 0; /*UCHAR LastRegClass = 0xff;*/ UCHAR ChannelList[MAX_TRIGGER_EVENT]; UCHAR TmpRegClass; UCHAR RegClassArray[7] = {0, 11,12, 32, 33, 54,55}; /* Those regulatory class has channel in 2.4GHz. See Annex J.*/ RTMPZeroMemory(ChannelList, MAX_TRIGGER_EVENT); /* Find every regulatory class*/ for ( k = 0;k < 7;k++) { TmpRegClass = RegClassArray[k]; idx = 0; /* Find Channel report with the same regulatory class in 2.4GHz.*/ for ( i = 0;i < pAd->CommonCfg.TriggerEventTab.EventANo;i++) { if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid == TRUE) { if (pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass == TmpRegClass) { for (j = 0;j < idx;j++) { if (ChannelList[j] == (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel) break; } if ((j == idx)) { ChannelList[idx] = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel; idx++; } pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE; } DBGPRINT(RT_DEBUG_ERROR,("ACT - BuildIntolerantChannelRep , Total Channel number = %d \n", idx)); } } /* idx > 0 means this regulatory class has some channel report and need to copy to the pDest.*/ if (idx > 0) { /* For each regaulatory IE report, contains all channels that has the same regulatory class.*/ *(pDest + ReadOffset) = IE_2040_BSS_INTOLERANT_REPORT; /* IE*/ *(pDest + ReadOffset + 1) = 1+ idx; /* Len = RegClass byte + channel byte.*/ *(pDest + ReadOffset + 2) = TmpRegClass; /* Len = RegClass byte + channel byte.*/ RTMPMoveMemory(pDest + ReadOffset + 3, ChannelList, idx); FrameLen += (3 + idx); ReadOffset += (3 + idx); } } DBGPRINT(RT_DEBUG_ERROR,("ACT-BuildIntolerantChannelRep(Size=%ld)\n", FrameLen)); hex_dump("ACT-pDestMsg", pDest, FrameLen); return FrameLen; } /* ========================================================================== Description: After scan, Update 20/40 BSS Coexistence IE and send out. According to 802.11n D3.03 11.14.10 Parameters: ========================================================================== */ VOID Update2040CoexistFrameAndNotify( IN PRTMP_ADAPTER pAd, IN UCHAR Wcid, IN BOOLEAN bAddIntolerantCha) { BSS_2040_COEXIST_IE OldValue; DBGPRINT(RT_DEBUG_ERROR,("ACT - Update2040CoexistFrameAndNotify. BSSCoexist2040 = %x. EventANo = %d. \n", pAd->CommonCfg.BSSCoexist2040.word, pAd->CommonCfg.TriggerEventTab.EventANo)); OldValue.word = pAd->CommonCfg.BSSCoexist2040.word; /* Reset value.*/ pAd->CommonCfg.BSSCoexist2040.word = 0; if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0) pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 1; /* Need to check !!!!*/ /* How STA will set Intolerant40 if implementation dependent. Now we don't set this bit first!!!!!*/ /* So Only check BSS20WidthReq change.*/ /*if (OldValue.field.BSS20WidthReq != pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq)*/ { Send2040CoexistAction(pAd, Wcid, bAddIntolerantCha); } } /* Description : Send 20/40 BSS Coexistence Action frame If one trigger event is triggered. */ VOID Send2040CoexistAction( IN PRTMP_ADAPTER pAd, IN UCHAR Wcid, IN BOOLEAN bAddIntolerantCha) { PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; FRAME_ACTION_HDR Frame; ULONG FrameLen; UINT32 IntolerantChaRepLen; UCHAR HtLen = 1; IntolerantChaRepLen = 0; NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction() allocate memory failed \n")); return; } ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); Frame.Category = CATEGORY_PUBLIC; Frame.Action = ACTION_BSS_2040_COEXIST; /*COEXIST_2040_ACTION;*/ MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_ACTION_HDR), &Frame, 1, &BssCoexistIe, 1, &HtLen, 1, &pAd->CommonCfg.BSSCoexist2040.word, END_OF_ARGS); if (bAddIntolerantCha == TRUE) IntolerantChaRepLen = BuildIntolerantChannelRep(pAd, pOutBuffer + FrameLen); /*2009 PF#3: IOT issue with Motorola AP. It will not check the field of BSSCoexist2040.*/ /*11.14.12 Switching between 40 MHz and 20 MHz*/ DBGPRINT(RT_DEBUG_TRACE, ("IntolerantChaRepLen=%d, BSSCoexist2040=0x%x!\n", IntolerantChaRepLen, pAd->CommonCfg.BSSCoexist2040.word)); if (!((IntolerantChaRepLen == 0) && (pAd->CommonCfg.BSSCoexist2040.word == 0))) MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen + IntolerantChaRepLen); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_TRACE,("ACT - Send2040CoexistAction( BSSCoexist2040 = 0x%x ) \n", pAd->CommonCfg.BSSCoexist2040.word)); } VOID UpdateBssScanParm( IN PRTMP_ADAPTER pAd, IN OVERLAP_BSS_SCAN_IE APBssScan) { pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = le2cpu16(APBssScan.DelayFactor); /*APBssScan.DelayFactor[1] * 256 + APBssScan.DelayFactor[0];*/ /* out of range defined in MIB... So fall back to default value.*/ if ((pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor <5) || (pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor > 100)) { /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11BssWidthChanTranDelayFactor out of range !!!!) \n"));*/ pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = 5; } pAd->CommonCfg.Dot11BssWidthTriggerScanInt = le2cpu16(APBssScan.TriggerScanInt); /*APBssScan.TriggerScanInt[1] * 256 + APBssScan.TriggerScanInt[0];*/ /* out of range defined in MIB... So fall back to default value.*/ if ((pAd->CommonCfg.Dot11BssWidthTriggerScanInt < 10) ||(pAd->CommonCfg.Dot11BssWidthTriggerScanInt > 900)) { /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11BssWidthTriggerScanInt out of range !!!!) \n"));*/ pAd->CommonCfg.Dot11BssWidthTriggerScanInt = 900; } pAd->CommonCfg.Dot11OBssScanPassiveDwell = le2cpu16(APBssScan.ScanPassiveDwell); /*APBssScan.ScanPassiveDwell[1] * 256 + APBssScan.ScanPassiveDwell[0];*/ /* out of range defined in MIB... So fall back to default value.*/ if ((pAd->CommonCfg.Dot11OBssScanPassiveDwell < 5) ||(pAd->CommonCfg.Dot11OBssScanPassiveDwell > 1000)) { /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11OBssScanPassiveDwell out of range !!!!) \n"));*/ pAd->CommonCfg.Dot11OBssScanPassiveDwell = 20; } pAd->CommonCfg.Dot11OBssScanActiveDwell = le2cpu16(APBssScan.ScanActiveDwell); /*APBssScan.ScanActiveDwell[1] * 256 + APBssScan.ScanActiveDwell[0];*/ /* out of range defined in MIB... So fall back to default value.*/ if ((pAd->CommonCfg.Dot11OBssScanActiveDwell < 10) ||(pAd->CommonCfg.Dot11OBssScanActiveDwell > 1000)) { /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11OBssScanActiveDwell out of range !!!!) \n"));*/ pAd->CommonCfg.Dot11OBssScanActiveDwell = 10; } pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = le2cpu16(APBssScan.PassiveTalPerChannel); /*APBssScan.PassiveTalPerChannel[1] * 256 + APBssScan.PassiveTalPerChannel[0];*/ /* out of range defined in MIB... So fall back to default value.*/ if ((pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel < 200) ||(pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel > 10000)) { /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11OBssScanPassiveTotalPerChannel out of range !!!!) \n"));*/ pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = 200; } pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = le2cpu16(APBssScan.ActiveTalPerChannel); /*APBssScan.ActiveTalPerChannel[1] * 256 + APBssScan.ActiveTalPerChannel[0];*/ /* out of range defined in MIB... So fall back to default value.*/ if ((pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel < 20) ||(pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel > 10000)) { /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11OBssScanActiveTotalPerChannel out of range !!!!) \n"));*/ pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = 20; } pAd->CommonCfg.Dot11OBssScanActivityThre = le2cpu16(APBssScan.ScanActThre); /*APBssScan.ScanActThre[1] * 256 + APBssScan.ScanActThre[0];*/ /* out of range defined in MIB... So fall back to default value.*/ if (pAd->CommonCfg.Dot11OBssScanActivityThre > 100) { /*DBGPRINT(RT_DEBUG_ERROR,("ACT - UpdateBssScanParm( Dot11OBssScanActivityThre out of range !!!!) \n"));*/ pAd->CommonCfg.Dot11OBssScanActivityThre = 25; } pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); /*DBGPRINT(RT_DEBUG_LOUD,("ACT - UpdateBssScanParm( Dot11BssWidthTriggerScanInt = %d ) \n", pAd->CommonCfg.Dot11BssWidthTriggerScanInt));*/ } #endif /* CONFIG_STA_SUPPORT */ BOOLEAN ChannelSwitchSanityCheck( IN PRTMP_ADAPTER pAd, IN UCHAR Wcid, IN UCHAR NewChannel, IN UCHAR Secondary) { UCHAR i; if (Wcid >= MAX_LEN_OF_MAC_TABLE) return FALSE; if ((NewChannel > 7) && (Secondary == 1)) return FALSE; if ((NewChannel < 5) && (Secondary == 3)) return FALSE; /* 0. Check if new channel is in the channellist.*/ for (i = 0;i < pAd->ChannelListNum;i++) { if (pAd->ChannelList[i].Channel == NewChannel) { break; } } if (i == pAd->ChannelListNum) return FALSE; return TRUE; } VOID ChannelSwitchAction( IN PRTMP_ADAPTER pAd, IN UCHAR Wcid, IN UCHAR NewChannel, IN UCHAR Secondary) { UCHAR rf_channel = 0, rf_bw; DBGPRINT(RT_DEBUG_TRACE,("%s(): NewChannel=%d, Secondary=%d\n", __FUNCTION__, NewChannel, Secondary)); if (ChannelSwitchSanityCheck(pAd, Wcid, NewChannel, Secondary) == FALSE) return; pAd->CommonCfg.Channel = NewChannel; if (Secondary == EXTCHA_NONE) { pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 0; pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0; rf_bw = BW_20; rf_channel = pAd->CommonCfg.Channel; } /* 1. Switches to BW = 40 And Station supports BW = 40.*/ else if (((Secondary == EXTCHA_ABOVE) || (Secondary == EXTCHA_BELOW)) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1) ) { rf_bw = BW_40; #ifdef GREENAP_SUPPORT if (pAd->ApCfg.bGreenAPActive == 1) { rf_bw = BW_20; pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; } else #endif /* GREENAP_SUPPORT */ if (Secondary == EXTCHA_ABOVE) pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; else pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; rf_channel = pAd->CommonCfg.CentralChannel; pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 1; } if (rf_channel != 0) { AsicSetChannel(pAd, rf_channel, rf_bw, Secondary, FALSE); DBGPRINT(RT_DEBUG_TRACE, ("%s(): %dMHz LINK UP, CtrlChannel=%d, CentralChannel= %d \n", __FUNCTION__, (rf_bw == BW_40 ? 40 : 20), pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel)); } } #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ VOID PeerPublicAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Action = Elem->Msg[LENGTH_802_11+1]; #ifdef P2P_SUPPORT if (!P2P_INF_ON(pAd)) #endif /* P2P_SUPPORT */ if ((Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) #ifdef DOT11Z_TDLS_SUPPORT && (Action != ACTION_TDLS_DISCOVERY_RSP) #endif // DOT11Z_TDLS_SUPPORT // ) return; switch(Action) { #ifdef DOT11_N_SUPPORT #ifdef DOT11N_DRAFT3 case ACTION_BSS_2040_COEXIST: /* Format defined in IEEE 7.4.7a.1 in 11n Draf3.03*/ { /*UCHAR BssCoexist;*/ BSS_2040_COEXIST_ELEMENT *pCoexistInfo; BSS_2040_COEXIST_IE *pBssCoexistIe; BSS_2040_INTOLERANT_CH_REPORT *pIntolerantReport = NULL; if (Elem->MsgLen <= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT)) ) { DBGPRINT(RT_DEBUG_ERROR, ("ACTION - 20/40 BSS Coexistence Management Frame length too short! len = %ld!\n", Elem->MsgLen)); break; } DBGPRINT(RT_DEBUG_TRACE, ("ACTION - 20/40 BSS Coexistence Management action----> \n")); hex_dump("CoexistenceMgmtFrame", Elem->Msg, Elem->MsgLen); pCoexistInfo = (BSS_2040_COEXIST_ELEMENT *) &Elem->Msg[LENGTH_802_11+2]; /*hex_dump("CoexistInfo", (PUCHAR)pCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT));*/ if (Elem->MsgLen >= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT) + sizeof(BSS_2040_INTOLERANT_CH_REPORT))) { pIntolerantReport = (BSS_2040_INTOLERANT_CH_REPORT *)((PUCHAR)pCoexistInfo + sizeof(BSS_2040_COEXIST_ELEMENT)); } /*hex_dump("IntolerantReport ", (PUCHAR)pIntolerantReport, sizeof(BSS_2040_INTOLERANT_CH_REPORT));*/ if(pAd->CommonCfg.bBssCoexEnable == FALSE || (pAd->CommonCfg.bForty_Mhz_Intolerant == TRUE)) { DBGPRINT(RT_DEBUG_TRACE, ("20/40 BSS CoexMgmt=%d, bForty_Mhz_Intolerant=%d, ignore this action!!\n", pAd->CommonCfg.bBssCoexEnable, pAd->CommonCfg.bForty_Mhz_Intolerant)); break; } pBssCoexistIe = (BSS_2040_COEXIST_IE *)(&pCoexistInfo->BssCoexistIe); #ifdef CONFIG_AP_SUPPORT #ifdef P2P_SUPPORT if ((Elem->OpMode == OPMODE_AP) || (pAd->OpMode == OPMODE_AP)) #else IF_DEV_CONFIG_OPMODE_ON_AP(pAd) #endif /* P2P_SUPPORT */ { BOOLEAN bNeedFallBack = FALSE; /*ApPublicAction(pAd, Elem);*/ if ((pBssCoexistIe->field.BSS20WidthReq ==1) || (pBssCoexistIe->field.Intolerant40 == 1)) { bNeedFallBack = TRUE; DBGPRINT(RT_DEBUG_TRACE, ("BSS_2040_COEXIST: BSS20WidthReq=%d, Intolerant40=%d!\n", pBssCoexistIe->field.BSS20WidthReq, pBssCoexistIe->field.Intolerant40)); } else if ((pIntolerantReport) && (pIntolerantReport->Len > 1) /*&& (pIntolerantReport->RegulatoryClass == get_regulatory_class(pAd))*/) { int i; UCHAR *ptr; INT retVal; BSS_COEX_CH_RANGE coexChRange; ptr = pIntolerantReport->ChList; bNeedFallBack = TRUE; DBGPRINT(RT_DEBUG_TRACE, ("The pIntolerantReport len = %d, chlist=", pIntolerantReport->Len)); for(i =0 ; i < (pIntolerantReport->Len -1); i++, ptr++) { DBGPRINT(RT_DEBUG_TRACE, ("%d,", *ptr)); } DBGPRINT(RT_DEBUG_TRACE, ("\n")); retVal = GetBssCoexEffectedChRange(pAd, &coexChRange); if (retVal == TRUE) { ptr = pIntolerantReport->ChList; bNeedFallBack = FALSE; DBGPRINT(RT_DEBUG_TRACE, ("Check IntolerantReport Channel List in our effectedChList(%d~%d)\n", pAd->ChannelList[coexChRange.effectChStart].Channel, pAd->ChannelList[coexChRange.effectChEnd].Channel)); for(i =0 ; i < (pIntolerantReport->Len -1); i++, ptr++) { UCHAR chEntry; chEntry = *ptr; if (chEntry >= pAd->ChannelList[coexChRange.effectChStart].Channel && chEntry <= pAd->ChannelList[coexChRange.effectChEnd].Channel) { DBGPRINT(RT_DEBUG_TRACE, ("Found Intolerant channel in effect range=%d!\n", *ptr)); bNeedFallBack = TRUE; break; } } DBGPRINT(RT_DEBUG_TRACE, ("After CoexChRange Check, bNeedFallBack=%d!\n", bNeedFallBack)); } if (bNeedFallBack) { pBssCoexistIe->field.Intolerant40 = 1; pBssCoexistIe->field.BSS20WidthReq = 1; } } if (bNeedFallBack) { int apidx; NdisMoveMemory((PUCHAR)&pAd->CommonCfg.LastBSSCoexist2040, (PUCHAR)pBssCoexistIe, sizeof(BSS_2040_COEXIST_IE)); pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_SYNC; if (!(pAd->CommonCfg.Bss2040CoexistFlag & BSS_2040_COEXIST_TIMER_FIRED)) { DBGPRINT(RT_DEBUG_TRACE, ("Fire the Bss2040CoexistTimer with timeout=%ld!\n", pAd->CommonCfg.Dot11BssWidthChanTranDelay)); pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_TIMER_FIRED; /* More 5 sec for the scan report of STAs.*/ RTMPSetTimer(&pAd->CommonCfg.Bss2040CoexistTimer, (pAd->CommonCfg.Dot11BssWidthChanTranDelay + 5) * 1000); } else { DBGPRINT(RT_DEBUG_TRACE, ("Already fallback to 20MHz, Extend the timeout of Bss2040CoexistTimer!\n")); /* More 5 sec for the scan report of STAs.*/ RTMPModTimer(&pAd->CommonCfg.Bss2040CoexistTimer, (pAd->CommonCfg.Dot11BssWidthChanTranDelay + 5) * 1000); } apidx = pAd->MacTab.Content[Elem->Wcid].apidx; for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) SendBSS2040CoexistMgmtAction(pAd, MCAST_WCID, apidx, 0); } } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT #ifdef P2P_SUPPORT if ((Elem->OpMode == OPMODE_STA) || (pAd->OpMode == OPMODE_STA)) #else IF_DEV_CONFIG_OPMODE_ON_STA(pAd) #endif /* P2P_SUPPORT */ { if (INFRA_ON(pAd)) { StaPublicAction(pAd, pBssCoexistIe); } } #endif /* CONFIG_STA_SUPPORT */ } break; #endif /* DOT11N_DRAFT3 */ #endif /* DOT11_N_SUPPORT */ case ACTION_WIFI_DIRECT: #ifdef IWSC_SUPPORT if ((pAd->StaCfg.BssType == BSS_ADHOC) && NdisEqualMemory(&(Elem->Msg[LENGTH_802_11+2]), IWSC_ACTION_OUI, 4)) { MlmeEnqueue(pAd, IWSC_STATE_MACHINE, IWSC_MT2_PEER_ACTION_FRAME, Elem->MsgLen, Elem->Msg, 0); RTMP_MLME_HANDLER(pAd); break; } #endif // IWSC_SUPPORT // #ifdef P2P_SUPPORT DBGPRINT(RT_DEBUG_TRACE, ("<---- Public. Vendor OUI+type = %08x \n", *(PULONG)&Elem->Msg[LENGTH_802_11+2] )); #ifdef RT_BIG_ENDIAN if (SWAP32(*(PUINT32)&Elem->Msg[LENGTH_802_11+2]) == P2P_OUI) #else if (*(PUINT32)&Elem->Msg[LENGTH_802_11+2] == P2P_OUI) #endif /* RT_BIG_ENDIAN */ { UCHAR Subtype = Elem->Msg[LENGTH_802_11+6]; DBGPRINT(RT_DEBUG_TRACE, ("!!!! Public action frames with Vendor specific OUI = WFAP2P.Subtype = %d. \n", Subtype)); pAd->P2pCfg.bPeriodicListen = FALSE; if (pAd->P2pCfg.P2pCounter.bStartScan) { pAd->P2pCfg.P2pCounter.bStartScan = FALSE; pAd->P2pCfg.P2pCounter.bListen = FALSE; pAd->P2pCfg.P2pCounter.bNextScan = FALSE; /* update P2P Ctrl State Machine status. */ MlmeEnqueue(pAd, P2P_CTRL_STATE_MACHINE, P2P_CTRL_DISC_CANL_EVT, 0, NULL, 0); RTMP_MLME_HANDLER(pAd); } switch(Subtype) { case GO_NEGOCIATION_REQ: DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Group Nego. Req\n", __FUNCTION__)); P2pPeerGoNegoReqAction(pAd,Elem); break; case GO_NEGOCIATION_RSP: DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Group Nego. Rsp\n", __FUNCTION__)); P2pPeerGoNegoRspAction(pAd,Elem); break; case GO_NEGOCIATION_CONFIRM: DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Group Nego. Confirm\n", __FUNCTION__)); P2pPeerGoNegoConfirmAction(pAd,Elem); break; case P2P_INVITE_REQ: DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Invite Req\n", __FUNCTION__)); P2pPeerInvitesReqAction(pAd,Elem); break; case P2P_INVITE_RSP: DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Invite Rsp\n", __FUNCTION__)); P2pPeerInvitesRspAction(pAd,Elem); break; case P2P_DEV_DIS_REQ: DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Device Discovery Req\n", __FUNCTION__)); P2pPeerDevDiscoverReqAction(pAd,Elem); break; case P2P_DEV_DIS_RSP: DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Device Discovery Rsp\n", __FUNCTION__)); P2pPeerDeviceDiscRspAction(pAd,Elem); break; case P2P_PROVISION_REQ: DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Provision Req\n", __FUNCTION__)); P2pPeerProvisionReqAction(pAd,Elem); break; case P2P_PROVISION_RSP: DBGPRINT(RT_DEBUG_ERROR, ("%s : recv Provision Rsp\n", __FUNCTION__)); P2pPeerProvisionRspAction(pAd,Elem); break; default: pAd->P2pCfg.bPeriodicListen = TRUE; DBGPRINT(RT_DEBUG_ERROR,("Unknown Public action frames with Vendor specific OUI = WFAP2P.Subtype = %d \n", Subtype)); break; } } #endif /* P2P_SUPPORT */ break; #ifdef DOT11Z_TDLS_SUPPORT case ACTION_TDLS_DISCOVERY_RSP: IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { if (INFRA_ON(pAd)) { TDLS_DiscoveryRspPublicAction(pAd, Elem, Elem->Msg, Elem->MsgLen); } } break; #endif // DOT11Z_TDLS_SUPPORT // default: break; } } static VOID ReservedAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Category; if (Elem->MsgLen <= LENGTH_802_11) { return; } Category = Elem->Msg[LENGTH_802_11]; DBGPRINT(RT_DEBUG_TRACE,("Rcv reserved category(%d) Action Frame\n", Category)); hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen); } VOID PeerRMAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { #ifdef CONFIG_AP_SUPPORT #endif /* CONFIG_AP_SUPPORT */ return; } #ifdef DOT11_N_SUPPORT static VOID respond_ht_information_exchange_action( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; ULONG FrameLen; #ifdef CONFIG_AP_SUPPORT INT apidx; #endif /* CONFIG_AP_SUPPORT */ FRAME_HT_INFO HTINFOframe, *pFrame; UCHAR *pAddr; #ifdef P2P_SUPPORT MAC_TABLE_ENTRY *pEntry = NULL; #endif /* P2P_SUPPORT */ /* 2. Always send back ADDBA Response */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ if (NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_TRACE,("ACTION - respond_ht_information_exchange_action() allocate memory failed \n")); return; } /* get RA */ pFrame = (FRAME_HT_INFO *) &Elem->Msg[0]; pAddr = pFrame->Hdr.Addr2; NdisZeroMemory(&HTINFOframe, sizeof(FRAME_HT_INFO)); /* 2-1. Prepare ADDBA Response frame.*/ #ifdef P2P_SUPPORT if (VALID_WCID(Elem->Wcid)) { pEntry = &pAd->MacTab.Content[Elem->Wcid]; ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pEntry->HdrAddr2, pEntry->HdrAddr3); } #else #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { #ifdef APCLI_SUPPORT if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Elem->Wcid])) { apidx = pAd->MacTab.Content[Elem->Wcid].MatchAPCLITabIdx; ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pAddr); } else #endif /* APCLI_SUPPORT */ { apidx = pAd->MacTab.Content[Elem->Wcid].apidx; ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); } } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { if (ADHOC_ON(pAd)) ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); else ActHeaderInit(pAd, &HTINFOframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr); } #endif /* CONFIG_STA_SUPPORT */ #endif /* P2P_SUPPORT */ HTINFOframe.Category = CATEGORY_HT; HTINFOframe.Action = HT_INFO_EXCHANGE; HTINFOframe.HT_Info.Request = 0; HTINFOframe.HT_Info.Forty_MHz_Intolerant = pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant; HTINFOframe.HT_Info.STA_Channel_Width = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_HT_INFO), &HTINFOframe, END_OF_ARGS); MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); } #ifdef CONFIG_AP_SUPPORT #ifdef DOT11N_DRAFT3 VOID SendNotifyBWActionFrame( IN PRTMP_ADAPTER pAd, IN UCHAR Wcid, IN UCHAR apidx) { PUCHAR pOutBuffer = NULL; NDIS_STATUS NStatus; FRAME_ACTION_HDR Frame; ULONG FrameLen; PUCHAR pAddr1; NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR,("ACT - SendNotifyBWAction() allocate memory failed \n")); return; } if (Wcid == MCAST_WCID) pAddr1 = &BROADCAST_ADDR[0]; else pAddr1 = pAd->MacTab.Content[Wcid].Addr; ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid); Frame.Category = CATEGORY_HT; Frame.Action = NOTIFY_BW_ACTION; MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_ACTION_HDR), &Frame, END_OF_ARGS); *(pOutBuffer + FrameLen) = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; FrameLen++; MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); MlmeFreeMemory(pAd, pOutBuffer); DBGPRINT(RT_DEBUG_TRACE,("ACT - SendNotifyBWAction(NotifyBW= %d)!\n", pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth)); } #endif /* DOT11N_DRAFT3 */ #endif /* CONFIG_AP_SUPPORT */ VOID PeerHTAction( IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) { UCHAR Action = Elem->Msg[LENGTH_802_11+1]; MAC_TABLE_ENTRY *pEntry; if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) return; pEntry = &pAd->MacTab.Content[Elem->Wcid]; switch(Action) { case NOTIFY_BW_ACTION: DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Notify Channel bandwidth action----> \n")); #ifdef CONFIG_STA_SUPPORT if(pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) { /* Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps */ /* sending BW_Notify Action frame, and cause us to linkup and linkdown. */ /* In legacy mode, don't need to parse HT action frame.*/ DBGPRINT(RT_DEBUG_TRACE,("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n", Elem->Msg[LENGTH_802_11+2] )); break; } #endif /* CONFIG_STA_SUPPORT */ if (Elem->Msg[LENGTH_802_11+2] == 0) /* 7.4.8.2. if value is 1, keep the same as supported channel bandwidth. */ pEntry->HTPhyMode.field.BW = 0; else { pEntry->HTPhyMode.field.BW = pEntry->MaxHTPhyMode.field.BW & pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth; } break; case SMPS_ACTION: /* 7.3.1.25*/ DBGPRINT(RT_DEBUG_TRACE,("ACTION - SMPS action----> \n")); if (((Elem->Msg[LENGTH_802_11+2] & 0x1) == 0)) pEntry->MmpsMode = MMPS_ENABLE; else if (((Elem->Msg[LENGTH_802_11+2] & 0x2) == 0)) pEntry->MmpsMode = MMPS_STATIC; else pEntry->MmpsMode = MMPS_DYNAMIC; DBGPRINT(RT_DEBUG_TRACE,("Aid(%d) MIMO PS = %d\n", Elem->Wcid, pEntry->MmpsMode)); /* rt2860c : add something for smps change.*/ break; case SETPCO_ACTION: break; case MIMO_CHA_MEASURE_ACTION: break; case HT_INFO_EXCHANGE: { HT_INFORMATION_OCTET *pHT_info; pHT_info = (HT_INFORMATION_OCTET *) &Elem->Msg[LENGTH_802_11+2]; /* 7.4.8.10*/ DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Information Exchange action----> \n")); if (pHT_info->Request) { respond_ht_information_exchange_action(pAd, Elem); } #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { if (pHT_info->Forty_MHz_Intolerant) { Handle_BSS_Width_Trigger_Events(pAd); } } #endif /* CONFIG_AP_SUPPORT */ } break; } } /* ========================================================================== Description: Retry sending ADDBA Reqest. IRQL = DISPATCH_LEVEL Parametrs: p8023Header: if this is already 802.3 format, p8023Header is NULL Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. FALSE , then continue indicaterx at this moment. ========================================================================== */ VOID ORIBATimerTimeout( IN PRTMP_ADAPTER pAd) { MAC_TABLE_ENTRY *pEntry; INT i, total; /* FRAME_BAR FrameBar;*/ /* ULONG FrameLen;*/ /* NDIS_STATUS NStatus;*/ /* PUCHAR pOutBuffer = NULL;*/ /* USHORT Sequence;*/ UCHAR TID; #ifdef RALINK_ATE if (ATE_ON(pAd)) return; #endif /* RALINK_ATE */ total = pAd->MacTab.Size * NUM_OF_TID; for (i = 1; ((i 0)) ; i++) { if (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done) { pEntry = &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i].Wcid]; TID = pAd->BATable.BAOriEntry[i].TID; ASSERT(pAd->BATable.BAOriEntry[i].Wcid < MAX_LEN_OF_MAC_TABLE); } total --; } } VOID SendRefreshBAR( IN PRTMP_ADAPTER pAd, IN MAC_TABLE_ENTRY *pEntry) { FRAME_BAR FrameBar; ULONG FrameLen; NDIS_STATUS NStatus; PUCHAR pOutBuffer = NULL; USHORT Sequence; UCHAR i, TID; USHORT idx; BA_ORI_ENTRY *pBAEntry; for (i = 0; i BAOriWcidArray[i]; if (idx == 0) { continue; } pBAEntry = &pAd->BATable.BAOriEntry[idx]; if (pBAEntry->ORI_BA_Status == Originator_Done) { TID = pBAEntry->TID; ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE); NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ if(NStatus != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); return; } Sequence = pEntry->TxSeq[TID]; #ifdef P2P_SUPPORT BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pEntry->HdrAddr2); #else #ifdef CONFIG_AP_SUPPORT IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { #ifdef APCLI_SUPPORT if (IS_ENTRY_APCLI(pEntry)) BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].CurrentAddress); else #endif /* APCLI_SUPPORT */ BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].Bssid); } #endif /* CONFIG_AP_SUPPORT */ #ifdef CONFIG_STA_SUPPORT IF_DEV_CONFIG_OPMODE_ON_STA(pAd) BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->CurrentAddress); #endif /* CONFIG_STA_SUPPORT */ #endif /* P2P_SUPPORT */ FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function.*/ FrameBar.StartingSeq.field.StartSeq = Sequence; /* make sure sequence not clear in DEL funciton.*/ FrameBar.BarControl.TID = TID; /* make sure sequence not clear in DEL funciton.*/ MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(FRAME_BAR), &FrameBar, END_OF_ARGS); /*if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET)))*/ if (1) /* Now we always send BAR.*/ { /*MiniportMMRequestUnlock(pAd, 0, pOutBuffer, FrameLen);*/ MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | MapUserPriorityToAccessCategory[TID]), pOutBuffer, FrameLen); } MlmeFreeMemory(pAd, pOutBuffer); } } } #endif /* DOT11_N_SUPPORT */ VOID ActHeaderInit( IN PRTMP_ADAPTER pAd, IN OUT PHEADER_802_11 pHdr80211, IN PUCHAR Addr1, IN PUCHAR Addr2, IN PUCHAR Addr3) { NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); pHdr80211->FC.Type = BTYPE_MGMT; pHdr80211->FC.SubType = SUBTYPE_ACTION; COPY_MAC_ADDR(pHdr80211->Addr1, Addr1); COPY_MAC_ADDR(pHdr80211->Addr2, Addr2); COPY_MAC_ADDR(pHdr80211->Addr3, Addr3); } VOID BarHeaderInit( IN PRTMP_ADAPTER pAd, IN OUT PFRAME_BAR pCntlBar, IN PUCHAR pDA, IN PUCHAR pSA) { /* USHORT Duration;*/ NdisZeroMemory(pCntlBar, sizeof(FRAME_BAR)); pCntlBar->FC.Type = BTYPE_CNTL; pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ; pCntlBar->BarControl.MTID = 0; pCntlBar->BarControl.Compressed = 1; pCntlBar->BarControl.ACKPolicy = 0; pCntlBar->Duration = 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(FRAME_BA)); COPY_MAC_ADDR(pCntlBar->Addr1, pDA); COPY_MAC_ADDR(pCntlBar->Addr2, pSA); } /* ========================================================================== Description: Insert Category and action code into the action frame. Parametrs: 1. frame buffer pointer. 2. frame length. 3. category code of the frame. 4. action code of the frame. Return : None. ========================================================================== */ VOID InsertActField( IN PRTMP_ADAPTER pAd, OUT PUCHAR pFrameBuf, OUT PULONG pFrameLen, IN UINT8 Category, IN UINT8 ActCode) { ULONG TempLen; MakeOutgoingFrame( pFrameBuf, &TempLen, 1, &Category, 1, &ActCode, END_OF_ARGS); *pFrameLen = *pFrameLen + TempLen; return; }