mirror of
https://github.com/YikeStone/MT7601u.git
synced 2025-08-02 19:04:09 +05:30
1689 lines
52 KiB
C
1689 lines
52 KiB
C
/****************************************************************************
|
|
* Ralink Tech Inc.
|
|
* 4F, No. 2 Technology 5th Rd.
|
|
* Science-based Industrial Park
|
|
* Hsin-chu, Taiwan, R.O.C.
|
|
* (c) Copyright 2002, Ralink Technology, Inc.
|
|
*
|
|
* All rights reserved. Ralink's source code is an unpublished work and the
|
|
* use of a copyright notice does not imply otherwise. This source code
|
|
* contains confidential trade secret material of Ralink Tech. Any attemp
|
|
* or participation in deciphering, decoding, reverse engineering or in any
|
|
* way altering the source code is stricitly prohibited, unless the prior
|
|
* written consent of Ralink Technology, Inc. is obtained.
|
|
****************************************************************************
|
|
|
|
Module Name:
|
|
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 <MAX_LEN_OF_BA_ORI_TABLE) && (total > 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 <NUM_OF_TID; i++)
|
|
{
|
|
idx = pEntry->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;
|
|
}
|