f4b44e763d
Fix staging/rt28x0 printk format warnings: linux-next-20090209/drivers/staging/rt2860/common/spectrum.c:1599: warning: format '%d' expects type 'int', but argument 3 has type 'long unsigned int' linux-next-20090209/drivers/staging/rt2860/rt_linux.c:857: warning: format '%d' expects type 'int', but argument 3 has type 'long unsigned int' linux-next-20090209/drivers/staging/rt2870/common/spectrum.c:1598: warning: format '%d' expects type 'int', but argument 3 has type 'long unsigned int' linux-next-20090209/drivers/staging/rt2870/rt_linux.c:898: warning: format '%d' expects type 'int', but argument 3 has type 'long unsigned int' Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
1878 lines
46 KiB
C
1878 lines
46 KiB
C
/*
|
|
*************************************************************************
|
|
* 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:
|
|
action.c
|
|
|
|
Abstract:
|
|
Handle association related requests either from WSTA or from local MLME
|
|
|
|
Revision History:
|
|
Who When What
|
|
--------- ---------- ----------------------------------------------
|
|
Fonchi Wu 2008 created for 802.11h
|
|
*/
|
|
|
|
#include "../rt_config.h"
|
|
#include "action.h"
|
|
|
|
VOID MeasureReqTabInit(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
|
|
|
|
pAd->CommonCfg.pMeasureReqTab = kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC);
|
|
if (pAd->CommonCfg.pMeasureReqTab)
|
|
NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, sizeof(MEASURE_REQ_TAB));
|
|
else
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __func__));
|
|
|
|
return;
|
|
}
|
|
|
|
VOID MeasureReqTabExit(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
NdisFreeSpinLock(pAd->CommonCfg.MeasureReqTabLock);
|
|
|
|
if (pAd->CommonCfg.pMeasureReqTab)
|
|
kfree(pAd->CommonCfg.pMeasureReqTab);
|
|
pAd->CommonCfg.pMeasureReqTab = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
static PMEASURE_REQ_ENTRY MeasureReqLookUp(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UINT8 DialogToken)
|
|
{
|
|
UINT HashIdx;
|
|
PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
|
|
PMEASURE_REQ_ENTRY pEntry = NULL;
|
|
PMEASURE_REQ_ENTRY pPrevEntry = NULL;
|
|
|
|
if (pTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
|
|
return NULL;
|
|
}
|
|
|
|
RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
|
|
|
|
HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
|
|
pEntry = pTab->Hash[HashIdx];
|
|
|
|
while (pEntry)
|
|
{
|
|
if (pEntry->DialogToken == DialogToken)
|
|
break;
|
|
else
|
|
{
|
|
pPrevEntry = pEntry;
|
|
pEntry = pEntry->pNext;
|
|
}
|
|
}
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
static PMEASURE_REQ_ENTRY MeasureReqInsert(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UINT8 DialogToken)
|
|
{
|
|
INT i;
|
|
ULONG HashIdx;
|
|
PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
|
|
PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry;
|
|
ULONG Now;
|
|
|
|
if(pTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
|
|
return NULL;
|
|
}
|
|
|
|
pEntry = MeasureReqLookUp(pAd, DialogToken);
|
|
if (pEntry == NULL)
|
|
{
|
|
RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
|
|
for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++)
|
|
{
|
|
NdisGetSystemUpTime(&Now);
|
|
pEntry = &pTab->Content[i];
|
|
|
|
if ((pEntry->Valid == TRUE)
|
|
&& RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT)))
|
|
{
|
|
PMEASURE_REQ_ENTRY pPrevEntry = NULL;
|
|
ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
|
|
PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
|
|
|
|
// update Hash list
|
|
do
|
|
{
|
|
if (pProbeEntry == pEntry)
|
|
{
|
|
if (pPrevEntry == NULL)
|
|
{
|
|
pTab->Hash[HashIdx] = pEntry->pNext;
|
|
}
|
|
else
|
|
{
|
|
pPrevEntry->pNext = pEntry->pNext;
|
|
}
|
|
break;
|
|
}
|
|
|
|
pPrevEntry = pProbeEntry;
|
|
pProbeEntry = pProbeEntry->pNext;
|
|
} while (pProbeEntry);
|
|
|
|
NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
|
|
pTab->Size--;
|
|
|
|
break;
|
|
}
|
|
|
|
if (pEntry->Valid == FALSE)
|
|
break;
|
|
}
|
|
|
|
if (i < MAX_MEASURE_REQ_TAB_SIZE)
|
|
{
|
|
NdisGetSystemUpTime(&Now);
|
|
pEntry->lastTime = Now;
|
|
pEntry->Valid = TRUE;
|
|
pEntry->DialogToken = DialogToken;
|
|
pTab->Size++;
|
|
}
|
|
else
|
|
{
|
|
pEntry = NULL;
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __func__));
|
|
}
|
|
|
|
// add this Neighbor entry into HASH table
|
|
if (pEntry)
|
|
{
|
|
HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
|
|
if (pTab->Hash[HashIdx] == NULL)
|
|
{
|
|
pTab->Hash[HashIdx] = pEntry;
|
|
}
|
|
else
|
|
{
|
|
pCurrEntry = pTab->Hash[HashIdx];
|
|
while (pCurrEntry->pNext != NULL)
|
|
pCurrEntry = pCurrEntry->pNext;
|
|
pCurrEntry->pNext = pEntry;
|
|
}
|
|
}
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
|
|
}
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
static VOID MeasureReqDelete(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UINT8 DialogToken)
|
|
{
|
|
PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
|
|
PMEASURE_REQ_ENTRY pEntry = NULL;
|
|
|
|
if(pTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
|
|
return;
|
|
}
|
|
|
|
// if empty, return
|
|
if (pTab->Size == 0)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
|
|
return;
|
|
}
|
|
|
|
pEntry = MeasureReqLookUp(pAd, DialogToken);
|
|
if (pEntry != NULL)
|
|
{
|
|
PMEASURE_REQ_ENTRY pPrevEntry = NULL;
|
|
ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
|
|
PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
|
|
|
|
RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
|
|
// update Hash list
|
|
do
|
|
{
|
|
if (pProbeEntry == pEntry)
|
|
{
|
|
if (pPrevEntry == NULL)
|
|
{
|
|
pTab->Hash[HashIdx] = pEntry->pNext;
|
|
}
|
|
else
|
|
{
|
|
pPrevEntry->pNext = pEntry->pNext;
|
|
}
|
|
break;
|
|
}
|
|
|
|
pPrevEntry = pProbeEntry;
|
|
pProbeEntry = pProbeEntry->pNext;
|
|
} while (pProbeEntry);
|
|
|
|
NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
|
|
pTab->Size--;
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID TpcReqTabInit(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
|
|
|
|
pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC);
|
|
if (pAd->CommonCfg.pTpcReqTab)
|
|
NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB));
|
|
else
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __func__));
|
|
|
|
return;
|
|
}
|
|
|
|
VOID TpcReqTabExit(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
NdisFreeSpinLock(pAd->CommonCfg.TpcReqTabLock);
|
|
|
|
if (pAd->CommonCfg.pTpcReqTab)
|
|
kfree(pAd->CommonCfg.pTpcReqTab);
|
|
pAd->CommonCfg.pTpcReqTab = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
static PTPC_REQ_ENTRY TpcReqLookUp(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UINT8 DialogToken)
|
|
{
|
|
UINT HashIdx;
|
|
PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
|
|
PTPC_REQ_ENTRY pEntry = NULL;
|
|
PTPC_REQ_ENTRY pPrevEntry = NULL;
|
|
|
|
if (pTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
|
|
return NULL;
|
|
}
|
|
|
|
RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
|
|
|
|
HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
|
|
pEntry = pTab->Hash[HashIdx];
|
|
|
|
while (pEntry)
|
|
{
|
|
if (pEntry->DialogToken == DialogToken)
|
|
break;
|
|
else
|
|
{
|
|
pPrevEntry = pEntry;
|
|
pEntry = pEntry->pNext;
|
|
}
|
|
}
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
|
|
static PTPC_REQ_ENTRY TpcReqInsert(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UINT8 DialogToken)
|
|
{
|
|
INT i;
|
|
ULONG HashIdx;
|
|
PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
|
|
PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry;
|
|
ULONG Now;
|
|
|
|
if(pTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
|
|
return NULL;
|
|
}
|
|
|
|
pEntry = TpcReqLookUp(pAd, DialogToken);
|
|
if (pEntry == NULL)
|
|
{
|
|
RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
|
|
for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++)
|
|
{
|
|
NdisGetSystemUpTime(&Now);
|
|
pEntry = &pTab->Content[i];
|
|
|
|
if ((pEntry->Valid == TRUE)
|
|
&& RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT)))
|
|
{
|
|
PTPC_REQ_ENTRY pPrevEntry = NULL;
|
|
ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
|
|
PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
|
|
|
|
// update Hash list
|
|
do
|
|
{
|
|
if (pProbeEntry == pEntry)
|
|
{
|
|
if (pPrevEntry == NULL)
|
|
{
|
|
pTab->Hash[HashIdx] = pEntry->pNext;
|
|
}
|
|
else
|
|
{
|
|
pPrevEntry->pNext = pEntry->pNext;
|
|
}
|
|
break;
|
|
}
|
|
|
|
pPrevEntry = pProbeEntry;
|
|
pProbeEntry = pProbeEntry->pNext;
|
|
} while (pProbeEntry);
|
|
|
|
NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
|
|
pTab->Size--;
|
|
|
|
break;
|
|
}
|
|
|
|
if (pEntry->Valid == FALSE)
|
|
break;
|
|
}
|
|
|
|
if (i < MAX_TPC_REQ_TAB_SIZE)
|
|
{
|
|
NdisGetSystemUpTime(&Now);
|
|
pEntry->lastTime = Now;
|
|
pEntry->Valid = TRUE;
|
|
pEntry->DialogToken = DialogToken;
|
|
pTab->Size++;
|
|
}
|
|
else
|
|
{
|
|
pEntry = NULL;
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __func__));
|
|
}
|
|
|
|
// add this Neighbor entry into HASH table
|
|
if (pEntry)
|
|
{
|
|
HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
|
|
if (pTab->Hash[HashIdx] == NULL)
|
|
{
|
|
pTab->Hash[HashIdx] = pEntry;
|
|
}
|
|
else
|
|
{
|
|
pCurrEntry = pTab->Hash[HashIdx];
|
|
while (pCurrEntry->pNext != NULL)
|
|
pCurrEntry = pCurrEntry->pNext;
|
|
pCurrEntry->pNext = pEntry;
|
|
}
|
|
}
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
|
|
}
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
static VOID TpcReqDelete(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UINT8 DialogToken)
|
|
{
|
|
PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
|
|
PTPC_REQ_ENTRY pEntry = NULL;
|
|
|
|
if(pTab == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
|
|
return;
|
|
}
|
|
|
|
// if empty, return
|
|
if (pTab->Size == 0)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
|
|
return;
|
|
}
|
|
|
|
pEntry = TpcReqLookUp(pAd, DialogToken);
|
|
if (pEntry != NULL)
|
|
{
|
|
PTPC_REQ_ENTRY pPrevEntry = NULL;
|
|
ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
|
|
PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
|
|
|
|
RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
|
|
// update Hash list
|
|
do
|
|
{
|
|
if (pProbeEntry == pEntry)
|
|
{
|
|
if (pPrevEntry == NULL)
|
|
{
|
|
pTab->Hash[HashIdx] = pEntry->pNext;
|
|
}
|
|
else
|
|
{
|
|
pPrevEntry->pNext = pEntry->pNext;
|
|
}
|
|
break;
|
|
}
|
|
|
|
pPrevEntry = pProbeEntry;
|
|
pProbeEntry = pProbeEntry->pNext;
|
|
} while (pProbeEntry);
|
|
|
|
NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
|
|
pTab->Size--;
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Get Current TimeS tamp.
|
|
|
|
Parametrs:
|
|
|
|
Return : Current Time Stamp.
|
|
==========================================================================
|
|
*/
|
|
static UINT64 GetCurrentTimeStamp(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
// get current time stamp.
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Get Current Transmit Power.
|
|
|
|
Parametrs:
|
|
|
|
Return : Current Time Stamp.
|
|
==========================================================================
|
|
*/
|
|
static UINT8 GetCurTxPwr(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UINT8 Wcid)
|
|
{
|
|
return 16; /* 16 dBm */
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Insert Dialog Token into frame.
|
|
|
|
Parametrs:
|
|
1. frame buffer pointer.
|
|
2. frame length.
|
|
3. Dialog token.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static VOID InsertDialogToken(
|
|
IN PRTMP_ADAPTER pAd,
|
|
OUT PUCHAR pFrameBuf,
|
|
OUT PULONG pFrameLen,
|
|
IN UINT8 DialogToken)
|
|
{
|
|
ULONG TempLen;
|
|
MakeOutgoingFrame(pFrameBuf, &TempLen,
|
|
1, &DialogToken,
|
|
END_OF_ARGS);
|
|
|
|
*pFrameLen = *pFrameLen + TempLen;
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Insert TPC Request IE into frame.
|
|
|
|
Parametrs:
|
|
1. frame buffer pointer.
|
|
2. frame length.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static VOID InsertTpcReqIE(
|
|
IN PRTMP_ADAPTER pAd,
|
|
OUT PUCHAR pFrameBuf,
|
|
OUT PULONG pFrameLen)
|
|
{
|
|
ULONG TempLen;
|
|
ULONG Len = 0;
|
|
UINT8 ElementID = IE_TPC_REQUEST;
|
|
|
|
MakeOutgoingFrame(pFrameBuf, &TempLen,
|
|
1, &ElementID,
|
|
1, &Len,
|
|
END_OF_ARGS);
|
|
|
|
*pFrameLen = *pFrameLen + TempLen;
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Insert TPC Report IE into frame.
|
|
|
|
Parametrs:
|
|
1. frame buffer pointer.
|
|
2. frame length.
|
|
3. Transmit Power.
|
|
4. Link Margin.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static VOID InsertTpcReportIE(
|
|
IN PRTMP_ADAPTER pAd,
|
|
OUT PUCHAR pFrameBuf,
|
|
OUT PULONG pFrameLen,
|
|
IN UINT8 TxPwr,
|
|
IN UINT8 LinkMargin)
|
|
{
|
|
ULONG TempLen;
|
|
ULONG Len = sizeof(TPC_REPORT_INFO);
|
|
UINT8 ElementID = IE_TPC_REPORT;
|
|
TPC_REPORT_INFO TpcReportIE;
|
|
|
|
TpcReportIE.TxPwr = TxPwr;
|
|
TpcReportIE.LinkMargin = LinkMargin;
|
|
|
|
MakeOutgoingFrame(pFrameBuf, &TempLen,
|
|
1, &ElementID,
|
|
1, &Len,
|
|
Len, &TpcReportIE,
|
|
END_OF_ARGS);
|
|
|
|
*pFrameLen = *pFrameLen + TempLen;
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Insert Channel Switch Announcement IE into frame.
|
|
|
|
Parametrs:
|
|
1. frame buffer pointer.
|
|
2. frame length.
|
|
3. channel switch announcement mode.
|
|
4. new selected channel.
|
|
5. channel switch announcement count.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static VOID InsertChSwAnnIE(
|
|
IN PRTMP_ADAPTER pAd,
|
|
OUT PUCHAR pFrameBuf,
|
|
OUT PULONG pFrameLen,
|
|
IN UINT8 ChSwMode,
|
|
IN UINT8 NewChannel,
|
|
IN UINT8 ChSwCnt)
|
|
{
|
|
ULONG TempLen;
|
|
ULONG Len = sizeof(CH_SW_ANN_INFO);
|
|
UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
|
|
CH_SW_ANN_INFO ChSwAnnIE;
|
|
|
|
ChSwAnnIE.ChSwMode = ChSwMode;
|
|
ChSwAnnIE.Channel = NewChannel;
|
|
ChSwAnnIE.ChSwCnt = ChSwCnt;
|
|
|
|
MakeOutgoingFrame(pFrameBuf, &TempLen,
|
|
1, &ElementID,
|
|
1, &Len,
|
|
Len, &ChSwAnnIE,
|
|
END_OF_ARGS);
|
|
|
|
*pFrameLen = *pFrameLen + TempLen;
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Insert Measure Request IE into frame.
|
|
|
|
Parametrs:
|
|
1. frame buffer pointer.
|
|
2. frame length.
|
|
3. Measure Token.
|
|
4. Measure Request Mode.
|
|
5. Measure Request Type.
|
|
6. Measure Channel.
|
|
7. Measure Start time.
|
|
8. Measure Duration.
|
|
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static VOID InsertMeasureReqIE(
|
|
IN PRTMP_ADAPTER pAd,
|
|
OUT PUCHAR pFrameBuf,
|
|
OUT PULONG pFrameLen,
|
|
IN PMEASURE_REQ_INFO pMeasureReqIE)
|
|
{
|
|
ULONG TempLen;
|
|
UINT8 Len = sizeof(MEASURE_REQ_INFO);
|
|
UINT8 ElementID = IE_MEASUREMENT_REQUEST;
|
|
|
|
MakeOutgoingFrame(pFrameBuf, &TempLen,
|
|
1, &ElementID,
|
|
1, &Len,
|
|
Len, pMeasureReqIE,
|
|
END_OF_ARGS);
|
|
|
|
*pFrameLen = *pFrameLen + TempLen;
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Insert Measure Report IE into frame.
|
|
|
|
Parametrs:
|
|
1. frame buffer pointer.
|
|
2. frame length.
|
|
3. Measure Token.
|
|
4. Measure Request Mode.
|
|
5. Measure Request Type.
|
|
6. Length of Report Infomation
|
|
7. Pointer of Report Infomation Buffer.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static VOID InsertMeasureReportIE(
|
|
IN PRTMP_ADAPTER pAd,
|
|
OUT PUCHAR pFrameBuf,
|
|
OUT PULONG pFrameLen,
|
|
IN PMEASURE_REPORT_INFO pMeasureReportIE,
|
|
IN UINT8 ReportLnfoLen,
|
|
IN PUINT8 pReportInfo)
|
|
{
|
|
ULONG TempLen;
|
|
ULONG Len;
|
|
UINT8 ElementID = IE_MEASUREMENT_REPORT;
|
|
|
|
Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen;
|
|
|
|
MakeOutgoingFrame(pFrameBuf, &TempLen,
|
|
1, &ElementID,
|
|
1, &Len,
|
|
Len, pMeasureReportIE,
|
|
END_OF_ARGS);
|
|
|
|
*pFrameLen = *pFrameLen + TempLen;
|
|
|
|
if ((ReportLnfoLen > 0) && (pReportInfo != NULL))
|
|
{
|
|
MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen,
|
|
ReportLnfoLen, pReportInfo,
|
|
END_OF_ARGS);
|
|
|
|
*pFrameLen = *pFrameLen + TempLen;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Prepare Measurement request action frame and enqueue it into
|
|
management queue waiting for transmition.
|
|
|
|
Parametrs:
|
|
1. the destination mac address of the frame.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
VOID EnqueueMeasurementReq(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pDA,
|
|
IN UINT8 MeasureToken,
|
|
IN UINT8 MeasureReqMode,
|
|
IN UINT8 MeasureReqType,
|
|
IN UINT8 MeasureCh,
|
|
IN UINT16 MeasureDuration)
|
|
{
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
ULONG FrameLen;
|
|
HEADER_802_11 ActHdr;
|
|
MEASURE_REQ_INFO MeasureReqIE;
|
|
UINT8 RmReqDailogToken = RandomByte(pAd);
|
|
UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd);
|
|
|
|
// build action frame header.
|
|
MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
|
|
pAd->CurrentAddress);
|
|
|
|
NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
|
|
if(NStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
|
|
return;
|
|
}
|
|
NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
|
|
FrameLen = sizeof(HEADER_802_11);
|
|
|
|
InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRQ);
|
|
|
|
// fill Dialog Token
|
|
InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, MeasureToken);
|
|
|
|
// prepare Measurement IE.
|
|
NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO));
|
|
MeasureReqIE.Token = RmReqDailogToken;
|
|
MeasureReqIE.ReqMode.word = MeasureReqMode;
|
|
MeasureReqIE.ReqType = MeasureReqType;
|
|
MeasureReqIE.MeasureReq.ChNum = MeasureCh;
|
|
MeasureReqIE.MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
|
|
MeasureReqIE.MeasureReq.MeasureDuration = cpu2le16(MeasureDuration);
|
|
InsertMeasureReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureReqIE);
|
|
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Prepare Measurement report action frame and enqueue it into
|
|
management queue waiting for transmition.
|
|
|
|
Parametrs:
|
|
1. the destination mac address of the frame.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
VOID EnqueueMeasurementRep(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pDA,
|
|
IN UINT8 DialogToken,
|
|
IN UINT8 MeasureToken,
|
|
IN UINT8 MeasureReqMode,
|
|
IN UINT8 MeasureReqType,
|
|
IN UINT8 ReportInfoLen,
|
|
IN PUINT8 pReportInfo)
|
|
{
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
ULONG FrameLen;
|
|
HEADER_802_11 ActHdr;
|
|
MEASURE_REPORT_INFO MeasureRepIE;
|
|
|
|
// build action frame header.
|
|
MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
|
|
pAd->CurrentAddress);
|
|
|
|
NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
|
|
if(NStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
|
|
return;
|
|
}
|
|
NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
|
|
FrameLen = sizeof(HEADER_802_11);
|
|
|
|
InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP);
|
|
|
|
// fill Dialog Token
|
|
InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
|
|
|
|
// prepare Measurement IE.
|
|
NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO));
|
|
MeasureRepIE.Token = MeasureToken;
|
|
MeasureRepIE.ReportMode.word = MeasureReqMode;
|
|
MeasureRepIE.ReportType = MeasureReqType;
|
|
InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo);
|
|
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Prepare TPC Request action frame and enqueue it into
|
|
management queue waiting for transmition.
|
|
|
|
Parametrs:
|
|
1. the destination mac address of the frame.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
VOID EnqueueTPCReq(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pDA,
|
|
IN UCHAR DialogToken)
|
|
{
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
ULONG FrameLen;
|
|
|
|
HEADER_802_11 ActHdr;
|
|
|
|
// build action frame header.
|
|
MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
|
|
pAd->CurrentAddress);
|
|
|
|
NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
|
|
if(NStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
|
|
return;
|
|
}
|
|
NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
|
|
FrameLen = sizeof(HEADER_802_11);
|
|
|
|
InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ);
|
|
|
|
// fill Dialog Token
|
|
InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
|
|
|
|
// Insert TPC Request IE.
|
|
InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
|
|
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Prepare TPC Report action frame and enqueue it into
|
|
management queue waiting for transmition.
|
|
|
|
Parametrs:
|
|
1. the destination mac address of the frame.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
VOID EnqueueTPCRep(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pDA,
|
|
IN UINT8 DialogToken,
|
|
IN UINT8 TxPwr,
|
|
IN UINT8 LinkMargin)
|
|
{
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
ULONG FrameLen;
|
|
|
|
HEADER_802_11 ActHdr;
|
|
|
|
// build action frame header.
|
|
MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
|
|
pAd->CurrentAddress);
|
|
|
|
NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
|
|
if(NStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
|
|
return;
|
|
}
|
|
NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
|
|
FrameLen = sizeof(HEADER_802_11);
|
|
|
|
InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP);
|
|
|
|
// fill Dialog Token
|
|
InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
|
|
|
|
// Insert TPC Request IE.
|
|
InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin);
|
|
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Prepare Channel Switch Announcement action frame and enqueue it into
|
|
management queue waiting for transmition.
|
|
|
|
Parametrs:
|
|
1. the destination mac address of the frame.
|
|
2. Channel switch announcement mode.
|
|
2. a New selected channel.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
VOID EnqueueChSwAnn(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pDA,
|
|
IN UINT8 ChSwMode,
|
|
IN UINT8 NewCh)
|
|
{
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
ULONG FrameLen;
|
|
|
|
HEADER_802_11 ActHdr;
|
|
|
|
// build action frame header.
|
|
MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
|
|
pAd->CurrentAddress);
|
|
|
|
NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
|
|
if(NStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
|
|
return;
|
|
}
|
|
NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
|
|
FrameLen = sizeof(HEADER_802_11);
|
|
|
|
InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
|
|
|
|
InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0);
|
|
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
|
|
return;
|
|
}
|
|
|
|
static BOOLEAN DfsRequirementCheck(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UINT8 Channel)
|
|
{
|
|
BOOLEAN Result = FALSE;
|
|
INT i;
|
|
|
|
do
|
|
{
|
|
// check DFS procedure is running.
|
|
// make sure DFS procedure won't start twice.
|
|
if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
|
|
{
|
|
Result = FALSE;
|
|
break;
|
|
}
|
|
|
|
// check the new channel carried from Channel Switch Announcemnet is valid.
|
|
for (i=0; i<pAd->ChannelListNum; i++)
|
|
{
|
|
if ((Channel == pAd->ChannelList[i].Channel)
|
|
&&(pAd->ChannelList[i].RemainingTimeForUse == 0))
|
|
{
|
|
// found radar signal in the channel. the channel can't use at least for 30 minutes.
|
|
pAd->ChannelList[i].RemainingTimeForUse = 1800;//30 min = 1800 sec
|
|
Result = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
} while(FALSE);
|
|
|
|
return Result;
|
|
}
|
|
|
|
VOID NotifyChSwAnnToPeerAPs(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pRA,
|
|
IN PUCHAR pTA,
|
|
IN UINT8 ChSwMode,
|
|
IN UINT8 Channel)
|
|
{
|
|
#ifdef WDS_SUPPORT
|
|
if (!((pRA[0] & 0xff) == 0xff)) // is pRA a broadcase address.
|
|
{
|
|
INT i;
|
|
// info neighbor APs that Radar signal found throgh WDS link.
|
|
for (i = 0; i < MAX_WDS_ENTRY; i++)
|
|
{
|
|
if (ValidWdsEntry(pAd, i))
|
|
{
|
|
PUCHAR pDA = pAd->WdsTab.WdsEntry[i].PeerWdsAddr;
|
|
|
|
// DA equal to SA. have no necessary orignal AP which found Radar signal.
|
|
if (MAC_ADDR_EQUAL(pTA, pDA))
|
|
continue;
|
|
|
|
// send Channel Switch Action frame to info Neighbro APs.
|
|
EnqueueChSwAnn(pAd, pDA, ChSwMode, Channel);
|
|
}
|
|
}
|
|
}
|
|
#endif // WDS_SUPPORT //
|
|
}
|
|
|
|
static VOID StartDFSProcedure(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR Channel,
|
|
IN UINT8 ChSwMode)
|
|
{
|
|
// start DFS procedure
|
|
pAd->CommonCfg.Channel = Channel;
|
|
#ifdef DOT11_N_SUPPORT
|
|
N_ChannelCheck(pAd);
|
|
#endif // DOT11_N_SUPPORT //
|
|
pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
|
|
pAd->CommonCfg.RadarDetect.CSCount = 0;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Channel Switch Announcement action frame sanity check.
|
|
|
|
Parametrs:
|
|
1. MLME message containing the received frame
|
|
2. message length.
|
|
3. Channel switch announcement infomation buffer.
|
|
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
|
|
/*
|
|
Channel Switch Announcement IE.
|
|
+----+-----+-----------+------------+-----------+
|
|
| ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
|
|
+----+-----+-----------+------------+-----------+
|
|
1 1 1 1 1
|
|
*/
|
|
static BOOLEAN PeerChSwAnnSanity(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN VOID *pMsg,
|
|
IN ULONG MsgLen,
|
|
OUT PCH_SW_ANN_INFO pChSwAnnInfo)
|
|
{
|
|
PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
|
|
PUCHAR pFramePtr = Fr->Octet;
|
|
BOOLEAN result = FALSE;
|
|
PEID_STRUCT eid_ptr;
|
|
|
|
// skip 802.11 header.
|
|
MsgLen -= sizeof(HEADER_802_11);
|
|
|
|
// skip category and action code.
|
|
pFramePtr += 2;
|
|
MsgLen -= 2;
|
|
|
|
if (pChSwAnnInfo == NULL)
|
|
return result;
|
|
|
|
eid_ptr = (PEID_STRUCT)pFramePtr;
|
|
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
|
|
{
|
|
switch(eid_ptr->Eid)
|
|
{
|
|
case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
|
|
NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1);
|
|
NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1);
|
|
NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1);
|
|
|
|
result = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Measurement request action frame sanity check.
|
|
|
|
Parametrs:
|
|
1. MLME message containing the received frame
|
|
2. message length.
|
|
3. Measurement request infomation buffer.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static BOOLEAN PeerMeasureReqSanity(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN VOID *pMsg,
|
|
IN ULONG MsgLen,
|
|
OUT PUINT8 pDialogToken,
|
|
OUT PMEASURE_REQ_INFO pMeasureReqInfo)
|
|
{
|
|
PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
|
|
PUCHAR pFramePtr = Fr->Octet;
|
|
BOOLEAN result = FALSE;
|
|
PEID_STRUCT eid_ptr;
|
|
PUCHAR ptr;
|
|
UINT64 MeasureStartTime;
|
|
UINT16 MeasureDuration;
|
|
|
|
// skip 802.11 header.
|
|
MsgLen -= sizeof(HEADER_802_11);
|
|
|
|
// skip category and action code.
|
|
pFramePtr += 2;
|
|
MsgLen -= 2;
|
|
|
|
if (pMeasureReqInfo == NULL)
|
|
return result;
|
|
|
|
NdisMoveMemory(pDialogToken, pFramePtr, 1);
|
|
pFramePtr += 1;
|
|
MsgLen -= 1;
|
|
|
|
eid_ptr = (PEID_STRUCT)pFramePtr;
|
|
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
|
|
{
|
|
switch(eid_ptr->Eid)
|
|
{
|
|
case IE_MEASUREMENT_REQUEST:
|
|
NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1);
|
|
NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1);
|
|
NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1);
|
|
ptr = eid_ptr->Octet + 3;
|
|
NdisMoveMemory(&pMeasureReqInfo->MeasureReq.ChNum, ptr, 1);
|
|
NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
|
|
pMeasureReqInfo->MeasureReq.MeasureStartTime = SWAP64(MeasureStartTime);
|
|
NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
|
|
pMeasureReqInfo->MeasureReq.MeasureDuration = SWAP16(MeasureDuration);
|
|
|
|
result = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Measurement report action frame sanity check.
|
|
|
|
Parametrs:
|
|
1. MLME message containing the received frame
|
|
2. message length.
|
|
3. Measurement report infomation buffer.
|
|
4. basic report infomation buffer.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
|
|
/*
|
|
Measurement Report IE.
|
|
+----+-----+-------+-------------+--------------+----------------+
|
|
| ID | Len | Token | Report Mode | Measure Type | Measure Report |
|
|
+----+-----+-------+-------------+--------------+----------------+
|
|
1 1 1 1 1 variable
|
|
|
|
Basic Report.
|
|
+--------+------------+----------+-----+
|
|
| Ch Num | Start Time | Duration | Map |
|
|
+--------+------------+----------+-----+
|
|
1 8 2 1
|
|
|
|
Map Field Bit Format.
|
|
+-----+---------------+---------------------+-------+------------+----------+
|
|
| Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
|
|
+-----+---------------+---------------------+-------+------------+----------+
|
|
0 1 2 3 4 5-7
|
|
*/
|
|
static BOOLEAN PeerMeasureReportSanity(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN VOID *pMsg,
|
|
IN ULONG MsgLen,
|
|
OUT PUINT8 pDialogToken,
|
|
OUT PMEASURE_REPORT_INFO pMeasureReportInfo,
|
|
OUT PUINT8 pReportBuf)
|
|
{
|
|
PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
|
|
PUCHAR pFramePtr = Fr->Octet;
|
|
BOOLEAN result = FALSE;
|
|
PEID_STRUCT eid_ptr;
|
|
PUCHAR ptr;
|
|
|
|
// skip 802.11 header.
|
|
MsgLen -= sizeof(HEADER_802_11);
|
|
|
|
// skip category and action code.
|
|
pFramePtr += 2;
|
|
MsgLen -= 2;
|
|
|
|
if (pMeasureReportInfo == NULL)
|
|
return result;
|
|
|
|
NdisMoveMemory(pDialogToken, pFramePtr, 1);
|
|
pFramePtr += 1;
|
|
MsgLen -= 1;
|
|
|
|
eid_ptr = (PEID_STRUCT)pFramePtr;
|
|
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
|
|
{
|
|
switch(eid_ptr->Eid)
|
|
{
|
|
case IE_MEASUREMENT_REPORT:
|
|
NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1);
|
|
NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1);
|
|
NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1);
|
|
if (pMeasureReportInfo->ReportType == RM_BASIC)
|
|
{
|
|
PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf;
|
|
ptr = eid_ptr->Octet + 3;
|
|
NdisMoveMemory(&pReport->ChNum, ptr, 1);
|
|
NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
|
|
NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
|
|
NdisMoveMemory(&pReport->Map, ptr + 11, 1);
|
|
|
|
}
|
|
else if (pMeasureReportInfo->ReportType == RM_CCA)
|
|
{
|
|
PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf;
|
|
ptr = eid_ptr->Octet + 3;
|
|
NdisMoveMemory(&pReport->ChNum, ptr, 1);
|
|
NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
|
|
NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
|
|
NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1);
|
|
|
|
}
|
|
else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM)
|
|
{
|
|
PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf;
|
|
ptr = eid_ptr->Octet + 3;
|
|
NdisMoveMemory(&pReport->ChNum, ptr, 1);
|
|
NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
|
|
NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
|
|
NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8);
|
|
}
|
|
result = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
TPC Request action frame sanity check.
|
|
|
|
Parametrs:
|
|
1. MLME message containing the received frame
|
|
2. message length.
|
|
3. Dialog Token.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static BOOLEAN PeerTpcReqSanity(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN VOID *pMsg,
|
|
IN ULONG MsgLen,
|
|
OUT PUINT8 pDialogToken)
|
|
{
|
|
PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
|
|
PUCHAR pFramePtr = Fr->Octet;
|
|
BOOLEAN result = FALSE;
|
|
PEID_STRUCT eid_ptr;
|
|
|
|
MsgLen -= sizeof(HEADER_802_11);
|
|
|
|
// skip category and action code.
|
|
pFramePtr += 2;
|
|
MsgLen -= 2;
|
|
|
|
if (pDialogToken == NULL)
|
|
return result;
|
|
|
|
NdisMoveMemory(pDialogToken, pFramePtr, 1);
|
|
pFramePtr += 1;
|
|
MsgLen -= 1;
|
|
|
|
eid_ptr = (PEID_STRUCT)pFramePtr;
|
|
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
|
|
{
|
|
switch(eid_ptr->Eid)
|
|
{
|
|
case IE_TPC_REQUEST:
|
|
result = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
TPC Report action frame sanity check.
|
|
|
|
Parametrs:
|
|
1. MLME message containing the received frame
|
|
2. message length.
|
|
3. Dialog Token.
|
|
4. TPC Report IE.
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static BOOLEAN PeerTpcRepSanity(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN VOID *pMsg,
|
|
IN ULONG MsgLen,
|
|
OUT PUINT8 pDialogToken,
|
|
OUT PTPC_REPORT_INFO pTpcRepInfo)
|
|
{
|
|
PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
|
|
PUCHAR pFramePtr = Fr->Octet;
|
|
BOOLEAN result = FALSE;
|
|
PEID_STRUCT eid_ptr;
|
|
|
|
MsgLen -= sizeof(HEADER_802_11);
|
|
|
|
// skip category and action code.
|
|
pFramePtr += 2;
|
|
MsgLen -= 2;
|
|
|
|
if (pDialogToken == NULL)
|
|
return result;
|
|
|
|
NdisMoveMemory(pDialogToken, pFramePtr, 1);
|
|
pFramePtr += 1;
|
|
MsgLen -= 1;
|
|
|
|
eid_ptr = (PEID_STRUCT)pFramePtr;
|
|
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
|
|
{
|
|
switch(eid_ptr->Eid)
|
|
{
|
|
case IE_TPC_REPORT:
|
|
NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
|
|
NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1);
|
|
result = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Channel Switch Announcement action frame handler.
|
|
|
|
Parametrs:
|
|
Elme - MLME message containing the received frame
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static VOID PeerChSwAnnAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
CH_SW_ANN_INFO ChSwAnnInfo;
|
|
PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
UCHAR index = 0, Channel = 0, NewChannel = 0;
|
|
ULONG Bssidx = 0;
|
|
#endif // CONFIG_STA_SUPPORT //
|
|
|
|
NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO));
|
|
if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo))
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n"));
|
|
return;
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
if (pAd->OpMode == OPMODE_STA)
|
|
{
|
|
Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel);
|
|
if (Bssidx == BSS_NOT_FOUND)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n"));
|
|
return;
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel));
|
|
hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6);
|
|
|
|
Channel = pAd->CommonCfg.Channel;
|
|
NewChannel = ChSwAnnInfo.Channel;
|
|
|
|
if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
|
|
{
|
|
// Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
|
|
// In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
|
|
AsicSwitchChannel(pAd, 1, FALSE);
|
|
AsicLockChannel(pAd, 1);
|
|
LinkDown(pAd, FALSE);
|
|
MlmeQueueInit(&pAd->Mlme.Queue);
|
|
BssTableInit(&pAd->ScanTab);
|
|
RTMPusecDelay(1000000); // use delay to prevent STA do reassoc
|
|
|
|
// channel sanity check
|
|
for (index = 0 ; index < pAd->ChannelListNum; index++)
|
|
{
|
|
if (pAd->ChannelList[index].Channel == NewChannel)
|
|
{
|
|
pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
|
|
pAd->CommonCfg.Channel = NewChannel;
|
|
AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
|
|
AsicLockChannel(pAd, pAd->CommonCfg.Channel);
|
|
DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (index >= pAd->ChannelListNum)
|
|
{
|
|
DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
|
|
}
|
|
}
|
|
}
|
|
#endif // CONFIG_STA_SUPPORT //
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Measurement Request action frame handler.
|
|
|
|
Parametrs:
|
|
Elme - MLME message containing the received frame
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static VOID PeerMeasureReqAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
|
|
UINT8 DialogToken;
|
|
MEASURE_REQ_INFO MeasureReqInfo;
|
|
MEASURE_REPORT_MODE ReportMode;
|
|
|
|
if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo))
|
|
{
|
|
ReportMode.word = 0;
|
|
ReportMode.field.Incapable = 1;
|
|
EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Measurement Report action frame handler.
|
|
|
|
Parametrs:
|
|
Elme - MLME message containing the received frame
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static VOID PeerMeasureReportAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
MEASURE_REPORT_INFO MeasureReportInfo;
|
|
PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
|
|
UINT8 DialogToken;
|
|
PUINT8 pMeasureReportInfo;
|
|
|
|
// if (pAd->CommonCfg.bIEEE80211H != TRUE)
|
|
// return;
|
|
|
|
if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%zu).\n", __func__, sizeof(MEASURE_RPI_REPORT)));
|
|
return;
|
|
}
|
|
|
|
NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO));
|
|
NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT));
|
|
if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo))
|
|
{
|
|
do {
|
|
PMEASURE_REQ_ENTRY pEntry = NULL;
|
|
|
|
// Not a autonomous measure report.
|
|
// check the dialog token field. drop it if the dialog token doesn't match.
|
|
if ((DialogToken != 0)
|
|
&& ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL))
|
|
break;
|
|
|
|
if (pEntry != NULL)
|
|
MeasureReqDelete(pAd, pEntry->DialogToken);
|
|
|
|
if (MeasureReportInfo.ReportType == RM_BASIC)
|
|
{
|
|
PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo;
|
|
if ((pBasicReport->Map.field.Radar)
|
|
&& (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE))
|
|
{
|
|
NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum);
|
|
StartDFSProcedure(pAd, pBasicReport->ChNum, 1);
|
|
}
|
|
}
|
|
} while (FALSE);
|
|
}
|
|
else
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n"));
|
|
|
|
kfree(pMeasureReportInfo);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
TPC Request action frame handler.
|
|
|
|
Parametrs:
|
|
Elme - MLME message containing the received frame
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static VOID PeerTpcReqAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
|
|
PUCHAR pFramePtr = pFr->Octet;
|
|
UINT8 DialogToken;
|
|
UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
|
|
UINT8 LinkMargin = 0;
|
|
CHAR RealRssi;
|
|
|
|
// link margin: Ratio of the received signal power to the minimum desired by the station (STA). The
|
|
// STA may incorporate rate information and channel conditions, including interference, into its computation
|
|
// of link margin.
|
|
|
|
RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
|
|
ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
|
|
ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
|
|
|
|
// skip Category and action code.
|
|
pFramePtr += 2;
|
|
|
|
// Dialog token.
|
|
NdisMoveMemory(&DialogToken, pFramePtr, 1);
|
|
|
|
LinkMargin = (RealRssi / MIN_RCV_PWR);
|
|
if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
|
|
EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
TPC Report action frame handler.
|
|
|
|
Parametrs:
|
|
Elme - MLME message containing the received frame
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
static VOID PeerTpcRepAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
UINT8 DialogToken;
|
|
TPC_REPORT_INFO TpcRepInfo;
|
|
PTPC_REQ_ENTRY pEntry = NULL;
|
|
|
|
NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO));
|
|
if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo))
|
|
{
|
|
if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL)
|
|
{
|
|
TpcReqDelete(pAd, pEntry->DialogToken);
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
|
|
__func__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin));
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Spectrun action frames Handler such as channel switch annoucement,
|
|
measurement report, measurement request actions frames.
|
|
|
|
Parametrs:
|
|
Elme - MLME message containing the received frame
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
VOID PeerSpectrumAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
|
|
UCHAR Action = Elem->Msg[LENGTH_802_11+1];
|
|
|
|
if (pAd->CommonCfg.bIEEE80211H != TRUE)
|
|
return;
|
|
|
|
switch(Action)
|
|
{
|
|
case SPEC_MRQ:
|
|
// current rt2860 unable do such measure specified in Measurement Request.
|
|
// reject all measurement request.
|
|
PeerMeasureReqAction(pAd, Elem);
|
|
break;
|
|
|
|
case SPEC_MRP:
|
|
PeerMeasureReportAction(pAd, Elem);
|
|
break;
|
|
|
|
case SPEC_TPCRQ:
|
|
PeerTpcReqAction(pAd, Elem);
|
|
break;
|
|
|
|
case SPEC_TPCRP:
|
|
PeerTpcRepAction(pAd, Elem);
|
|
break;
|
|
|
|
case SPEC_CHANNEL_SWITCH:
|
|
{
|
|
#ifdef DOT11N_DRAFT3
|
|
SEC_CHA_OFFSET_IE Secondary;
|
|
CHA_SWITCH_ANNOUNCE_IE ChannelSwitch;
|
|
|
|
// 802.11h only has Channel Switch Announcement IE.
|
|
RTMPMoveMemory(&ChannelSwitch, &Elem->Msg[LENGTH_802_11+4], sizeof (CHA_SWITCH_ANNOUNCE_IE));
|
|
|
|
// 802.11n D3.03 adds secondary channel offset element in the end.
|
|
if (Elem->MsgLen == (LENGTH_802_11 + 2 + sizeof (CHA_SWITCH_ANNOUNCE_IE) + sizeof (SEC_CHA_OFFSET_IE)))
|
|
{
|
|
RTMPMoveMemory(&Secondary, &Elem->Msg[LENGTH_802_11+9], sizeof (SEC_CHA_OFFSET_IE));
|
|
}
|
|
else
|
|
{
|
|
Secondary.SecondaryChannelOffset = 0;
|
|
}
|
|
|
|
if ((Elem->Msg[LENGTH_802_11+2] == IE_CHANNEL_SWITCH_ANNOUNCEMENT) && (Elem->Msg[LENGTH_802_11+3] == 3))
|
|
{
|
|
ChannelSwitchAction(pAd, Elem->Wcid, ChannelSwitch.NewChannel, Secondary.SecondaryChannelOffset);
|
|
}
|
|
#endif // DOT11N_DRAFT3 //
|
|
}
|
|
PeerChSwAnnAction(pAd, Elem);
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
|
|
Parametrs:
|
|
|
|
Return : None.
|
|
==========================================================================
|
|
*/
|
|
INT Set_MeasureReq_Proc(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR arg)
|
|
{
|
|
UINT Aid = 1;
|
|
UINT ArgIdx;
|
|
PUCHAR thisChar;
|
|
|
|
MEASURE_REQ_MODE MeasureReqMode;
|
|
UINT8 MeasureReqToken = RandomByte(pAd);
|
|
UINT8 MeasureReqType = RM_BASIC;
|
|
UINT8 MeasureCh = 1;
|
|
|
|
ArgIdx = 1;
|
|
while ((thisChar = strsep((char **)&arg, "-")) != NULL)
|
|
{
|
|
switch(ArgIdx)
|
|
{
|
|
case 1: // Aid.
|
|
Aid = simple_strtol(thisChar, 0, 16);
|
|
break;
|
|
|
|
case 2: // Measurement Request Type.
|
|
MeasureReqType = simple_strtol(thisChar, 0, 16);
|
|
if (MeasureReqType > 3)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __func__, MeasureReqType));
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case 3: // Measurement channel.
|
|
MeasureCh = simple_strtol(thisChar, 0, 16);
|
|
break;
|
|
}
|
|
ArgIdx++;
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, Aid, MeasureReqType, MeasureCh));
|
|
if (!VALID_WCID(Aid))
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
|
|
return TRUE;
|
|
}
|
|
|
|
MeasureReqMode.word = 0;
|
|
MeasureReqMode.field.Enable = 1;
|
|
|
|
MeasureReqInsert(pAd, MeasureReqToken);
|
|
|
|
EnqueueMeasurementReq(pAd, pAd->MacTab.Content[Aid].Addr,
|
|
MeasureReqToken, MeasureReqMode.word, MeasureReqType, MeasureCh, 2000);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_TpcReq_Proc(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR arg)
|
|
{
|
|
UINT Aid;
|
|
|
|
UINT8 TpcReqToken = RandomByte(pAd);
|
|
|
|
Aid = simple_strtol(arg, 0, 16);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
|
|
if (!VALID_WCID(Aid))
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
|
|
return TRUE;
|
|
}
|
|
|
|
TpcReqInsert(pAd, TpcReqToken);
|
|
|
|
EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);
|
|
|
|
return TRUE;
|
|
}
|
|
|