blob: 306e16fdeeaeef68775e24df9bb60bb22047f38c [file] [log] [blame]
/*
*************************************************************************
* Ralink Tech Inc.
* 5F., No.36, Taiyuan St., Jhubei City,
* Hsinchu County 302,
* Taiwan, R.O.C.
*
* (c) Copyright 2002-2007, Ralink Technology, Inc.
*
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
*************************************************************************
Module Name:
dls.c
Abstract:
Handle WMM-DLS state machine
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Rory Chen 02-14-2006
Arvin Tai 06-03-2008 Modified for RT28xx
*/
#include "../rt_config.h"
/*
==========================================================================
Description:
dls state machine init, including state transition and timer init
Parameters:
Sm - pointer to the dls state machine
Note:
The state machine looks like this
DLS_IDLE
MT2_MLME_DLS_REQUEST MlmeDlsReqAction
MT2_PEER_DLS_REQUEST PeerDlsReqAction
MT2_PEER_DLS_RESPONSE PeerDlsRspAction
MT2_MLME_DLS_TEARDOWN MlmeTearDownAction
MT2_PEER_DLS_TEARDOWN PeerTearDownAction
IRQL = PASSIVE_LEVEL
==========================================================================
*/
void DlsStateMachineInit(
IN PRTMP_ADAPTER pAd,
IN STATE_MACHINE *Sm,
OUT STATE_MACHINE_FUNC Trans[])
{
UCHAR i;
StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, MAX_DLS_STATE, MAX_DLS_MSG, (STATE_MACHINE_FUNC)Drop, DLS_IDLE, DLS_MACHINE_BASE);
// the first column
StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_REQ, (STATE_MACHINE_FUNC)MlmeDlsReqAction);
StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_REQ, (STATE_MACHINE_FUNC)PeerDlsReqAction);
StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_RSP, (STATE_MACHINE_FUNC)PeerDlsRspAction);
StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)MlmeDlsTearDownAction);
StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)PeerDlsTearDownAction);
for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
{
pAd->StaCfg.DLSEntry[i].pAd = pAd;
RTMPInitTimer(pAd, &pAd->StaCfg.DLSEntry[i].Timer, GET_TIMER_FUNCTION(DlsTimeoutAction), pAd, FALSE);
}
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID MlmeDlsReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
ULONG FrameLen = 0;
HEADER_802_11 DlsReqHdr;
PRT_802_11_DLS pDLS = NULL;
UCHAR Category = CATEGORY_DLS;
UCHAR Action = ACTION_DLS_REQUEST;
ULONG tmp;
USHORT reason;
ULONG Timeout;
BOOLEAN TimerCancelled;
if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &reason))
return;
DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsReqAction() \n"));
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsReqAction() allocate memory failed \n"));
return;
}
ActHeaderInit(pAd, &DlsReqHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
// Build basic frame first
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &DlsReqHdr,
1, &Category,
1, &Action,
6, &pDLS->MacAddr,
6, pAd->CurrentAddress,
2, &pAd->StaActive.CapabilityInfo,
2, &pDLS->TimeOut,
1, &SupRateIe,
1, &pAd->MlmeAux.SupRateLen,
pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate,
END_OF_ARGS);
if (pAd->MlmeAux.ExtRateLen != 0)
{
MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1, &ExtRateIe,
1, &pAd->MlmeAux.ExtRateLen,
pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate,
END_OF_ARGS);
FrameLen += tmp;
}
#ifdef DOT11_N_SUPPORT
if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
{
UCHAR HtLen;
#ifdef RT_BIG_ENDIAN
HT_CAPABILITY_IE HtCapabilityTmp;
#endif
// add HT Capability IE
HtLen = sizeof(HT_CAPABILITY_IE);
#ifndef RT_BIG_ENDIAN
MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1, &HtCapIe,
1, &HtLen,
HtLen, &pAd->CommonCfg.HtCapability,
END_OF_ARGS);
#else
NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
*(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1, &HtCapIe,
1, &HtLen,
HtLen, &HtCapabilityTmp,
END_OF_ARGS);
#endif
FrameLen = FrameLen + tmp;
}
#endif // DOT11_N_SUPPORT //
RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
Timeout = DLS_TIMEOUT;
RTMPSetTimer(&pDLS->Timer, Timeout);
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID PeerDlsReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
ULONG FrameLen = 0;
USHORT StatusCode = MLME_SUCCESS;
HEADER_802_11 DlsRspHdr;
UCHAR Category = CATEGORY_DLS;
UCHAR Action = ACTION_DLS_RESPONSE;
ULONG tmp;
USHORT CapabilityInfo;
UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
USHORT DLSTimeOut;
SHORT i;
ULONG Timeout;
BOOLEAN TimerCancelled;
PRT_802_11_DLS pDLS = NULL;
UCHAR MaxSupportedRateIn500Kbps = 0;
UCHAR SupportedRatesLen;
UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
UCHAR HtCapabilityLen;
HT_CAPABILITY_IE HtCapability;
if (!PeerDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &DLSTimeOut,
&SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability))
return;
// supported rates array may not be sorted. sort it and find the maximum rate
for (i = 0; i < SupportedRatesLen; i++)
{
if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f))
MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f;
}
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() from %02x:%02x:%02x:%02x:%02x:%02x\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() allocate memory failed \n"));
return;
}
if (!INFRA_ON(pAd))
{
StatusCode = MLME_REQUEST_DECLINED;
}
else if (!pAd->CommonCfg.bWmmCapable)
{
StatusCode = MLME_DEST_STA_IS_NOT_A_QSTA;
}
else if (!pAd->CommonCfg.bDLSCapable)
{
StatusCode = MLME_REQUEST_DECLINED;
}
else
{
// find table to update parameters
for (i = (MAX_NUM_OF_DLS_ENTRY-1); i >= 0; i--)
{
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
{
if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
else
{
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
}
pAd->StaCfg.DLSEntry[i].Sequence = 0;
pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut;
pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut;
if (HtCapabilityLen != 0)
pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
else
pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
pDLS = &pAd->StaCfg.DLSEntry[i];
break;
}
}
// can not find in table, create a new one
if (i < 0)
{
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() can not find same entry \n"));
for (i=(MAX_NUM_OF_DLS_ENTRY - 1); i >= MAX_NUM_OF_INIT_DLS_ENTRY; i--)
{
if (!pAd->StaCfg.DLSEntry[i].Valid)
{
MAC_TABLE_ENTRY *pEntry;
UCHAR MaxSupportedRate = RATE_11;
if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
{
pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
}
else
{
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
}
pAd->StaCfg.DLSEntry[i].Sequence = 0;
pAd->StaCfg.DLSEntry[i].Valid = TRUE;
pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut;
pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut;
NdisMoveMemory(pAd->StaCfg.DLSEntry[i].MacAddr, SA, MAC_ADDR_LEN);
if (HtCapabilityLen != 0)
pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
else
pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
pDLS = &pAd->StaCfg.DLSEntry[i];
pEntry = MacTableInsertDlsEntry(pAd, SA, i);
switch (MaxSupportedRateIn500Kbps)
{
case 108: MaxSupportedRate = RATE_54; break;
case 96: MaxSupportedRate = RATE_48; break;
case 72: MaxSupportedRate = RATE_36; break;
case 48: MaxSupportedRate = RATE_24; break;
case 36: MaxSupportedRate = RATE_18; break;
case 24: MaxSupportedRate = RATE_12; break;
case 18: MaxSupportedRate = RATE_9; break;
case 12: MaxSupportedRate = RATE_6; break;
case 22: MaxSupportedRate = RATE_11; break;
case 11: MaxSupportedRate = RATE_5_5; break;
case 4: MaxSupportedRate = RATE_2; break;
case 2: MaxSupportedRate = RATE_1; break;
default: MaxSupportedRate = RATE_11; break;
}
pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
{
pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
pEntry->HTPhyMode.field.MODE = MODE_CCK;
pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
}
else
{
pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
pEntry->HTPhyMode.field.MODE = MODE_OFDM;
pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
}
pEntry->MaxHTPhyMode.field.BW = BW_20;
pEntry->MinHTPhyMode.field.BW = BW_20;
#ifdef DOT11_N_SUPPORT
pEntry->HTCapability.MCSSet[0] = 0;
pEntry->HTCapability.MCSSet[1] = 0;
// If this Entry supports 802.11n, upgrade to HT rate.
if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
{
UCHAR j, bitmask; //k,bitmask;
CHAR ii;
DBGPRINT(RT_DEBUG_TRACE, ("DLS - PeerDlsReqAction() Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
{
pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
}
else
{
pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
pAd->MacTab.fAnyStationNonGF = TRUE;
pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
}
if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
{
pEntry->MaxHTPhyMode.field.BW= BW_40;
pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
}
else
{
pEntry->MaxHTPhyMode.field.BW = BW_20;
pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
pAd->MacTab.fAnyStation20Only = TRUE;
}
// find max fixed rate
for (ii=15; ii>=0; ii--)
{
j = ii/8;
bitmask = (1<<(ii-(j*8)));
if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
{
pEntry->MaxHTPhyMode.field.MCS = ii;
break;
}
if (ii==0)
break;
}
if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
{
DBGPRINT(RT_DEBUG_OFF, ("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n",
pAd->StaCfg.DesiredTransmitSetting.field.MCS));
if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
{
// Fix MCS as HT Duplicated Mode
pEntry->MaxHTPhyMode.field.BW = 1;
pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
pEntry->MaxHTPhyMode.field.STBC = 0;
pEntry->MaxHTPhyMode.field.ShortGI = 0;
pEntry->MaxHTPhyMode.field.MCS = 32;
}
else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
{
// STA supports fixed MCS
pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
}
}
pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
if (HtCapability.HtCapInfo.ShortGIfor20)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
if (HtCapability.HtCapInfo.ShortGIfor40)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
if (HtCapability.HtCapInfo.TxSTBC)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
if (HtCapability.HtCapInfo.RxSTBC)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
if (HtCapability.ExtHtCapInfo.PlusHTC)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
}
#endif // DOT11_N_SUPPORT //
pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
pEntry->CurrTxRate = pEntry->MaxSupportedRate;
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
{
PUCHAR pTable;
UCHAR TableSize = 0;
MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
pEntry->bAutoTxRateSwitch = TRUE;
}
else
{
pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
pEntry->bAutoTxRateSwitch = FALSE;
RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
}
pEntry->RateLen = SupportedRatesLen;
break;
}
}
}
StatusCode = MLME_SUCCESS;
// can not find in table, create a new one
if (i < 0)
{
StatusCode = MLME_QOS_UNSPECIFY;
DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() DLSEntry table full(only can support %d DLS session) \n", MAX_NUM_OF_DLS_ENTRY - MAX_NUM_OF_INIT_DLS_ENTRY));
}
else
{
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() use entry(%d) %02x:%02x:%02x:%02x:%02x:%02x\n",
i, SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
}
}
ActHeaderInit(pAd, &DlsRspHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
// Build basic frame first
if (StatusCode == MLME_SUCCESS)
{
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &DlsRspHdr,
1, &Category,
1, &Action,
2, &StatusCode,
6, SA,
6, pAd->CurrentAddress,
2, &pAd->StaActive.CapabilityInfo,
1, &SupRateIe,
1, &pAd->MlmeAux.SupRateLen,
pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate,
END_OF_ARGS);
if (pAd->MlmeAux.ExtRateLen != 0)
{
MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1, &ExtRateIe,
1, &pAd->MlmeAux.ExtRateLen,
pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate,
END_OF_ARGS);
FrameLen += tmp;
}
#ifdef DOT11_N_SUPPORT
if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
{
UCHAR HtLen;
#ifdef RT_BIG_ENDIAN
HT_CAPABILITY_IE HtCapabilityTmp;
#endif
// add HT Capability IE
HtLen = sizeof(HT_CAPABILITY_IE);
#ifndef RT_BIG_ENDIAN
MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1, &HtCapIe,
1, &HtLen,
HtLen, &pAd->CommonCfg.HtCapability,
END_OF_ARGS);
#else
NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
*(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
1, &HtCapIe,
1, &HtLen,
HtLen, &HtCapabilityTmp,
END_OF_ARGS);
#endif
FrameLen = FrameLen + tmp;
}
#endif // DOT11_N_SUPPORT //
if (pDLS && (pDLS->Status != DLS_FINISH))
{
RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
Timeout = DLS_TIMEOUT;
RTMPSetTimer(&pDLS->Timer, Timeout);
}
}
else
{
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &DlsRspHdr,
1, &Category,
1, &Action,
2, &StatusCode,
6, SA,
6, pAd->CurrentAddress,
END_OF_ARGS);
}
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID PeerDlsRspAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
USHORT CapabilityInfo;
UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
USHORT StatusCode;
SHORT i;
BOOLEAN TimerCancelled;
UCHAR MaxSupportedRateIn500Kbps = 0;
UCHAR SupportedRatesLen;
UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
UCHAR HtCapabilityLen;
HT_CAPABILITY_IE HtCapability;
if (!pAd->CommonCfg.bDLSCapable)
return;
if (!INFRA_ON(pAd))
return;
if (!PeerDlsRspSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &StatusCode,
&SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability))
return;
// supported rates array may not be sorted. sort it and find the maximum rate
for (i=0; i<SupportedRatesLen; i++)
{
if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f))
MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f;
}
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d, CapabilityInfo=0x%x\n",
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], StatusCode, CapabilityInfo));
for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
{
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
{
if (StatusCode == MLME_SUCCESS)
{
MAC_TABLE_ENTRY *pEntry;
UCHAR MaxSupportedRate = RATE_11;
pEntry = MacTableInsertDlsEntry(pAd, SA, i);
switch (MaxSupportedRateIn500Kbps)
{
case 108: MaxSupportedRate = RATE_54; break;
case 96: MaxSupportedRate = RATE_48; break;
case 72: MaxSupportedRate = RATE_36; break;
case 48: MaxSupportedRate = RATE_24; break;
case 36: MaxSupportedRate = RATE_18; break;
case 24: MaxSupportedRate = RATE_12; break;
case 18: MaxSupportedRate = RATE_9; break;
case 12: MaxSupportedRate = RATE_6; break;
case 22: MaxSupportedRate = RATE_11; break;
case 11: MaxSupportedRate = RATE_5_5; break;
case 4: MaxSupportedRate = RATE_2; break;
case 2: MaxSupportedRate = RATE_1; break;
default: MaxSupportedRate = RATE_11; break;
}
pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
{
pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
pEntry->HTPhyMode.field.MODE = MODE_CCK;
pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
}
else
{
pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
pEntry->HTPhyMode.field.MODE = MODE_OFDM;
pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
}
pEntry->MaxHTPhyMode.field.BW = BW_20;
pEntry->MinHTPhyMode.field.BW = BW_20;
#ifdef DOT11_N_SUPPORT
pEntry->HTCapability.MCSSet[0] = 0;
pEntry->HTCapability.MCSSet[1] = 0;
// If this Entry supports 802.11n, upgrade to HT rate.
if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
{
UCHAR j, bitmask; //k,bitmask;
CHAR ii;
DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
{
pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
}
else
{
pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
pAd->MacTab.fAnyStationNonGF = TRUE;
pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
}
if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
{
pEntry->MaxHTPhyMode.field.BW= BW_40;
pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
}
else
{
pEntry->MaxHTPhyMode.field.BW = BW_20;
pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
pAd->MacTab.fAnyStation20Only = TRUE;
}
// find max fixed rate
for (ii=15; ii>=0; ii--)
{
j = ii/8;
bitmask = (1<<(ii-(j*8)));
if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
{
pEntry->MaxHTPhyMode.field.MCS = ii;
break;
}
if (ii==0)
break;
}
if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
{
if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
{
// Fix MCS as HT Duplicated Mode
pEntry->MaxHTPhyMode.field.BW = 1;
pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
pEntry->MaxHTPhyMode.field.STBC = 0;
pEntry->MaxHTPhyMode.field.ShortGI = 0;
pEntry->MaxHTPhyMode.field.MCS = 32;
}
else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
{
// STA supports fixed MCS
pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
}
}
pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
if (HtCapability.HtCapInfo.ShortGIfor20)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
if (HtCapability.HtCapInfo.ShortGIfor40)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
if (HtCapability.HtCapInfo.TxSTBC)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
if (HtCapability.HtCapInfo.RxSTBC)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
if (HtCapability.ExtHtCapInfo.PlusHTC)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
}
#endif // DOT11_N_SUPPORT //
pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
pEntry->CurrTxRate = pEntry->MaxSupportedRate;
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
{
PUCHAR pTable;
UCHAR TableSize = 0;
MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
pEntry->bAutoTxRateSwitch = TRUE;
}
else
{
pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
pEntry->bAutoTxRateSwitch = FALSE;
RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
}
pEntry->RateLen = SupportedRatesLen;
if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
{
// If support WPA or WPA2, start STAKey hand shake,
// If failed hand shake, just tear down peer DLS
if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS)
{
MLME_DLS_REQ_STRUCT MlmeDlsReq;
USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT;
DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n"));
}
else
{
pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n"));
}
}
else
{
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
}
//initialize seq no for DLS frames.
pAd->StaCfg.DLSEntry[i].Sequence = 0;
if (HtCapabilityLen != 0)
pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
else
pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
}
else
{
// DLS setup procedure failed.
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode));
}
}
}
if (i >= MAX_NUM_OF_INIT_DLS_ENTRY)
{
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() update timeout value \n"));
for (i=(MAX_NUM_OF_DLS_ENTRY-1); i>=MAX_NUM_OF_INIT_DLS_ENTRY; i--)
{
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
{
if (StatusCode == MLME_SUCCESS)
{
MAC_TABLE_ENTRY *pEntry;
UCHAR MaxSupportedRate = RATE_11;
pEntry = MacTableInsertDlsEntry(pAd, SA, i);
switch (MaxSupportedRateIn500Kbps)
{
case 108: MaxSupportedRate = RATE_54; break;
case 96: MaxSupportedRate = RATE_48; break;
case 72: MaxSupportedRate = RATE_36; break;
case 48: MaxSupportedRate = RATE_24; break;
case 36: MaxSupportedRate = RATE_18; break;
case 24: MaxSupportedRate = RATE_12; break;
case 18: MaxSupportedRate = RATE_9; break;
case 12: MaxSupportedRate = RATE_6; break;
case 22: MaxSupportedRate = RATE_11; break;
case 11: MaxSupportedRate = RATE_5_5; break;
case 4: MaxSupportedRate = RATE_2; break;
case 2: MaxSupportedRate = RATE_1; break;
default: MaxSupportedRate = RATE_11; break;
}
pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
{
pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
pEntry->HTPhyMode.field.MODE = MODE_CCK;
pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
}
else
{
pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
pEntry->HTPhyMode.field.MODE = MODE_OFDM;
pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
}
pEntry->MaxHTPhyMode.field.BW = BW_20;
pEntry->MinHTPhyMode.field.BW = BW_20;
#ifdef DOT11_N_SUPPORT
pEntry->HTCapability.MCSSet[0] = 0;
pEntry->HTCapability.MCSSet[1] = 0;
// If this Entry supports 802.11n, upgrade to HT rate.
if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
{
UCHAR j, bitmask; //k,bitmask;
CHAR ii;
DBGPRINT(RT_DEBUG_TRACE, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
{
pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
}
else
{
pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
pAd->MacTab.fAnyStationNonGF = TRUE;
pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
}
if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
{
pEntry->MaxHTPhyMode.field.BW= BW_40;
pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
}
else
{
pEntry->MaxHTPhyMode.field.BW = BW_20;
pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
pAd->MacTab.fAnyStation20Only = TRUE;
}
// find max fixed rate
for (ii=15; ii>=0; ii--)
{
j = ii/8;
bitmask = (1<<(ii-(j*8)));
if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
{
pEntry->MaxHTPhyMode.field.MCS = ii;
break;
}
if (ii==0)
break;
}
if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
{
DBGPRINT(RT_DEBUG_OFF, ("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n",
pAd->StaCfg.DesiredTransmitSetting.field.MCS));
if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
{
// Fix MCS as HT Duplicated Mode
pEntry->MaxHTPhyMode.field.BW = 1;
pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
pEntry->MaxHTPhyMode.field.STBC = 0;
pEntry->MaxHTPhyMode.field.ShortGI = 0;
pEntry->MaxHTPhyMode.field.MCS = 32;
}
else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
{
// STA supports fixed MCS
pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
}
}
pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
if (HtCapability.HtCapInfo.ShortGIfor20)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
if (HtCapability.HtCapInfo.ShortGIfor40)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
if (HtCapability.HtCapInfo.TxSTBC)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
if (HtCapability.HtCapInfo.RxSTBC)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
if (HtCapability.ExtHtCapInfo.PlusHTC)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
}
#endif // DOT11_N_SUPPORT //
pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
pEntry->CurrTxRate = pEntry->MaxSupportedRate;
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
{
PUCHAR pTable;
UCHAR TableSize = 0;
MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
pEntry->bAutoTxRateSwitch = TRUE;
}
else
{
pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
pEntry->bAutoTxRateSwitch = FALSE;
RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
}
pEntry->RateLen = SupportedRatesLen;
if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
{
// If support WPA or WPA2, start STAKey hand shake,
// If failed hand shake, just tear down peer DLS
if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS)
{
MLME_DLS_REQ_STRUCT MlmeDlsReq;
USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT;
DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n"));
}
else
{
pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n"));
}
}
else
{
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
}
pAd->StaCfg.DLSEntry[i].Sequence = 0;
if (HtCapabilityLen != 0)
pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
else
pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
}
else
{
// DLS setup procedure failed.
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode));
}
}
}
}
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID MlmeDlsTearDownAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
ULONG FrameLen = 0;
UCHAR Category = CATEGORY_DLS;
UCHAR Action = ACTION_DLS_TEARDOWN;
USHORT ReasonCode = REASON_QOS_UNSPECIFY;
HEADER_802_11 DlsTearDownHdr;
PRT_802_11_DLS pDLS;
BOOLEAN TimerCancelled;
UCHAR i;
if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &ReasonCode))
return;
DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsTearDownAction() with ReasonCode=%d \n", ReasonCode));
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsTearDownAction() allocate memory failed \n"));
return;
}
ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
// Build basic frame first
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &DlsTearDownHdr,
1, &Category,
1, &Action,
6, &pDLS->MacAddr,
6, pAd->CurrentAddress,
2, &ReasonCode,
END_OF_ARGS);
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
// Remove key in local dls table entry
for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
{
if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
{
MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
}
}
// clear peer dls table entry
for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++)
{
if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
{
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
}
}
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID PeerDlsTearDownAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
USHORT ReasonCode;
UINT i;
BOOLEAN TimerCancelled;
if (!pAd->CommonCfg.bDLSCapable)
return;
if (!INFRA_ON(pAd))
return;
if (!PeerDlsTearDownSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &ReasonCode))
return;
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x with ReasonCode=%d\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], ReasonCode));
// clear local dls table entry
for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
{
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
{
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
//AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
//AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
}
}
// clear peer dls table entry
for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
{
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
{
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
//AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
//AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
}
}
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID RTMPCheckDLSTimeOut(
IN PRTMP_ADAPTER pAd)
{
ULONG i;
MLME_DLS_REQ_STRUCT MlmeDlsReq;
USHORT reason = REASON_QOS_UNSPECIFY;
if (! pAd->CommonCfg.bDLSCapable)
return;
if (! INFRA_ON(pAd))
return;
// If timeout value is equaled to zero, it means always not be timeout.
// update local dls table entry
for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
{
if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
&& (pAd->StaCfg.DLSEntry[i].TimeOut != 0))
{
pAd->StaCfg.DLSEntry[i].CountDownTimer --;
if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0)
{
reason = REASON_QOS_REQUEST_TIMEOUT;
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
}
}
}
// update peer dls table entry
for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
{
if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
&& (pAd->StaCfg.DLSEntry[i].TimeOut != 0))
{
pAd->StaCfg.DLSEntry[i].CountDownTimer --;
if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0)
{
reason = REASON_QOS_REQUEST_TIMEOUT;
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
}
}
}
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
BOOLEAN RTMPRcvFrameDLSCheck(
IN PRTMP_ADAPTER pAd,
IN PHEADER_802_11 pHeader,
IN ULONG Len,
IN PRT28XX_RXD_STRUC pRxD)
{
ULONG i;
BOOLEAN bFindEntry = FALSE;
BOOLEAN bSTAKeyFrame = FALSE;
PEAPOL_PACKET pEap;
PUCHAR pProto, pAddr = NULL;
PUCHAR pSTAKey = NULL;
UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY];
UCHAR Mic[16], OldMic[16];
UCHAR digest[80];
UCHAR DlsPTK[80];
UCHAR temp[64];
BOOLEAN TimerCancelled;
CIPHER_KEY PairwiseKey;
if (! pAd->CommonCfg.bDLSCapable)
return bSTAKeyFrame;
if (! INFRA_ON(pAd))
return bSTAKeyFrame;
if (Len < LENGTH_802_11 + 6 + 2) /* LENGTH_802_11 + LLC + EAPOL protocol type */
return bSTAKeyFrame;
pProto = (PUCHAR)pHeader + LENGTH_802_11;
if ((pHeader->FC.SubType & 0x08))
pProto += 2; /* QOS Control field */
/* Skip 4-bytes for HTC */
if (pHeader->FC.Order && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
{
pProto += 4;
}
/* L2PAD bit on will pad 2 bytes at LLC */
if (pRxD->L2PAD)
{
pProto += 2;
}
pProto += 6; /* 0xAA 0xAA 0xAA 0x00 0x00 0x00 */
if ((!(pHeader->FC.SubType & 0x08)) && (!RTMPEqualMemory(EAPOL, pProto, 2)))
return bSTAKeyFrame;
pAddr = pHeader->Addr2;
if (RTMPEqualMemory(EAPOL, pProto, 2) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA))
{
pEap = (PEAPOL_PACKET) (pProto + 2);
DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff Len=%ld, DataLen=%d, KeyMic=%d, Install=%d, KeyAck=%d, Secure=%d, EKD_DL=%d, Error=%d, Request=%d\n", Len,
(LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16),
pEap->KeyDesc.KeyInfo.KeyMic,
pEap->KeyDesc.KeyInfo.Install,
pEap->KeyDesc.KeyInfo.KeyAck,
pEap->KeyDesc.KeyInfo.Secure,
pEap->KeyDesc.KeyInfo.EKD_DL,
pEap->KeyDesc.KeyInfo.Error,
pEap->KeyDesc.KeyInfo.Request));
if ((Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16)) && pEap->KeyDesc.KeyInfo.KeyMic
&& pEap->KeyDesc.KeyInfo.Install && pEap->KeyDesc.KeyInfo.KeyAck && pEap->KeyDesc.KeyInfo.Secure
&& pEap->KeyDesc.KeyInfo.EKD_DL && !pEap->KeyDesc.KeyInfo.Error && !pEap->KeyDesc.KeyInfo.Request)
{
// First validate replay counter, only accept message with larger replay counter
// Let equal pass, some AP start with all zero replay counter
NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
if ((RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) &&
(RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
return bSTAKeyFrame;
//RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter (%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n",
pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2],
pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4], pAd->StaCfg.ReplayCounter[5],
pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1]));
// put these code segment to get the replay counter
if (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)
return bSTAKeyFrame;
// Check MIC value
// Save the MIC and replace with zero
// use proprietary PTK
NdisZeroMemory(temp, 64);
NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
WpaDerivePTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
NdisMoveMemory(OldMic, pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
NdisZeroMemory(pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
{
// AES
HMAC_SHA1(DlsPTK, LEN_EAP_MICK, (PUCHAR) pEap, pEap->Body_Len[1] + 4, digest, SHA1_DIGEST_SIZE);
NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
}
else
{
HMAC_MD5(DlsPTK, LEN_EAP_MICK, (PUCHAR) pEap, pEap->Body_Len[1] + 4, Mic, MD5_DIGEST_SIZE);
}
if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
{
DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in Msg1 of STAKey handshake! \n"));
return bSTAKeyFrame;
}
else
DBGPRINT(RT_DEBUG_TRACE, ("MIC VALID in Msg1 of STAKey handshake! \n"));
if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0C)
&& (pEap->KeyDesc.KeyData[4] == 0x43) && (pEap->KeyDesc.KeyData[5] == 0x02))
{
pAddr = pEap->KeyDesc.KeyData + 8; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2)
pSTAKey = pEap->KeyDesc.KeyData + 14; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6)
DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%ld, KeyDataLen=%d\n",
pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1]));
bSTAKeyFrame = TRUE;
}
}
else if (Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE))
{
RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter 2(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n",
pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2],
pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4], pAd->StaCfg.ReplayCounter[5],
pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1]));
}
}
// If timeout value is equaled to zero, it means always not be timeout.
// update local dls table entry
for (i= 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
{
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
{
if (bSTAKeyFrame)
{
PMAC_TABLE_ENTRY pEntry;
// STAKey frame, add pairwise key table
pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
PairwiseKey.KeyLen = LEN_TKIP_EK;
NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK);
NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK);
NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK);
//PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg;
if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
PairwiseKey.CipherAlg = CIPHER_TKIP;
else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
PairwiseKey.CipherAlg = CIPHER_AES;
pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE);
//AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast
//AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
// Add Pair-wise key to Asic
#ifdef RTMP_MAC_PCI
AsicAddPairwiseKeyEntry(pAd,
pAd->StaCfg.DLSEntry[i].MacAddr,
(UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID,
&PairwiseKey);
RTMPAddWcidAttributeEntry(pAd,
BSS0,
0,
PairwiseKey.CipherAlg,
pEntry);
#endif // RTMP_MAC_PCI //
NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY));
DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Peer STA MAC Address STAKey) \n"));
RTMPSendSTAKeyHandShake(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Initiator side)\n"));
}
else
{
// Data frame, update timeout value
if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
{
pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
//AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
}
}
bFindEntry = TRUE;
}
}
// update peer dls table entry
for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
{
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
{
if (bSTAKeyFrame)
{
PMAC_TABLE_ENTRY pEntry = NULL;
// STAKey frame, add pairwise key table, and send STAkey Msg-2
pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
PairwiseKey.KeyLen = LEN_TKIP_EK;
NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK);
NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK);
NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK);
//PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg;
if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
PairwiseKey.CipherAlg = CIPHER_TKIP;
else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
PairwiseKey.CipherAlg = CIPHER_AES;
pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE);
//AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast
//AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
// Add Pair-wise key to Asic
#ifdef RTMP_MAC_PCI
AsicAddPairwiseKeyEntry(pAd,
pAd->StaCfg.DLSEntry[i].MacAddr,
(UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID,
&PairwiseKey);
RTMPAddWcidAttributeEntry(pAd,
BSS0,
0,
PairwiseKey.CipherAlg,
pEntry);
#endif // RTMP_MAC_PCI //
NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY));
DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Initiator STA MAC Address STAKey)\n"));
// If support WPA or WPA2, start STAKey hand shake,
// If failed hand shake, just tear down peer DLS
if (RTMPSendSTAKeyHandShake(pAd, pAddr) != NDIS_STATUS_SUCCESS)
{
MLME_DLS_REQ_STRUCT MlmeDlsReq;
USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT;
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
}
else
{
DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Peer side)\n"));
}
}
else
{
// Data frame, update timeout value
if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
{
pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
}
}
bFindEntry = TRUE;
}
}
return bSTAKeyFrame;
}
/*
========================================================================
Routine Description:
Check if the frame can be sent through DLS direct link interface
Arguments:
pAd Pointer to adapter
Return Value:
DLS entry index
Note:
========================================================================
*/
INT RTMPCheckDLSFrame(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pDA)
{
INT rval = -1;
INT i;
if (!pAd->CommonCfg.bDLSCapable)
return rval;
if (!INFRA_ON(pAd))
return rval;
do{
// check local dls table entry
for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
{
if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
{
rval = i;
break;
}
}
// check peer dls table entry
for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
{
if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
{
rval = i;
break;
}
}
} while (FALSE);
return rval;
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID RTMPSendDLSTearDownFrame(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pDA)
{
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
HEADER_802_11 DlsTearDownHdr;
ULONG FrameLen = 0;
USHORT Reason = REASON_QOS_QSTA_LEAVING_QBSS;
UCHAR Category = CATEGORY_DLS;
UCHAR Action = ACTION_DLS_TEARDOWN;
UCHAR i = 0;
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
return;
DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame \n"));
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("ASSOC - RTMPSendDLSTearDownFrame() allocate memory failed \n"));
return;
}
ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &DlsTearDownHdr,
1, &Category,
1, &Action,
6, pDA,
6, pAd->CurrentAddress,
2, &Reason,
END_OF_ARGS);
MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
// Remove key in local dls table entry
for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
{
if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
&& MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
{
MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
}
}
// Remove key in peer dls table entry
for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
{
if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
&& MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
{
MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
}
}
DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame and remove key in (i=%d) \n", i));
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
NDIS_STATUS RTMPSendSTAKeyRequest(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pDA)
{
UCHAR Header802_3[14];
NDIS_STATUS NStatus;
ULONG FrameLen = 0;
EAPOL_PACKET Packet;
UCHAR Mic[16];
UCHAR digest[80];
PUCHAR pOutBuffer = NULL;
PNDIS_PACKET pNdisPacket;
UCHAR temp[64];
UCHAR DlsPTK[80];
DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyRequest() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5]));
pAd->Sequence ++;
MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
// Zero message body
NdisZeroMemory(&Packet, sizeof(Packet));
Packet.ProVer = EAPOL_VER;
Packet.ProType = EAPOLKey;
Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN; // data field contain KDE andPeer MAC address
// STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE)
if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
{
Packet.KeyDesc.Type = WPA1_KEY_DESC;
}
else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
{
Packet.KeyDesc.Type = WPA2_KEY_DESC;
}
// Key descriptor version
Packet.KeyDesc.KeyInfo.KeyDescVer =
(((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
Packet.KeyDesc.KeyInfo.KeyMic = 1;
Packet.KeyDesc.KeyInfo.Secure = 1;
Packet.KeyDesc.KeyInfo.Request = 1;
Packet.KeyDesc.KeyDataLen[1] = 12;
// use our own OUI to distinguish proprietary with standard.
Packet.KeyDesc.KeyData[0] = 0xDD;
Packet.KeyDesc.KeyData[1] = 0x0A;
Packet.KeyDesc.KeyData[2] = 0x00;
Packet.KeyDesc.KeyData[3] = 0x0C;
Packet.KeyDesc.KeyData[4] = 0x43;
Packet.KeyDesc.KeyData[5] = 0x03;
NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN);
NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY);
// Allocate buffer for transmitting message
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if (NStatus != NDIS_STATUS_SUCCESS)
return NStatus;
// Prepare EAPOL frame for MIC calculation
// Be careful, only EAPOL frame is counted for MIC calculation
MakeOutgoingFrame(pOutBuffer, &FrameLen,
Packet.Body_Len[1] + 4, &Packet,
END_OF_ARGS);
// use proprietary PTK
NdisZeroMemory(temp, 64);
NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
WpaDerivePTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
// calculate MIC
if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
{
// AES
NdisZeroMemory(digest, sizeof(digest));
HMAC_SHA1(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE);
NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC);
}
else
{
NdisZeroMemory(Mic, sizeof(Mic));
HMAC_MD5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE);
NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
}
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(Header802_3), Header802_3,
Packet.Body_Len[1] + 4, &Packet,
END_OF_ARGS);
NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen);
if (NStatus == NDIS_STATUS_SUCCESS)
{
RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID);
STASendPacket(pAd, pNdisPacket);
RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
}
MlmeFreeMemory(pAd, pOutBuffer);
DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyRequest- Send STAKey request (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen));
return NStatus;
}
/*
==========================================================================
Description:
IRQL = DISPATCH_LEVEL
==========================================================================
*/
NDIS_STATUS RTMPSendSTAKeyHandShake(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pDA)
{
UCHAR Header802_3[14];
NDIS_STATUS NStatus;
ULONG FrameLen = 0;
EAPOL_PACKET Packet;
UCHAR Mic[16];
UCHAR digest[80];
PUCHAR pOutBuffer = NULL;
PNDIS_PACKET pNdisPacket;
UCHAR temp[64];
UCHAR DlsPTK[80]; // Due to dirver can not get PTK, use proprietary PTK
DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyHandShake() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5]));
pAd->Sequence ++;
MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
// Zero message body
NdisZeroMemory(&Packet, sizeof(Packet));
Packet.ProVer = EAPOL_VER;
Packet.ProType = EAPOLKey;
Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN; // data field contain KDE and Peer MAC address
// STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE)
if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
{
Packet.KeyDesc.Type = WPA1_KEY_DESC;
}
else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
{
Packet.KeyDesc.Type = WPA2_KEY_DESC;
}
// Key descriptor version
Packet.KeyDesc.KeyInfo.KeyDescVer =
(((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
Packet.KeyDesc.KeyInfo.KeyMic = 1;
Packet.KeyDesc.KeyInfo.Secure = 1;
Packet.KeyDesc.KeyDataLen[1] = 12;
// use our own OUI to distinguish proprietary with standard.
Packet.KeyDesc.KeyData[0] = 0xDD;
Packet.KeyDesc.KeyData[1] = 0x0A;
Packet.KeyDesc.KeyData[2] = 0x00;
Packet.KeyDesc.KeyData[3] = 0x0C;
Packet.KeyDesc.KeyData[4] = 0x43;
Packet.KeyDesc.KeyData[5] = 0x03;
NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN);
NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY);
// Allocate buffer for transmitting message
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if (NStatus != NDIS_STATUS_SUCCESS)
return NStatus;
// Prepare EAPOL frame for MIC calculation
// Be careful, only EAPOL frame is counted for MIC calculation
MakeOutgoingFrame(pOutBuffer, &FrameLen,
Packet.Body_Len[1] + 4, &Packet,
END_OF_ARGS);
// use proprietary PTK
NdisZeroMemory(temp, 64);
NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
WpaDerivePTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
// calculate MIC
if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
{
// AES
NdisZeroMemory(digest, sizeof(digest));
HMAC_SHA1(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE);
NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC);
}
else
{
NdisZeroMemory(Mic, sizeof(Mic));
HMAC_MD5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE);
NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
}
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(Header802_3), Header802_3,
Packet.Body_Len[1] + 4, &Packet,
END_OF_ARGS);
NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen);
if (NStatus == NDIS_STATUS_SUCCESS)
{
RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID);
STASendPacket(pAd, pNdisPacket);
RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
}
MlmeFreeMemory(pAd, pOutBuffer);
DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyHandShake- Send STAKey Message-2 (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen));
return NStatus;
}
VOID DlsTimeoutAction(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
MLME_DLS_REQ_STRUCT MlmeDlsReq;
USHORT reason;
PRT_802_11_DLS pDLS = (PRT_802_11_DLS)FunctionContext;
PRTMP_ADAPTER pAd = pDLS->pAd;
DBGPRINT(RT_DEBUG_TRACE, ("DlsTimeout - Tear down DLS links (%02x:%02x:%02x:%02x:%02x:%02x)\n",
pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5]));
if ((pDLS) && (pDLS->Valid))
{
reason = REASON_QOS_REQUEST_TIMEOUT;
pDLS->Valid = FALSE;
pDLS->Status = DLS_NONE;
DlsParmFill(pAd, &MlmeDlsReq, pDLS, reason);
MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
RTMP_MLME_HANDLER(pAd);
}
}
/*
================================================================
Description : because DLS and CLI share the same WCID table in ASIC.
Mesh entry also insert to pAd->MacTab.content[]. Such is marked as ValidAsDls = TRUE.
Also fills the pairwise key.
Because front MAX_AID_BA entries have direct mapping to BAEntry, which is only used as CLI. So we insert Dls
from index MAX_AID_BA.
================================================================
*/
MAC_TABLE_ENTRY *MacTableInsertDlsEntry(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pAddr,
IN UINT DlsEntryIdx)
{
PMAC_TABLE_ENTRY pEntry = NULL;
DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableInsertDlsEntry\n"));
// if FULL, return
if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
return NULL;
do
{
if((pEntry = DlsEntryTableLookup(pAd, pAddr, TRUE)) != NULL)
break;
// allocate one MAC entry
pEntry = MacTableInsertEntry(pAd, pAddr, DlsEntryIdx + MIN_NET_DEVICE_FOR_DLS, TRUE);
if (pEntry)
{
pAd->StaCfg.DLSEntry[DlsEntryIdx].MacTabMatchWCID = pEntry->Aid;
pEntry->MatchDlsEntryIdx = DlsEntryIdx;
pEntry->AuthMode = pAd->StaCfg.AuthMode;
pEntry->WepStatus = pAd->StaCfg.WepStatus;
pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertDlsEntry - allocate entry #%d, Total= %d\n",pEntry->Aid, pAd->MacTab.Size));
// If legacy WEP is used, set pair-wise cipherAlg into WCID attribute table for this entry
if ((pEntry->ValidAsDls) && (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled))
{
UCHAR KeyIdx = 0;
UCHAR CipherAlg = 0;
KeyIdx = pAd->StaCfg.DefaultKeyId;
CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
RTMPAddWcidAttributeEntry(pAd,
BSS0,
pAd->StaCfg.DefaultKeyId,
pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
pEntry);
}
break;
}
} while(FALSE);
DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableInsertDlsEntry\n"));
return pEntry;
}
/*
==========================================================================
Description:
Delete all Mesh Entry in pAd->MacTab
==========================================================================
*/
BOOLEAN MacTableDeleteDlsEntry(
IN PRTMP_ADAPTER pAd,
IN USHORT wcid,
IN PUCHAR pAddr)
{
DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableDeleteDlsEntry\n"));
if (!VALID_WCID(wcid))
return FALSE;
MacTableDeleteEntry(pAd, wcid, pAddr);
DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableDeleteDlsEntry\n"));
return TRUE;
}
MAC_TABLE_ENTRY *DlsEntryTableLookup(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pAddr,
IN BOOLEAN bResetIdelCount)
{
ULONG HashIdx;
MAC_TABLE_ENTRY *pEntry = NULL;
RTMP_SEM_LOCK(&pAd->MacTabLock);
HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
pEntry = pAd->MacTab.Hash[HashIdx];
while (pEntry)
{
if ((pEntry->ValidAsDls == TRUE)
&& MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
{
if(bResetIdelCount)
pEntry->NoDataIdleCount = 0;
break;
}
else
pEntry = pEntry->pNext;
}
RTMP_SEM_UNLOCK(&pAd->MacTabLock);
return pEntry;
}
MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid(
IN PRTMP_ADAPTER pAd,
IN UCHAR wcid,
IN PUCHAR pAddr,
IN BOOLEAN bResetIdelCount)
{
ULONG DLsIndex;
PMAC_TABLE_ENTRY pCurEntry = NULL;
PMAC_TABLE_ENTRY pEntry = NULL;
if (!VALID_WCID(wcid))
return NULL;
RTMP_SEM_LOCK(&pAd->MacTabLock);
do
{
pCurEntry = &pAd->MacTab.Content[wcid];
DLsIndex = 0xff;
if ((pCurEntry) && (pCurEntry->ValidAsDls== TRUE))
{
DLsIndex = pCurEntry->MatchDlsEntryIdx;
}
if (DLsIndex == 0xff)
break;
if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddr))
{
if(bResetIdelCount)
pCurEntry->NoDataIdleCount = 0;
pEntry = pCurEntry;
break;
}
} while(FALSE);
RTMP_SEM_UNLOCK(&pAd->MacTabLock);
return pEntry;
}
INT Set_DlsEntryInfo_Display_Proc(
IN PRTMP_ADAPTER pAd,
IN PUCHAR arg)
{
INT i;
DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-8s\n", "MAC", "TIMEOUT\n"));
for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
{
if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
{
PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[pAd->StaCfg.DLSEntry[i].MacTabMatchWCID];
DBGPRINT(RT_DEBUG_OFF, ("%02x:%02x:%02x:%02x:%02x:%02x ",
pAd->StaCfg.DLSEntry[i].MacAddr[0], pAd->StaCfg.DLSEntry[i].MacAddr[1], pAd->StaCfg.DLSEntry[i].MacAddr[2],
pAd->StaCfg.DLSEntry[i].MacAddr[3], pAd->StaCfg.DLSEntry[i].MacAddr[4], pAd->StaCfg.DLSEntry[i].MacAddr[5]));
DBGPRINT(RT_DEBUG_OFF, ("%-8d\n", pAd->StaCfg.DLSEntry[i].TimeOut));
DBGPRINT(RT_DEBUG_OFF, ("\n"));
DBGPRINT(RT_DEBUG_OFF, ("\n%-19s%-4s%-4s%-4s%-4s%-7s%-7s%-7s","MAC", "AID", "BSS", "PSM", "WMM", "RSSI0", "RSSI1", "RSSI2"));
#ifdef DOT11_N_SUPPORT
DBGPRINT(RT_DEBUG_OFF, ("%-8s%-10s%-6s%-6s%-6s%-6s", "MIMOPS", "PhMd", "BW", "MCS", "SGI", "STBC"));
#endif // DOT11_N_SUPPORT //
DBGPRINT(RT_DEBUG_OFF, ("\n%02X:%02X:%02X:%02X:%02X:%02X ",
pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]));
DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->Aid));
DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->apidx));
DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->PsMode));
DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)));
DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi0));
DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi1));
DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi2));
#ifdef DOT11_N_SUPPORT
DBGPRINT(RT_DEBUG_OFF, ("%-8d", (int)pEntry->MmpsMode));
DBGPRINT(RT_DEBUG_OFF, ("%-10s", GetPhyMode(pEntry->HTPhyMode.field.MODE)));
DBGPRINT(RT_DEBUG_OFF, ("%-6s", GetBW(pEntry->HTPhyMode.field.BW)));
DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.MCS));
DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.ShortGI));
DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.STBC));
#endif // DOT11_N_SUPPORT //
DBGPRINT(RT_DEBUG_OFF, ("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount,
(pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0));
DBGPRINT(RT_DEBUG_OFF, ("\n"));
}
}
return TRUE;
}
INT Set_DlsAddEntry_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
UCHAR mac[MAC_ADDR_LEN];
USHORT Timeout;
PSTRING token;
STRING sepValue[] = ":", DASH = '-';
INT i;
RT_802_11_DLS Dls;
if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and timeout value in decimal format.
return FALSE;
token = strchr(arg, DASH);
if ((token != NULL) && (strlen(token)>1))
{
Timeout = (USHORT) simple_strtol((token+1), 0, 10);
*token = '\0';
for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
{
if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
return FALSE;
AtoH(token, (&mac[i]), 1);
}
if(i != 6)
return FALSE;
DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%d", mac[0], mac[1],
mac[2], mac[3], mac[4], mac[5], (int)Timeout));
NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
Dls.TimeOut = Timeout;
COPY_MAC_ADDR(Dls.MacAddr, mac);
Dls.Valid = 1;
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
RT_OID_802_11_SET_DLS_PARAM,
sizeof(RT_802_11_DLS),
&Dls);
return TRUE;
}
return FALSE;
}
INT Set_DlsTearDownEntry_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
UCHAR macAddr[MAC_ADDR_LEN];
PSTRING value;
INT i;
RT_802_11_DLS Dls;
if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17
return FALSE;
for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":"))
{
if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
return FALSE; //Invalid
AtoH(value, &macAddr[i++], 2);
}
DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x", macAddr[0], macAddr[1],
macAddr[2], macAddr[3], macAddr[4], macAddr[5]));
NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
COPY_MAC_ADDR(Dls.MacAddr, macAddr);
Dls.Valid = 0;
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
RT_OID_802_11_SET_DLS_PARAM,
sizeof(RT_802_11_DLS),
&Dls);
return TRUE;
}