summaryrefslogtreecommitdiff
path: root/cleopatre/devkit/mt7601udrv/common
diff options
context:
space:
mode:
authorFisher Cheng2013-05-24 16:54:08 +0800
committerJulien Lacour2013-10-01 12:12:48 +0200
commit8c1eb022607c0aba81d93b961abbfb47a2dcc325 (patch)
tree13b1cd55172e93b3d1e5baa7141ba259fd71b0af /cleopatre/devkit/mt7601udrv/common
parent9e4d9d72dcac9686f1b4720e46e3bb88f6375a1e (diff)
cleo/devkit: add MTK MT7601U drv source code, refs #4011
- Enable Wireless LAN and Wireless extension in linux26.config
Diffstat (limited to 'cleopatre/devkit/mt7601udrv/common')
-rw-r--r--cleopatre/devkit/mt7601udrv/common/action.c1126
-rw-r--r--cleopatre/devkit/mt7601udrv/common/ba_action.c2190
-rw-r--r--cleopatre/devkit/mt7601udrv/common/client_wds.c197
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_aes.c1142
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_asic.c2699
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_cfg.c1494
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_cmd.c169
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_cs.c763
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_data.c3569
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_data_usb.c1312
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_dfs.c3136
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_info.c6151
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_mac_usb.c2159
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_mat.c443
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_mat_iparp.c694
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_mat_ipv6.c824
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_mat_pppoe.c1062
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_profile.c5059
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_radar.c329
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_sanity.c2162
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_sync.c494
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_tkip.c923
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_video.c168
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_wep.c365
-rw-r--r--cleopatre/devkit/mt7601udrv/common/cmm_wpa.c4728
-rw-r--r--cleopatre/devkit/mt7601udrv/common/crypt_aes.c1605
-rw-r--r--cleopatre/devkit/mt7601udrv/common/crypt_arc4.c139
-rw-r--r--cleopatre/devkit/mt7601udrv/common/crypt_biginteger.c1116
-rw-r--r--cleopatre/devkit/mt7601udrv/common/crypt_dh.c227
-rw-r--r--cleopatre/devkit/mt7601udrv/common/crypt_hmac.c282
-rw-r--r--cleopatre/devkit/mt7601udrv/common/crypt_md5.c356
-rw-r--r--cleopatre/devkit/mt7601udrv/common/crypt_sha2.c555
-rw-r--r--cleopatre/devkit/mt7601udrv/common/ee_efuse.c1893
-rw-r--r--cleopatre/devkit/mt7601udrv/common/ee_prom.c265
-rw-r--r--cleopatre/devkit/mt7601udrv/common/eeprom.c85
-rw-r--r--cleopatre/devkit/mt7601udrv/common/frq_cal.c28
-rw-r--r--cleopatre/devkit/mt7601udrv/common/igmp_snoop.c1511
-rw-r--r--cleopatre/devkit/mt7601udrv/common/image.binbin0 -> 67936 bytes
-rw-r--r--cleopatre/devkit/mt7601udrv/common/misc.c35
-rw-r--r--cleopatre/devkit/mt7601udrv/common/mlme.c4000
-rw-r--r--cleopatre/devkit/mt7601udrv/common/multi_channel.c1012
-rw-r--r--cleopatre/devkit/mt7601udrv/common/netif_block.c121
-rw-r--r--cleopatre/devkit/mt7601udrv/common/ps.c370
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rt2860.bin.dfsbin0 -> 8192 bytes
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rt2860.bin.oldbin0 -> 8192 bytes
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rt2870_wow.binbin0 -> 12288 bytes
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rt_channel.c2057
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rt_os_util.c161
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rt_rf.c33
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rtmp_init.c3849
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rtmp_init_inf.c1094
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rtmp_timer.c358
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rtusb_bulk.c1693
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rtusb_data.c31
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rtusb_dev_id.c48
-rw-r--r--cleopatre/devkit/mt7601udrv/common/rtusb_io.c2021
-rw-r--r--cleopatre/devkit/mt7601udrv/common/scan.c415
-rw-r--r--cleopatre/devkit/mt7601udrv/common/spectrum.c2393
-rw-r--r--cleopatre/devkit/mt7601udrv/common/txpower.c1172
-rw-r--r--cleopatre/devkit/mt7601udrv/common/uapsd.c2074
-rw-r--r--cleopatre/devkit/mt7601udrv/common/vht.c400
-rw-r--r--cleopatre/devkit/mt7601udrv/common/wapi.c1185
-rw-r--r--cleopatre/devkit/mt7601udrv/common/wfd.c823
-rw-r--r--cleopatre/devkit/mt7601udrv/common/wsc.c9058
-rw-r--r--cleopatre/devkit/mt7601udrv/common/wsc_tlv.c4002
-rw-r--r--cleopatre/devkit/mt7601udrv/common/wsc_ufd.c598
-rw-r--r--cleopatre/devkit/mt7601udrv/common/wsc_v2.c408
67 files changed, 90831 insertions, 0 deletions
diff --git a/cleopatre/devkit/mt7601udrv/common/action.c b/cleopatre/devkit/mt7601udrv/common/action.c
new file mode 100644
index 0000000000..945b902ad5
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/action.c
@@ -0,0 +1,1126 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ****************************************************************************
+
+ Module Name:
+ action.c
+
+ Abstract:
+ Handle association related requests either from WSTA or from local MLME
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Jan Lee 2006 created for rt2860
+ */
+
+#include "rt_config.h"
+#include "action.h"
+
+extern UCHAR ZeroSsid[32];
+
+
+static VOID ReservedAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+
+/*
+ ==========================================================================
+ Description:
+ association state machine init, including state transition and timer init
+ Parameters:
+ S - pointer to the association state machine
+ Note:
+ The state machine looks like the following
+
+ ASSOC_IDLE
+ MT2_MLME_DISASSOC_REQ mlme_disassoc_req_action
+ MT2_PEER_DISASSOC_REQ peer_disassoc_action
+ MT2_PEER_ASSOC_REQ drop
+ MT2_PEER_REASSOC_REQ drop
+ MT2_CLS3ERR cls3err_action
+ ==========================================================================
+ */
+VOID ActionStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ OUT STATE_MACHINE_FUNC Trans[])
+{
+ StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_ACT_STATE, MAX_ACT_MSG, (STATE_MACHINE_FUNC)Drop, ACT_IDLE, ACT_MACHINE_BASE);
+
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, (STATE_MACHINE_FUNC)PeerSpectrumAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, (STATE_MACHINE_FUNC)PeerQOSAction);
+
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)ReservedAction);
+#ifdef QOS_DLS_SUPPORT
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)PeerDLSAction);
+#endif /* QOS_DLS_SUPPORT */
+
+#ifdef DOT11_N_SUPPORT
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, (STATE_MACHINE_FUNC)PeerBAAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, (STATE_MACHINE_FUNC)PeerHTAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, (STATE_MACHINE_FUNC)MlmeADDBAAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction);
+#endif /* DOT11_N_SUPPORT */
+
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, (STATE_MACHINE_FUNC)PeerPublicAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, (STATE_MACHINE_FUNC)PeerRMAction);
+
+ StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, (STATE_MACHINE_FUNC)MlmeQOSAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, (STATE_MACHINE_FUNC)MlmeDLSAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, (STATE_MACHINE_FUNC)MlmeInvalidAction);
+
+
+#ifdef CONFIG_AP_SUPPORT
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+}
+
+#ifdef DOT11_N_SUPPORT
+VOID MlmeADDBAAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+
+{
+ MLME_ADDBA_REQ_STRUCT *pInfo;
+ UCHAR Addr[6];
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG Idx;
+ FRAME_ADDBA_REQ Frame;
+ ULONG FrameLen;
+ BA_ORI_ENTRY *pBAEntry = NULL;
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR apidx;
+#endif /* CONFIG_AP_SUPPORT */
+
+ pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg;
+ NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ));
+
+ if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr) &&
+ VALID_WCID(pInfo->Wcid))
+ {
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory*/
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n"));
+ return;
+ }
+ /* 1. find entry */
+ Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID];
+ if (Idx == 0)
+ {
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n"));
+ return;
+ }
+ else
+ {
+ pBAEntry =&pAd->BATable.BAOriEntry[Idx];
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pInfo->Wcid]))
+ {
+ apidx = pAd->MacTab.Content[pInfo->Wcid].MatchAPCLITabIdx;
+ ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pInfo->pAddr);
+ }
+ else
+#endif /* APCLI_SUPPORT */
+ {
+ apidx = pAd->MacTab.Content[pInfo->Wcid].apidx;
+ ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ Frame.Category = CATEGORY_BA;
+ Frame.Action = ADDBA_REQ;
+ Frame.BaParm.AMSDUSupported = 0;
+ Frame.BaParm.BAPolicy = IMMED_BA;
+ Frame.BaParm.TID = pInfo->TID;
+ Frame.BaParm.BufSize = pInfo->BaBufSize;
+ Frame.Token = pInfo->Token;
+ Frame.TimeOutValue = pInfo->TimeOutValue;
+ Frame.BaStartSeq.field.FragNum = 0;
+ Frame.BaStartSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID];
+
+#ifdef UNALIGNMENT_SUPPORT
+ {
+ BA_PARM tmpBaParm;
+
+ NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&Frame.BaParm), sizeof(BA_PARM));
+ *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm));
+ NdisMoveMemory((PUCHAR)(&Frame.BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM));
+ }
+#else
+ *(USHORT *)(&(Frame.BaParm)) = cpu2le16((*(USHORT *)(&(Frame.BaParm))));
+#endif /* UNALIGNMENT_SUPPORT */
+
+ Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue);
+ Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word);
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_ADDBA_REQ), &Frame,
+ END_OF_ARGS);
+
+ MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | MapUserPriorityToAccessCategory[pInfo->TID]), pOutBuffer, FrameLen);
+
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize));
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ send DELBA and delete BaEntry if any
+ Parametrs:
+ Elem - MLME message MLME_DELBA_REQ_STRUCT
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeDELBAAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ MLME_DELBA_REQ_STRUCT *pInfo;
+ PUCHAR pOutBuffer = NULL;
+ PUCHAR pOutBuffer2 = NULL;
+ NDIS_STATUS NStatus;
+ ULONG Idx;
+ FRAME_DELBA_REQ Frame;
+ ULONG FrameLen;
+ FRAME_BAR FrameBar;
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR apidx;
+#endif /* CONFIG_AP_SUPPORT */
+
+ pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg;
+ /* must send back DELBA */
+ NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ));
+ DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator));
+
+ if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen) &&
+ VALID_WCID(pInfo->Wcid))
+ {
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n"));
+ return;
+ }
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); /*Get an unused nonpaged memory*/
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n"));
+ return;
+ }
+
+ /* SEND BAR (Send BAR to refresh peer reordering buffer.) */
+ Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID];
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pInfo->Wcid]))
+ {
+ apidx = pAd->MacTab.Content[pInfo->Wcid].MatchAPCLITabIdx;
+ BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress);
+ }
+ else
+#endif /* APCLI_SUPPORT */
+ {
+ apidx = pAd->MacTab.Content[pInfo->Wcid].apidx;
+ BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL funciton.*/
+ FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; /* make sure sequence not clear in DEL funciton.*/
+ FrameBar.BarControl.TID = pInfo->TID; /* make sure sequence not clear in DEL funciton.*/
+ FrameBar.BarControl.ACKPolicy = IMMED_BA; /* make sure sequence not clear in DEL funciton.*/
+ FrameBar.BarControl.Compressed = 1; /* make sure sequence not clear in DEL funciton.*/
+ FrameBar.BarControl.MTID = 0; /* make sure sequence not clear in DEL funciton.*/
+
+ MakeOutgoingFrame(pOutBuffer2, &FrameLen,
+ sizeof(FRAME_BAR), &FrameBar,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer2);
+ DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n"));
+
+ /* SEND DELBA FRAME*/
+ FrameLen = 0;
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pInfo->Wcid]))
+ {
+ apidx = pAd->MacTab.Content[pInfo->Wcid].MatchAPCLITabIdx;
+ ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr);
+ }
+ else
+#endif /* APCLI_SUPPORT */
+ {
+ apidx = pAd->MacTab.Content[pInfo->Wcid].apidx;
+ ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ Frame.Category = CATEGORY_BA;
+ Frame.Action = DELBA;
+ Frame.DelbaParm.Initiator = pInfo->Initiator;
+ Frame.DelbaParm.TID = pInfo->TID;
+ Frame.ReasonCode = 39; /* Time Out*/
+ *(USHORT *)(&Frame.DelbaParm) = cpu2le16(*(USHORT *)(&Frame.DelbaParm));
+ Frame.ReasonCode = cpu2le16(Frame.ReasonCode);
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_DELBA_REQ), &Frame,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator));
+ }
+}
+#endif /* DOT11_N_SUPPORT */
+
+VOID MlmeQOSAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+VOID MlmeDLSAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+VOID MlmeInvalidAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ /*PUCHAR pOutBuffer = NULL;*/
+ /*Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11*/
+}
+
+VOID PeerQOSAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+#ifdef QOS_DLS_SUPPORT
+VOID PeerDLSAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Action = Elem->Msg[LENGTH_802_11+1];
+
+ switch(Action)
+ {
+ case ACTION_DLS_REQUEST:
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ APPeerDlsReqAction(pAd, Elem);
+#endif /* CONFIG_AP_SUPPORT */
+ break;
+
+ case ACTION_DLS_RESPONSE:
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ APPeerDlsRspAction(pAd, Elem);
+#endif /* CONFIG_AP_SUPPORT */
+ break;
+
+ case ACTION_DLS_TEARDOWN:
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ APPeerDlsTearDownAction(pAd, Elem);
+#endif /* CONFIG_AP_SUPPORT */
+ break;
+ }
+}
+#endif /* QOS_DLS_SUPPORT */
+
+
+
+#ifdef DOT11_N_SUPPORT
+VOID PeerBAAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Action = Elem->Msg[LENGTH_802_11+1];
+
+ switch(Action)
+ {
+ case ADDBA_REQ:
+ PeerAddBAReqAction(pAd,Elem);
+ break;
+ case ADDBA_RESP:
+ PeerAddBARspAction(pAd,Elem);
+ break;
+ case DELBA:
+ PeerDelBAAction(pAd,Elem);
+ break;
+ }
+}
+
+
+#ifdef DOT11N_DRAFT3
+#ifdef CONFIG_AP_SUPPORT
+extern UCHAR get_regulatory_class(IN PRTMP_ADAPTER pAd);
+
+VOID ApPublicAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Action = Elem->Msg[LENGTH_802_11+1];
+ BSS_2040_COEXIST_IE BssCoexist;
+
+ /* Format as in IEEE 7.4.7.2*/
+ if (Action == ACTION_BSS_2040_COEXIST)
+ {
+ BssCoexist.word = Elem->Msg[LENGTH_802_11+2];
+ }
+}
+
+
+VOID SendBSS2040CoexistMgmtAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR apidx,
+ IN UCHAR InfoReq)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ FRAME_ACTION_HDR Frame;
+ ULONG FrameLen;
+ BSS_2040_COEXIST_ELEMENT BssCoexistInfo;
+ BSS_2040_INTOLERANT_CH_REPORT BssIntolerantInfo;
+ PUCHAR pAddr1;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("SendBSS2040CoexistMgmtAction(): Wcid=%d, apidx=%d, InfoReq=%d!\n", Wcid, apidx, InfoReq));
+
+ NdisZeroMemory((PUCHAR)&BssCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT));
+ NdisZeroMemory((PUCHAR)&BssIntolerantInfo, sizeof(BSS_2040_INTOLERANT_CH_REPORT));
+
+ BssCoexistInfo.ElementID = IE_2040_BSS_COEXIST;
+ BssCoexistInfo.Len = 1;
+ BssCoexistInfo.BssCoexistIe.word = pAd->CommonCfg.LastBSSCoexist2040.word;
+ BssCoexistInfo.BssCoexistIe.field.InfoReq = InfoReq;
+ BssIntolerantInfo.ElementID = IE_2040_BSS_INTOLERANT_REPORT;
+ BssIntolerantInfo.Len = 1;
+ BssIntolerantInfo.RegulatoryClass = get_regulatory_class(pAd);
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("ACT - SendBSS2040CoexistMgmtAction() allocate memory failed \n"));
+ return;
+ }
+
+ if (Wcid == MCAST_WCID)
+ pAddr1 = &BROADCAST_ADDR[0];
+ else
+ pAddr1 = pAd->MacTab.Content[Wcid].Addr;
+ ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
+
+ Frame.Category = CATEGORY_PUBLIC;
+ Frame.Action = ACTION_BSS_2040_COEXIST;
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_ACTION_HDR), &Frame,
+ sizeof(BSS_2040_COEXIST_ELEMENT), &BssCoexistInfo,
+ sizeof(BSS_2040_INTOLERANT_CH_REPORT), &BssIntolerantInfo,
+ END_OF_ARGS);
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ DBGPRINT(RT_DEBUG_ERROR,("ACT - SendBSS2040CoexistMgmtAction( BSSCoexist2040 = 0x%x ) \n", BssCoexistInfo.BssCoexistIe.word));
+
+}
+
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+BOOLEAN ChannelSwitchSanityCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR NewChannel,
+ IN UCHAR Secondary)
+{
+ UCHAR i;
+
+ if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+ return FALSE;
+
+ if ((NewChannel > 7) && (Secondary == 1))
+ return FALSE;
+
+ if ((NewChannel < 5) && (Secondary == 3))
+ return FALSE;
+
+ /* 0. Check if new channel is in the channellist.*/
+ for (i = 0;i < pAd->ChannelListNum;i++)
+ {
+ if (pAd->ChannelList[i].Channel == NewChannel)
+ {
+ break;
+ }
+ }
+
+ if (i == pAd->ChannelListNum)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+VOID ChannelSwitchAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR NewChannel,
+ IN UCHAR Secondary)
+{
+ UCHAR rf_channel = 0, rf_bw;
+
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s(): NewChannel=%d, Secondary=%d\n",
+ __FUNCTION__, NewChannel, Secondary));
+
+ if (ChannelSwitchSanityCheck(pAd, Wcid, NewChannel, Secondary) == FALSE)
+ return;
+
+ pAd->CommonCfg.Channel = NewChannel;
+ if (Secondary == EXTCHA_NONE)
+ {
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
+ pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 0;
+ pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0;
+ pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0;
+
+ rf_bw = BW_20;
+ rf_channel = pAd->CommonCfg.Channel;
+ }
+ /* 1. Switches to BW = 40 And Station supports BW = 40.*/
+ else if (((Secondary == EXTCHA_ABOVE) || (Secondary == EXTCHA_BELOW)) &&
+ (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)
+ )
+ {
+ rf_bw = BW_40;
+#ifdef GREENAP_SUPPORT
+ if (pAd->ApCfg.bGreenAPActive == 1)
+ {
+ rf_bw = BW_20;
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
+ }
+ else
+#endif /* GREENAP_SUPPORT */
+ if (Secondary == EXTCHA_ABOVE)
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2;
+ else
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2;
+
+ rf_channel = pAd->CommonCfg.CentralChannel;
+ pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 1;
+ }
+
+ if (rf_channel != 0) {
+ AsicSetChannel(pAd, rf_channel, rf_bw, Secondary, FALSE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): %dMHz LINK UP, CtrlChannel=%d, CentralChannel= %d \n",
+ __FUNCTION__, (rf_bw == BW_40 ? 40 : 20),
+ pAd->CommonCfg.Channel,
+ pAd->CommonCfg.CentralChannel));
+ }
+}
+#endif /* DOT11N_DRAFT3 */
+#endif /* DOT11_N_SUPPORT */
+
+VOID PeerPublicAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Action = Elem->Msg[LENGTH_802_11+1];
+ if ((Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
+ )
+ return;
+
+
+ switch(Action)
+ {
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+ case ACTION_BSS_2040_COEXIST: /* Format defined in IEEE 7.4.7a.1 in 11n Draf3.03*/
+ {
+ /*UCHAR BssCoexist;*/
+ BSS_2040_COEXIST_ELEMENT *pCoexistInfo;
+ BSS_2040_COEXIST_IE *pBssCoexistIe;
+ BSS_2040_INTOLERANT_CH_REPORT *pIntolerantReport = NULL;
+
+ if (Elem->MsgLen <= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT)) )
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ACTION - 20/40 BSS Coexistence Management Frame length too short! len = %ld!\n", Elem->MsgLen));
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("ACTION - 20/40 BSS Coexistence Management action----> \n"));
+ hex_dump("CoexistenceMgmtFrame", Elem->Msg, Elem->MsgLen);
+
+
+ pCoexistInfo = (BSS_2040_COEXIST_ELEMENT *) &Elem->Msg[LENGTH_802_11+2];
+ /*hex_dump("CoexistInfo", (PUCHAR)pCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT));*/
+ if (Elem->MsgLen >= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT) + sizeof(BSS_2040_INTOLERANT_CH_REPORT)))
+ {
+ pIntolerantReport = (BSS_2040_INTOLERANT_CH_REPORT *)((PUCHAR)pCoexistInfo + sizeof(BSS_2040_COEXIST_ELEMENT));
+ }
+ /*hex_dump("IntolerantReport ", (PUCHAR)pIntolerantReport, sizeof(BSS_2040_INTOLERANT_CH_REPORT));*/
+
+ if(pAd->CommonCfg.bBssCoexEnable == FALSE || (pAd->CommonCfg.bForty_Mhz_Intolerant == TRUE))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("20/40 BSS CoexMgmt=%d, bForty_Mhz_Intolerant=%d, ignore this action!!\n",
+ pAd->CommonCfg.bBssCoexEnable,
+ pAd->CommonCfg.bForty_Mhz_Intolerant));
+ break;
+ }
+
+ pBssCoexistIe = (BSS_2040_COEXIST_IE *)(&pCoexistInfo->BssCoexistIe);
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ BOOLEAN bNeedFallBack = FALSE;
+
+ /*ApPublicAction(pAd, Elem);*/
+ if ((pBssCoexistIe->field.BSS20WidthReq ==1) || (pBssCoexistIe->field.Intolerant40 == 1))
+ {
+ bNeedFallBack = TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BSS_2040_COEXIST: BSS20WidthReq=%d, Intolerant40=%d!\n", pBssCoexistIe->field.BSS20WidthReq, pBssCoexistIe->field.Intolerant40));
+ }
+ else if ((pIntolerantReport) && (pIntolerantReport->Len > 1)
+ /*&& (pIntolerantReport->RegulatoryClass == get_regulatory_class(pAd))*/)
+ {
+ int i;
+ UCHAR *ptr;
+ INT retVal;
+ BSS_COEX_CH_RANGE coexChRange;
+
+ ptr = pIntolerantReport->ChList;
+ bNeedFallBack = TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("The pIntolerantReport len = %d, chlist=", pIntolerantReport->Len));
+ for(i =0 ; i < (pIntolerantReport->Len -1); i++, ptr++)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%d,", *ptr));
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("\n"));
+
+ retVal = GetBssCoexEffectedChRange(pAd, &coexChRange);
+ if (retVal == TRUE)
+ {
+ ptr = pIntolerantReport->ChList;
+ bNeedFallBack = FALSE;
+ DBGPRINT(RT_DEBUG_TRACE, ("Check IntolerantReport Channel List in our effectedChList(%d~%d)\n",
+ pAd->ChannelList[coexChRange.effectChStart].Channel,
+ pAd->ChannelList[coexChRange.effectChEnd].Channel));
+ for(i =0 ; i < (pIntolerantReport->Len -1); i++, ptr++)
+ {
+ UCHAR chEntry;
+
+ chEntry = *ptr;
+ if (chEntry >= pAd->ChannelList[coexChRange.effectChStart].Channel &&
+ chEntry <= pAd->ChannelList[coexChRange.effectChEnd].Channel)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Found Intolerant channel in effect range=%d!\n", *ptr));
+ bNeedFallBack = TRUE;
+ break;
+ }
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("After CoexChRange Check, bNeedFallBack=%d!\n", bNeedFallBack));
+ }
+
+ if (bNeedFallBack)
+ {
+ pBssCoexistIe->field.Intolerant40 = 1;
+ pBssCoexistIe->field.BSS20WidthReq = 1;
+ }
+ }
+
+ if (bNeedFallBack)
+ {
+ int apidx;
+
+ NdisMoveMemory((PUCHAR)&pAd->CommonCfg.LastBSSCoexist2040, (PUCHAR)pBssCoexistIe, sizeof(BSS_2040_COEXIST_IE));
+ pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_SYNC;
+
+ if (!(pAd->CommonCfg.Bss2040CoexistFlag & BSS_2040_COEXIST_TIMER_FIRED))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Fire the Bss2040CoexistTimer with timeout=%ld!\n",
+ pAd->CommonCfg.Dot11BssWidthChanTranDelay));
+
+ pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_TIMER_FIRED;
+ /* More 5 sec for the scan report of STAs.*/
+ RTMPSetTimer(&pAd->CommonCfg.Bss2040CoexistTimer, (pAd->CommonCfg.Dot11BssWidthChanTranDelay + 5) * 1000);
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Already fallback to 20MHz, Extend the timeout of Bss2040CoexistTimer!\n"));
+ /* More 5 sec for the scan report of STAs.*/
+ RTMPModTimer(&pAd->CommonCfg.Bss2040CoexistTimer, (pAd->CommonCfg.Dot11BssWidthChanTranDelay + 5) * 1000);
+ }
+
+ apidx = pAd->MacTab.Content[Elem->Wcid].apidx;
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ SendBSS2040CoexistMgmtAction(pAd, MCAST_WCID, apidx, 0);
+ }
+
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ break;
+#endif /* DOT11N_DRAFT3 */
+#endif /* DOT11_N_SUPPORT */
+
+ case ACTION_WIFI_DIRECT:
+
+ break;
+
+
+ default:
+ break;
+ }
+
+}
+
+
+static VOID ReservedAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Category;
+
+ if (Elem->MsgLen <= LENGTH_802_11)
+ {
+ return;
+ }
+
+ Category = Elem->Msg[LENGTH_802_11];
+ DBGPRINT(RT_DEBUG_TRACE,("Rcv reserved category(%d) Action Frame\n", Category));
+ hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen);
+}
+
+VOID PeerRMAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+
+{
+#ifdef CONFIG_AP_SUPPORT
+#endif /* CONFIG_AP_SUPPORT */
+ return;
+}
+
+#ifdef DOT11_N_SUPPORT
+static VOID respond_ht_information_exchange_action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen;
+#ifdef CONFIG_AP_SUPPORT
+ INT apidx;
+#endif /* CONFIG_AP_SUPPORT */
+ FRAME_HT_INFO HTINFOframe, *pFrame;
+ UCHAR *pAddr;
+
+
+ /* 2. Always send back ADDBA Response */
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/
+
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("ACTION - respond_ht_information_exchange_action() allocate memory failed \n"));
+ return;
+ }
+
+ /* get RA */
+ pFrame = (FRAME_HT_INFO *) &Elem->Msg[0];
+ pAddr = pFrame->Hdr.Addr2;
+
+ NdisZeroMemory(&HTINFOframe, sizeof(FRAME_HT_INFO));
+ /* 2-1. Prepare ADDBA Response frame.*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Elem->Wcid]))
+ {
+ apidx = pAd->MacTab.Content[Elem->Wcid].MatchAPCLITabIdx;
+ ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pAddr);
+ }
+ else
+#endif /* APCLI_SUPPORT */
+ {
+ apidx = pAd->MacTab.Content[Elem->Wcid].apidx;
+ ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ HTINFOframe.Category = CATEGORY_HT;
+ HTINFOframe.Action = HT_INFO_EXCHANGE;
+ HTINFOframe.HT_Info.Request = 0;
+ HTINFOframe.HT_Info.Forty_MHz_Intolerant = pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant;
+ HTINFOframe.HT_Info.STA_Channel_Width = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_HT_INFO), &HTINFOframe,
+ END_OF_ARGS);
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+}
+
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef DOT11N_DRAFT3
+VOID SendNotifyBWActionFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR apidx)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ FRAME_ACTION_HDR Frame;
+ ULONG FrameLen;
+ PUCHAR pAddr1;
+
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("ACT - SendNotifyBWAction() allocate memory failed \n"));
+ return;
+ }
+
+ if (Wcid == MCAST_WCID)
+ pAddr1 = &BROADCAST_ADDR[0];
+ else
+ pAddr1 = pAd->MacTab.Content[Wcid].Addr;
+
+ ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
+
+ Frame.Category = CATEGORY_HT;
+ Frame.Action = NOTIFY_BW_ACTION;
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_ACTION_HDR), &Frame,
+ END_OF_ARGS);
+
+ *(pOutBuffer + FrameLen) = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
+ FrameLen++;
+
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_TRACE,("ACT - SendNotifyBWAction(NotifyBW= %d)!\n", pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth));
+
+}
+#endif /* DOT11N_DRAFT3 */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+VOID PeerHTAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Action = Elem->Msg[LENGTH_802_11+1];
+ MAC_TABLE_ENTRY *pEntry;
+
+ if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
+ return;
+
+ pEntry = &pAd->MacTab.Content[Elem->Wcid];
+
+ switch(Action)
+ {
+ case NOTIFY_BW_ACTION:
+ DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Notify Channel bandwidth action----> \n"));
+
+ if (Elem->Msg[LENGTH_802_11+2] == 0) /* 7.4.8.2. if value is 1, keep the same as supported channel bandwidth. */
+ pEntry->HTPhyMode.field.BW = 0;
+ else
+ {
+ pEntry->HTPhyMode.field.BW = pEntry->MaxHTPhyMode.field.BW &
+ pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth;
+ }
+
+ break;
+
+ case SMPS_ACTION:
+ /* 7.3.1.25*/
+ DBGPRINT(RT_DEBUG_TRACE,("ACTION - SMPS action----> \n"));
+ if (((Elem->Msg[LENGTH_802_11+2] & 0x1) == 0))
+ pEntry->MmpsMode = MMPS_ENABLE;
+ else if (((Elem->Msg[LENGTH_802_11+2] & 0x2) == 0))
+ pEntry->MmpsMode = MMPS_STATIC;
+ else
+ pEntry->MmpsMode = MMPS_DYNAMIC;
+
+ DBGPRINT(RT_DEBUG_TRACE,("Aid(%d) MIMO PS = %d\n", Elem->Wcid, pEntry->MmpsMode));
+ /* rt2860c : add something for smps change.*/
+ break;
+
+ case SETPCO_ACTION:
+ break;
+
+ case MIMO_CHA_MEASURE_ACTION:
+ break;
+
+ case HT_INFO_EXCHANGE:
+ {
+ HT_INFORMATION_OCTET *pHT_info;
+
+ pHT_info = (HT_INFORMATION_OCTET *) &Elem->Msg[LENGTH_802_11+2];
+ /* 7.4.8.10*/
+ DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Information Exchange action----> \n"));
+ if (pHT_info->Request)
+ {
+ respond_ht_information_exchange_action(pAd, Elem);
+ }
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if (pHT_info->Forty_MHz_Intolerant)
+ {
+ Handle_BSS_Width_Trigger_Events(pAd);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ break;
+ }
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Retry sending ADDBA Reqest.
+
+ IRQL = DISPATCH_LEVEL
+
+ Parametrs:
+ p8023Header: if this is already 802.3 format, p8023Header is NULL
+
+ Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
+ FALSE , then continue indicaterx at this moment.
+ ==========================================================================
+ */
+VOID ORIBATimerTimeout(
+ IN PRTMP_ADAPTER pAd)
+{
+ MAC_TABLE_ENTRY *pEntry;
+ INT i, total;
+/* FRAME_BAR FrameBar;*/
+/* ULONG FrameLen;*/
+/* NDIS_STATUS NStatus;*/
+/* PUCHAR pOutBuffer = NULL;*/
+/* USHORT Sequence;*/
+ UCHAR TID;
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ return;
+#endif /* RALINK_ATE */
+
+ total = pAd->MacTab.Size * NUM_OF_TID;
+
+ for (i = 1; ((i <MAX_LEN_OF_BA_ORI_TABLE) && (total > 0)) ; i++)
+ {
+ if (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done)
+ {
+ pEntry = &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i].Wcid];
+ TID = pAd->BATable.BAOriEntry[i].TID;
+
+ ASSERT(pAd->BATable.BAOriEntry[i].Wcid < MAX_LEN_OF_MAC_TABLE);
+ }
+ total --;
+ }
+}
+
+
+VOID SendRefreshBAR(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ FRAME_BAR FrameBar;
+ ULONG FrameLen;
+ NDIS_STATUS NStatus;
+ PUCHAR pOutBuffer = NULL;
+ USHORT Sequence;
+ UCHAR i, TID;
+ USHORT idx;
+ BA_ORI_ENTRY *pBAEntry;
+
+ for (i = 0; i <NUM_OF_TID; i++)
+ {
+ idx = pEntry->BAOriWcidArray[i];
+ if (idx == 0)
+ {
+ continue;
+ }
+ pBAEntry = &pAd->BATable.BAOriEntry[idx];
+
+ if (pBAEntry->ORI_BA_Status == Originator_Done)
+ {
+ TID = pBAEntry->TID;
+
+ ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE);
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
+ return;
+ }
+
+ Sequence = pEntry->TxSeq[TID];
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(pEntry))
+ BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].CurrentAddress);
+ else
+#endif /* APCLI_SUPPORT */
+ BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].Bssid);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function.*/
+ FrameBar.StartingSeq.field.StartSeq = Sequence; /* make sure sequence not clear in DEL funciton.*/
+ FrameBar.BarControl.TID = TID; /* make sure sequence not clear in DEL funciton.*/
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_BAR), &FrameBar,
+ END_OF_ARGS);
+ /*if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET)))*/
+ if (1) /* Now we always send BAR.*/
+ {
+ /*MiniportMMRequestUnlock(pAd, 0, pOutBuffer, FrameLen);*/
+ MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | MapUserPriorityToAccessCategory[TID]), pOutBuffer, FrameLen);
+
+ }
+ MlmeFreeMemory(pAd, pOutBuffer);
+ }
+ }
+}
+#endif /* DOT11_N_SUPPORT */
+
+VOID ActHeaderInit(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PHEADER_802_11 pHdr80211,
+ IN PUCHAR Addr1,
+ IN PUCHAR Addr2,
+ IN PUCHAR Addr3)
+{
+ NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
+ pHdr80211->FC.Type = BTYPE_MGMT;
+ pHdr80211->FC.SubType = SUBTYPE_ACTION;
+
+ COPY_MAC_ADDR(pHdr80211->Addr1, Addr1);
+ COPY_MAC_ADDR(pHdr80211->Addr2, Addr2);
+ COPY_MAC_ADDR(pHdr80211->Addr3, Addr3);
+}
+
+VOID BarHeaderInit(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PFRAME_BAR pCntlBar,
+ IN PUCHAR pDA,
+ IN PUCHAR pSA)
+{
+/* USHORT Duration;*/
+
+ NdisZeroMemory(pCntlBar, sizeof(FRAME_BAR));
+ pCntlBar->FC.Type = BTYPE_CNTL;
+ pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ;
+ pCntlBar->BarControl.MTID = 0;
+ pCntlBar->BarControl.Compressed = 1;
+ pCntlBar->BarControl.ACKPolicy = 0;
+
+
+ pCntlBar->Duration = 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(FRAME_BA));
+
+ COPY_MAC_ADDR(pCntlBar->Addr1, pDA);
+ COPY_MAC_ADDR(pCntlBar->Addr2, pSA);
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Insert Category and action code into the action frame.
+
+ Parametrs:
+ 1. frame buffer pointer.
+ 2. frame length.
+ 3. category code of the frame.
+ 4. action code of the frame.
+
+ Return : None.
+ ==========================================================================
+ */
+VOID InsertActField(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pFrameBuf,
+ OUT PULONG pFrameLen,
+ IN UINT8 Category,
+ IN UINT8 ActCode)
+{
+ ULONG TempLen;
+
+ MakeOutgoingFrame( pFrameBuf, &TempLen,
+ 1, &Category,
+ 1, &ActCode,
+ END_OF_ARGS);
+
+ *pFrameLen = *pFrameLen + TempLen;
+
+ return;
+}
diff --git a/cleopatre/devkit/mt7601udrv/common/ba_action.c b/cleopatre/devkit/mt7601udrv/common/ba_action.c
new file mode 100644
index 0000000000..cc7211f013
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/ba_action.c
@@ -0,0 +1,2190 @@
+#ifdef DOT11_N_SUPPORT
+
+#include "rt_config.h"
+
+
+
+#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) /*1 inital sequence number of BA session*/
+
+#define ORI_SESSION_MAX_RETRY 8
+#define ORI_BA_SESSION_TIMEOUT (2000) /* ms*/
+#define REC_BA_SESSION_IDLE_TIMEOUT (1000) /* ms*/
+
+#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms*/
+#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) /* system ticks -- 100 ms*/
+
+
+#define RESET_RCV_SEQ (0xFFFF)
+
+static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk);
+
+
+BA_ORI_ENTRY *BATableAllocOriEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT USHORT *Idx);
+
+BA_REC_ENTRY *BATableAllocRecEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT USHORT *Idx);
+
+VOID BAOriSessionSetupTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID BARecSessionIdleTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+
+BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout);
+BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout);
+
+#define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
+ Announce_Reordering_Packet(_pAd, _mpdu_blk);
+
+VOID BA_MaxWinSizeReasign(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntryPeer,
+ OUT UCHAR *pWinSize)
+{
+ UCHAR MaxSize;
+ UCHAR MaxPeerRxSize;
+
+
+ if (CLIENT_STATUS_TEST_FLAG(pEntryPeer, fCLIENT_STATUS_RALINK_CHIPSET))
+ MaxPeerRxSize = (1 << (pEntryPeer->MaxRAmpduFactor + 3)); /* (2^(13 + exp)) / 2048 bytes */
+ else
+ MaxPeerRxSize = (((1 << (pEntryPeer->MaxRAmpduFactor + 3)) * 10) / 16) -1;
+
+#ifdef RT65xx
+ if (IS_RT65XX(pAd))
+ MaxSize = 31;
+ else
+#endif /* RT65xx */
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ MaxSize = 21;
+ else
+#endif /* MT7601 */
+ if (pAd->MACVersion >= RALINK_2883_VERSION)
+ {
+ if (pAd->MACVersion >= RALINK_3070_VERSION)
+ {
+ if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
+ MaxSize = 7; /* for non-open mode*/
+ else
+ MaxSize = 13;
+ }
+ else
+ MaxSize = 31;
+ }
+ else if (pAd->MACVersion >= RALINK_2880E_VERSION) /* 2880e */
+ {
+ if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
+ MaxSize = 7; /* for non-open mode */
+ else
+ MaxSize = 13;
+ }
+ else
+ MaxSize = 7;
+
+#ifdef CONFIG_AP_SUPPORT
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ba>WinSize=%d, MaxSize=%d, MaxPeerRxSize=%d\n",
+ *pWinSize, MaxSize, MaxPeerRxSize));
+
+ MaxSize = min(MaxPeerRxSize, MaxSize);
+ if ((*pWinSize) > MaxSize)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n",
+ *pWinSize, MaxSize));
+
+ *pWinSize = MaxSize;
+ }
+}
+
+void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd,
+ IN struct reordering_mpdu *mpdu)
+{
+ PNDIS_PACKET pPacket;
+
+ pPacket = mpdu->pPacket;
+
+ if (mpdu->bAMSDU)
+ {
+ /*ASSERT(0);*/
+ BA_Reorder_AMSDU_Annnounce(pAd, pPacket, mpdu->OpMode);
+ }
+ else
+ {
+
+ /* pass this 802.3 packet to upper layer or forward this packet to WM directly */
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket));
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+}
+
+/*
+ * Insert a reordering mpdu into sorted linked list by sequence no.
+ */
+BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu)
+{
+
+ struct reordering_mpdu **ppScan = &list->next;
+
+ while (*ppScan != NULL)
+ {
+ if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ))
+ {
+ ppScan = &(*ppScan)->next;
+ }
+ else if ((*ppScan)->Sequence == mpdu->Sequence)
+ {
+ /* give up this duplicated frame */
+ return(FALSE);
+ }
+ else
+ {
+ /* find position */
+ break;
+ }
+ }
+
+ mpdu->next = *ppScan;
+ *ppScan = mpdu;
+ list->qlen++;
+ return TRUE;
+}
+
+
+/*
+ * caller lock critical section if necessary
+ */
+static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk)
+{
+ list->qlen++;
+ mpdu_blk->next = list->next;
+ list->next = mpdu_blk;
+}
+
+/*
+ * caller lock critical section if necessary
+ */
+static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list)
+{
+ struct reordering_mpdu *mpdu_blk = NULL;
+
+ ASSERT(list);
+
+ if (list->qlen)
+ {
+ list->qlen--;
+ mpdu_blk = list->next;
+ if (mpdu_blk)
+ {
+ list->next = mpdu_blk->next;
+ mpdu_blk->next = NULL;
+ }
+ }
+ return mpdu_blk;
+}
+
+
+static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list)
+{
+ return(ba_dequeue(list));
+}
+
+
+static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list)
+ {
+ ASSERT(list);
+
+ return(list->next);
+ }
+
+
+/*
+ * free all resource for reordering mechanism
+ */
+void ba_reordering_resource_release(PRTMP_ADAPTER pAd)
+{
+ BA_TABLE *Tab;
+ PBA_REC_ENTRY pBAEntry;
+ struct reordering_mpdu *mpdu_blk;
+ int i;
+
+ Tab = &pAd->BATable;
+
+ /* I. release all pending reordering packet */
+ NdisAcquireSpinLock(&pAd->BATabLock);
+ for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
+ {
+ pBAEntry = &Tab->BARecEntry[i];
+ if (pBAEntry->REC_BA_Status != Recipient_NONE)
+ {
+ while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
+ {
+ ASSERT(mpdu_blk->pPacket);
+ RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE);
+ ba_mpdu_blk_free(pAd, mpdu_blk);
+ }
+ }
+ }
+ NdisReleaseSpinLock(&pAd->BATabLock);
+
+ ASSERT(pBAEntry->list.qlen == 0);
+ /* II. free memory of reordering mpdu table */
+ NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
+ os_free_mem(pAd, pAd->mpdu_blk_pool.mem);
+ NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
+}
+
+
+
+/*
+ * Allocate all resource for reordering mechanism
+ */
+BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num)
+{
+ int i;
+ PUCHAR mem;
+ struct reordering_mpdu *mpdu_blk;
+ struct reordering_list *freelist;
+
+ /* allocate spinlock */
+ NdisAllocateSpinLock(pAd, &pAd->mpdu_blk_pool.lock);
+
+ /* initialize freelist */
+ freelist = &pAd->mpdu_blk_pool.freelist;
+ freelist->next = NULL;
+ freelist->qlen = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu))));
+
+ /* allocate number of mpdu_blk memory */
+ os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu)));
+
+ pAd->mpdu_blk_pool.mem = mem;
+
+ if (mem == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n"));
+ return(FALSE);
+ }
+
+ /* build mpdu_blk free list */
+ for (i=0; i<num; i++)
+ {
+ /* get mpdu_blk */
+ mpdu_blk = (struct reordering_mpdu *) mem;
+ /* initial mpdu_blk */
+ NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
+ /* next mpdu_blk */
+ mem += sizeof(struct reordering_mpdu);
+ /* insert mpdu_blk into freelist */
+ ba_enqueue(freelist, mpdu_blk);
+ }
+
+ return(TRUE);
+}
+
+/* static int blk_count=0; sample take off, no use */
+
+static struct reordering_mpdu *ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd)
+{
+ struct reordering_mpdu *mpdu_blk;
+
+ NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
+ mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist);
+ if (mpdu_blk)
+ {
+/* blk_count++; */
+ /* reset mpdu_blk */
+ NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
+ }
+ NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
+ return mpdu_blk;
+}
+
+static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk)
+{
+ ASSERT(mpdu_blk);
+
+ NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
+/* blk_count--; */
+ ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk);
+ NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
+}
+
+
+static USHORT ba_indicate_reordering_mpdus_in_order(
+ IN PRTMP_ADAPTER pAd,
+ IN PBA_REC_ENTRY pBAEntry,
+ IN USHORT StartSeq)
+{
+ struct reordering_mpdu *mpdu_blk;
+ USHORT LastIndSeq = RESET_RCV_SEQ;
+
+ NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+
+ while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
+ {
+ /* find in-order frame */
+ if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ))
+ {
+ break;
+ }
+ /* dequeue in-order frame from reodering list */
+ mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
+ /* pass this frame up */
+ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
+ /* move to next sequence */
+ StartSeq = mpdu_blk->Sequence;
+ LastIndSeq = StartSeq;
+ /* free mpdu_blk */
+ ba_mpdu_blk_free(pAd, mpdu_blk);
+ }
+
+ NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+
+ /* update last indicated sequence */
+ return LastIndSeq;
+}
+
+static void ba_indicate_reordering_mpdus_le_seq(
+ IN PRTMP_ADAPTER pAd,
+ IN PBA_REC_ENTRY pBAEntry,
+ IN USHORT Sequence)
+{
+ struct reordering_mpdu *mpdu_blk;
+
+ NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+ while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
+ {
+ /* find in-order frame */
+ if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ))
+ {
+ /* dequeue in-order frame from reodering list */
+ mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
+ /* pass this frame up */
+ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
+ /* free mpdu_blk */
+ ba_mpdu_blk_free(pAd, mpdu_blk);
+ }
+ else
+ {
+ break;
+ }
+ }
+ NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+}
+
+
+static void ba_refresh_reordering_mpdus(
+ IN PRTMP_ADAPTER pAd,
+ PBA_REC_ENTRY pBAEntry)
+{
+ struct reordering_mpdu *mpdu_blk;
+
+ NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+
+ /* dequeue in-order frame from reodering list */
+ while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
+ {
+ /* pass this frame up */
+ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
+
+ pBAEntry->LastIndSeq = mpdu_blk->Sequence;
+ ba_mpdu_blk_free(pAd, mpdu_blk);
+
+ /* update last indicated sequence */
+ }
+ ASSERT(pBAEntry->list.qlen == 0);
+ pBAEntry->LastIndSeq = RESET_RCV_SEQ;
+ NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+}
+
+
+/* static */
+void ba_flush_reordering_timeout_mpdus(
+ IN PRTMP_ADAPTER pAd,
+ IN PBA_REC_ENTRY pBAEntry,
+ IN ULONG Now32)
+
+{
+ USHORT Sequence;
+
+ if ((pBAEntry == NULL) || (pBAEntry->list.qlen <= 0))
+ return;
+
+/* if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) &&*/
+/* (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) ||*/
+/* (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) &&*/
+/* (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8)))*/
+ if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6)))
+ &&(pBAEntry->list.qlen > 1)
+ )
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
+ (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT,
+ pBAEntry->LastIndSeq));
+ ba_refresh_reordering_mpdus(pAd, pBAEntry);
+ pBAEntry->LastIndSeqAtTimer = Now32;
+ }
+ else
+ if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
+ && (pBAEntry->list.qlen > 0)
+ )
+ {
+/*
+ DBGPRINT(RT_DEBUG_OFF, ("timeout[%d] (%lx-%lx = %d > %d): %x, ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
+ (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), REORDERING_PACKET_TIMEOUT,
+ pBAEntry->LastIndSeq));
+*/
+
+ /* force LastIndSeq to shift to LastIndSeq+1*/
+ Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ;
+ ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
+ pBAEntry->LastIndSeqAtTimer = Now32;
+ pBAEntry->LastIndSeq = Sequence;
+
+ /* indicate in-order mpdus*/
+ Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence);
+ if (Sequence != RESET_RCV_SEQ)
+ {
+ pBAEntry->LastIndSeq = Sequence;
+ }
+
+ DBGPRINT(RT_DEBUG_OFF, ("%x, flush one!\n", pBAEntry->LastIndSeq));
+
+ }
+}
+
+
+/*
+ * generate ADDBA request to
+ * set up BA agreement
+ */
+VOID BAOriSessionSetUp(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN UCHAR TID,
+ IN USHORT TimeOut,
+ IN ULONG DelayTime,
+ IN BOOLEAN isForced)
+
+{
+ /*MLME_ADDBA_REQ_STRUCT AddbaReq;*/
+ BA_ORI_ENTRY *pBAEntry = NULL;
+ USHORT Idx;
+ BOOLEAN Cancelled;
+
+ ASSERT(TID < NUM_OF_TID);
+ if (TID >= NUM_OF_TID)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Wrong TID %d!\n", TID));
+ return;
+ }
+
+ if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE))
+ return;
+
+ /* if this entry is limited to use legacy tx mode, it doesn't generate BA. */
+ if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
+ return;
+
+ if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE))
+ {
+ /* try again after 3 secs*/
+ DelayTime = 3000;
+/* DBGPRINT(RT_DEBUG_TRACE, ("DeCline BA from Peer\n"));*/
+/* return;*/
+ }
+
+
+ Idx = pEntry->BAOriWcidArray[TID];
+ if (Idx == 0)
+ {
+ /* allocate a BA session*/
+ pBAEntry = BATableAllocOriEntry(pAd, &Idx);
+ if (pBAEntry == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
+ return;
+ }
+ }
+ else
+ {
+ pBAEntry =&pAd->BATable.BAOriEntry[Idx];
+ }
+
+ if (pBAEntry->ORI_BA_Status >= Originator_WaitRes)
+ {
+ return;
+ }
+
+ pEntry->BAOriWcidArray[TID] = Idx;
+
+ /* Initialize BA session */
+ pBAEntry->ORI_BA_Status = Originator_WaitRes;
+ pBAEntry->Wcid = pEntry->Aid;
+ pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
+ pBAEntry->Sequence = BA_ORI_INIT_SEQ;
+ pBAEntry->Token = 1; /* (2008-01-21) Jan Lee recommends it - this token can't be 0*/
+ pBAEntry->TID = TID;
+ pBAEntry->TimeOutValue = TimeOut;
+ pBAEntry->pAdapter = pAd;
+
+ if (!(pEntry->TXBAbitmap & (1<<TID)))
+ {
+ RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE);
+ }
+ else
+ RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
+
+ /* set timer to send ADDBA request */
+ RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime);
+}
+
+VOID BAOriSessionAdd(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN PFRAME_ADDBA_RSP pFrame)
+{
+ BA_ORI_ENTRY *pBAEntry = NULL;
+ BOOLEAN Cancelled;
+ UCHAR TID;
+ USHORT Idx;
+ PUCHAR pOutBuffer2 = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen;
+ FRAME_BAR FrameBar;
+ UCHAR MaxPeerBufSize;
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR apidx;
+#endif /* CONFIG_AP_SUPPORT */
+
+ TID = pFrame->BaParm.TID;
+ Idx = pEntry->BAOriWcidArray[TID];
+ pBAEntry =&pAd->BATable.BAOriEntry[Idx];
+
+ MaxPeerBufSize = 0;
+
+ /* Start fill in parameters.*/
+ if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes))
+ {
+ MaxPeerBufSize = (UCHAR)pFrame->BaParm.BufSize;
+
+ if (MaxPeerBufSize > 0)
+ MaxPeerBufSize -= 1;
+ else
+ MaxPeerBufSize = 0;
+ pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, MaxPeerBufSize);
+ BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize);
+
+ pBAEntry->TimeOutValue = pFrame->TimeOutValue;
+ pBAEntry->ORI_BA_Status = Originator_Done;
+ pAd->BATable.numDoneOriginator ++;
+
+ /* reset sequence number */
+ pBAEntry->Sequence = BA_ORI_INIT_SEQ;
+ /* Set Bitmap flag.*/
+ pEntry->TXBAbitmap |= (1<<TID);
+ RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
+
+ pBAEntry->ORIBATimer.TimerValue = 0; /*pFrame->TimeOutValue;*/
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():TXBAbitmap=%x, BAWinSize=%d, TimeOut=%ld\n",
+ __FUNCTION__, pEntry->TXBAbitmap,
+ pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue));
+
+ /* SEND BAR */
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); /*Get an unused nonpaged memory*/
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n"));
+ return;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(&pAd->MacTab.Content[pBAEntry->Wcid]))
+ {
+ apidx = pAd->MacTab.Content[pBAEntry->Wcid].MatchAPCLITabIdx;
+ BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress);
+ }
+ else
+#endif /* APCLI_SUPPORT */
+#ifdef WDS_SUPPORT
+ if (IS_ENTRY_WDS(&pAd->MacTab.Content[pBAEntry->Wcid]))
+ {
+ apidx = pAd->MacTab.Content[pBAEntry->Wcid].MatchWDSTabIdx;
+ BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->ApCfg.MBSSID[MAIN_MBSSID].Bssid);
+ }
+ else
+#endif /* WDS_SUPPORT */
+ {
+ apidx = pAd->MacTab.Content[pBAEntry->Wcid].apidx;
+ BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function.*/
+ FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; /* make sure sequence not clear in DEL funciton.*/
+ FrameBar.BarControl.TID = pBAEntry->TID; /* make sure sequence not clear in DEL funciton.*/
+ MakeOutgoingFrame(pOutBuffer2, &FrameLen,
+ sizeof(FRAME_BAR), &FrameBar,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer2);
+
+ if (pBAEntry->ORIBATimer.TimerValue)
+ RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); /* in mSec */
+ }
+}
+
+BOOLEAN BARecSessionAdd(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN PFRAME_ADDBA_REQ pFrame)
+{
+ BA_REC_ENTRY *pBAEntry = NULL;
+ BOOLEAN Status = TRUE;
+ BOOLEAN Cancelled;
+ USHORT Idx;
+ UCHAR TID;
+ UCHAR BAWinSize;
+ /*UINT32 Value;*/
+ /*UINT offset;*/
+
+
+ ASSERT(pEntry);
+
+ /* find TID*/
+ TID = pFrame->BaParm.TID;
+
+ BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
+
+ /* Intel patch*/
+ if (BAWinSize == 0)
+ {
+ BAWinSize = 64;
+ }
+
+ /* get software BA rec array index, Idx*/
+ Idx = pEntry->BARecWcidArray[TID];
+
+
+ if (Idx == 0)
+ {
+ /* allocate new array entry for the new session*/
+ pBAEntry = BATableAllocRecEntry(pAd, &Idx);
+ }
+ else
+ {
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ /* flush all pending reordering mpdus*/
+ ba_refresh_reordering_mpdus(pAd, pBAEntry);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __FUNCTION__, pAd->BATable.numAsRecipient, Idx,
+ pFrame->BaParm.BufSize, BAWinSize));
+
+ /* Start fill in parameters.*/
+ if (pBAEntry != NULL)
+ {
+ ASSERT(pBAEntry->list.qlen == 0);
+
+ pBAEntry->REC_BA_Status = Recipient_HandleRes;
+ pBAEntry->BAWinSize = BAWinSize;
+ pBAEntry->Wcid = pEntry->Aid;
+ pBAEntry->TID = TID;
+ pBAEntry->TimeOutValue = pFrame->TimeOutValue;
+ pBAEntry->REC_BA_Status = Recipient_Accept;
+ /* initial sequence number */
+ pBAEntry->LastIndSeq = RESET_RCV_SEQ; /*pFrame->BaStartSeq.field.StartSeq;*/
+
+ DBGPRINT(RT_DEBUG_OFF, ("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq));
+
+ if (pEntry->RXBAbitmap & (1<<TID))
+ {
+ RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
+ }
+ else
+ {
+ RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE);
+ }
+
+
+ /* Set Bitmap flag.*/
+ pEntry->RXBAbitmap |= (1<<TID);
+ pEntry->BARecWcidArray[TID] = Idx;
+
+ pEntry->BADeclineBitmap &= ~(1<<TID);
+
+ /* Set BA session mask in WCID table.*/
+ RTMP_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID);
+
+ DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
+ pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID]));
+ }
+ else
+ {
+ Status = FALSE;
+ DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
+ PRINT_MAC(pEntry->Addr), TID));
+ }
+ return(Status);
+}
+
+
+BA_REC_ENTRY *BATableAllocRecEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT USHORT *Idx)
+{
+ int i;
+ BA_REC_ENTRY *pBAEntry = NULL;
+
+
+ NdisAcquireSpinLock(&pAd->BATabLock);
+
+ if (pAd->BATable.numAsRecipient >= (MAX_LEN_OF_BA_REC_TABLE - 1))
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n",
+ pAd->BATable.numAsRecipient, (MAX_LEN_OF_BA_REC_TABLE - 1)));
+ goto done;
+ }
+
+ /* reserve idx 0 to identify BAWcidArray[TID] as empty*/
+ for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++)
+ {
+ pBAEntry =&pAd->BATable.BARecEntry[i];
+ if ((pBAEntry->REC_BA_Status == Recipient_NONE))
+ {
+ /* get one */
+ pAd->BATable.numAsRecipient++;
+ pBAEntry->REC_BA_Status = Recipient_USED;
+ *Idx = i;
+ break;
+ }
+ }
+
+done:
+ NdisReleaseSpinLock(&pAd->BATabLock);
+ return pBAEntry;
+}
+
+BA_ORI_ENTRY *BATableAllocOriEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT USHORT *Idx)
+{
+ int i;
+ BA_ORI_ENTRY *pBAEntry = NULL;
+
+ NdisAcquireSpinLock(&pAd->BATabLock);
+
+ if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE - 1))
+ {
+ goto done;
+ }
+
+ /* reserve idx 0 to identify BAWcidArray[TID] as empty*/
+ for (i=1; i<MAX_LEN_OF_BA_ORI_TABLE; i++)
+ {
+ pBAEntry =&pAd->BATable.BAOriEntry[i];
+ if ((pBAEntry->ORI_BA_Status == Originator_NONE))
+ {
+ /* get one */
+ pAd->BATable.numAsOriginator++;
+ pBAEntry->ORI_BA_Status = Originator_USED;
+ pBAEntry->pAdapter = pAd;
+ *Idx = i;
+ break;
+ }
+ }
+
+done:
+ NdisReleaseSpinLock(&pAd->BATabLock);
+ return pBAEntry;
+}
+
+
+VOID BATableFreeOriEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Idx)
+{
+ BA_ORI_ENTRY *pBAEntry = NULL;
+ MAC_TABLE_ENTRY *pEntry;
+
+
+ if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
+ return;
+
+ pBAEntry =&pAd->BATable.BAOriEntry[Idx];
+
+ if (pBAEntry->ORI_BA_Status != Originator_NONE)
+ {
+ pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
+ pEntry->BAOriWcidArray[pBAEntry->TID] = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Wcid = %d, TID = %d\n", __FUNCTION__, pBAEntry->Wcid, pBAEntry->TID));
+
+
+ NdisAcquireSpinLock(&pAd->BATabLock);
+ if (pBAEntry->ORI_BA_Status == Originator_Done)
+ {
+ pAd->BATable.numDoneOriginator -= 1;
+ pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) ));
+ DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
+ /* Erase Bitmap flag.*/
+ }
+
+ ASSERT(pAd->BATable.numAsOriginator != 0);
+
+ pAd->BATable.numAsOriginator -= 1;
+
+ pBAEntry->ORI_BA_Status = Originator_NONE;
+ pBAEntry->Token = 0;
+ NdisReleaseSpinLock(&pAd->BATabLock);
+ }
+}
+
+
+VOID BATableFreeRecEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Idx)
+{
+ BA_REC_ENTRY *pBAEntry = NULL;
+ MAC_TABLE_ENTRY *pEntry;
+
+
+ if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
+ return;
+
+ pBAEntry =&pAd->BATable.BARecEntry[Idx];
+
+ if (pBAEntry->REC_BA_Status != Recipient_NONE)
+ {
+ pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
+ pEntry->BARecWcidArray[pBAEntry->TID] = 0;
+
+ NdisAcquireSpinLock(&pAd->BATabLock);
+
+ ASSERT(pAd->BATable.numAsRecipient != 0);
+
+ pAd->BATable.numAsRecipient -= 1;
+
+ pBAEntry->REC_BA_Status = Recipient_NONE;
+ NdisReleaseSpinLock(&pAd->BATabLock);
+ }
+}
+
+
+VOID BAOriSessionTearDown(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR TID,
+ IN BOOLEAN bPassive,
+ IN BOOLEAN bForceSend)
+{
+ ULONG Idx = 0;
+ BA_ORI_ENTRY *pBAEntry;
+ BOOLEAN Cancelled;
+
+ if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+ {
+ return;
+ }
+
+
+ /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).*/
+ Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID];
+ if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
+ {
+ if (bForceSend == TRUE)
+ {
+ /* force send specified TID DelBA*/
+ MLME_DELBA_REQ_STRUCT DelbaReq;
+ MLME_QUEUE_ELEM *Elem; /* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);*/
+ os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM));
+ if (Elem != NULL)
+ {
+ NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
+ NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
+
+ COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
+ DelbaReq.Wcid = Wcid;
+ DelbaReq.TID = TID;
+ DelbaReq.Initiator = ORIGINATOR;
+ Elem->MsgLen = sizeof(DelbaReq);
+ NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
+ MlmeDELBAAction(pAd, Elem);
+/* kfree(Elem);*/
+ os_free_mem(NULL, Elem);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s(bForceSend):alloc memory failed!\n", __FUNCTION__));
+ }
+ }
+
+ return;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID));
+
+ pBAEntry = &pAd->BATable.BAOriEntry[Idx];
+ DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status));
+
+ /* Prepare DelBA action frame and send to the peer.*/
+ if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done))
+ {
+ MLME_DELBA_REQ_STRUCT DelbaReq;
+ MLME_QUEUE_ELEM *Elem; /* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);*/
+ os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM));
+ if (Elem != NULL)
+ {
+ NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
+ NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
+
+ COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
+ DelbaReq.Wcid = Wcid;
+ DelbaReq.TID = pBAEntry->TID;
+ DelbaReq.Initiator = ORIGINATOR;
+ Elem->MsgLen = sizeof(DelbaReq);
+ NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
+ MlmeDELBAAction(pAd, Elem);
+/* kfree(Elem);*/
+ os_free_mem(NULL, Elem);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__));
+ return;
+ }
+ }
+ RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
+ BATableFreeOriEntry(pAd, Idx);
+
+ if (bPassive)
+ {
+ /*BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);*/
+ }
+}
+
+VOID BARecSessionTearDown(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR TID,
+ IN BOOLEAN bPassive)
+{
+ ULONG Idx = 0;
+ BA_REC_ENTRY *pBAEntry;
+
+ if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+ {
+ return;
+ }
+
+
+ /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).*/
+ Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+ if (Idx == 0)
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID));
+
+
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status));
+
+ /* Prepare DelBA action frame and send to the peer.*/
+ if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept))
+ {
+ MLME_DELBA_REQ_STRUCT DelbaReq;
+ BOOLEAN Cancelled;
+ /*ULONG offset; */
+ /*UINT32 VALUE;*/
+
+ RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
+
+
+ /* 1. Send DELBA Action Frame*/
+ if (bPassive == FALSE)
+ {
+ MLME_QUEUE_ELEM *Elem; /* = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);*/
+ os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM));
+ if (Elem != NULL)
+ {
+ NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
+ NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
+
+ COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
+ DelbaReq.Wcid = Wcid;
+ DelbaReq.TID = TID;
+ DelbaReq.Initiator = RECIPIENT;
+ Elem->MsgLen = sizeof(DelbaReq);
+ NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
+ MlmeDELBAAction(pAd, Elem);
+/* kfree(Elem);*/
+ os_free_mem(NULL, Elem);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__));
+ return;
+ }
+ }
+
+
+
+ /* 2. Free resource of BA session*/
+ /* flush all pending reordering mpdus */
+ ba_refresh_reordering_mpdus(pAd, pBAEntry);
+
+ NdisAcquireSpinLock(&pAd->BATabLock);
+
+ /* Erase Bitmap flag.*/
+ pBAEntry->LastIndSeq = RESET_RCV_SEQ;
+ pBAEntry->BAWinSize = 0;
+ /* Erase Bitmap flag at software mactable*/
+ pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID)));
+ pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0;
+
+ RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID);
+
+ NdisReleaseSpinLock(&pAd->BATabLock);
+
+ }
+
+ BATableFreeRecEntry(pAd, Idx);
+}
+
+VOID BASessionTearDownALL(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid)
+{
+ int i;
+
+ for (i=0; i<NUM_OF_TID; i++)
+ {
+ BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
+ BARecSessionTearDown(pAd, Wcid, i, FALSE);
+ }
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Retry sending ADDBA Reqest.
+
+ IRQL = DISPATCH_LEVEL
+
+ Parametrs:
+ p8023Header: if this is already 802.3 format, p8023Header is NULL
+
+ Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
+ FALSE , then continue indicaterx at this moment.
+ ==========================================================================
+ */
+VOID BAOriSessionSetupTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ BA_ORI_ENTRY *pBAEntry = (BA_ORI_ENTRY *)FunctionContext;
+ MAC_TABLE_ENTRY *pEntry;
+ PRTMP_ADAPTER pAd;
+
+ if (pBAEntry == NULL)
+ return;
+
+ pAd = pBAEntry->pAdapter;
+
+
+#ifdef RALINK_ATE
+ /* Nothing to do in ATE mode. */
+ if (ATE_ON(pAd))
+ return;
+#endif /* RALINK_ATE */
+
+ pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
+
+ if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY))
+ {
+ MLME_ADDBA_REQ_STRUCT AddbaReq;
+
+
+ NdisZeroMemory(&AddbaReq, sizeof(AddbaReq));
+ COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr);
+ AddbaReq.Wcid = (UCHAR)(pEntry->Aid);
+ AddbaReq.TID = pBAEntry->TID;
+ AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
+ AddbaReq.TimeOutValue = 0;
+ AddbaReq.Token = pBAEntry->Token;
+ MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq, 0);
+ RTMP_MLME_HANDLER(pAd);
+ DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token));
+
+ pBAEntry->Token++;
+ RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
+ }
+ else
+ {
+ BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ Retry sending ADDBA Reqest.
+
+ IRQL = DISPATCH_LEVEL
+
+ Parametrs:
+ p8023Header: if this is already 802.3 format, p8023Header is NULL
+
+ Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
+ FALSE , then continue indicaterx at this moment.
+ ==========================================================================
+ */
+VOID BARecSessionIdleTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+
+ BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext;
+ PRTMP_ADAPTER pAd;
+ ULONG Now32;
+
+ if (pBAEntry == NULL)
+ return;
+
+ if ((pBAEntry->REC_BA_Status == Recipient_Accept))
+ {
+ NdisGetSystemUpTime(&Now32);
+
+ if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT)))
+ {
+ pAd = pBAEntry->pAdapter;
+ /* flush all pending reordering mpdus */
+ ba_refresh_reordering_mpdus(pAd, pBAEntry);
+ DBGPRINT(RT_DEBUG_OFF, ("%ld: REC BA session Timeout\n", Now32));
+ }
+ }
+}
+
+
+VOID PeerAddBAReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+
+{
+ /* 7.4.4.1*/
+ /*ULONG Idx;*/
+ UCHAR Status = 1;
+ UCHAR pAddr[6];
+ FRAME_ADDBA_RSP ADDframe;
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ PFRAME_ADDBA_REQ pAddreqFrame = NULL;
+ /*UCHAR BufSize;*/
+ ULONG FrameLen;
+ PULONG ptemp;
+ PMAC_TABLE_ENTRY pMacEntry;
+#ifdef CONFIG_AP_SUPPORT
+ INT apidx;
+#endif /* CONFIG_AP_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid));
+
+ /*hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);*/
+
+ /*ADDBA Request from unknown peer, ignore this.*/
+ if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
+ return;
+
+ pMacEntry = &pAd->MacTab.Content[Elem->Wcid];
+ DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n"));
+ ptemp = (PULONG)Elem->Msg;
+ /*DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8)));*/
+
+ if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr))
+ {
+
+ if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry))
+ {
+ pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
+ DBGPRINT(RT_DEBUG_OFF, ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid));
+ if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame))
+ Status = 0;
+ else
+ Status = 38; /* more parameters have invalid values*/
+ }
+ else
+ {
+ Status = 37; /* the request has been declined.*/
+ }
+ }
+
+ if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[Elem->Wcid]))
+ ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
+
+ pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
+ /* 2. Always send back ADDBA Response */
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n"));
+ return;
+ }
+
+ NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP));
+ /* 2-1. Prepare ADDBA Response frame.*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Elem->Wcid]))
+ {
+ apidx = pAd->MacTab.Content[Elem->Wcid].MatchAPCLITabIdx;
+ ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pAddr);
+ }
+ else
+#endif /* APCLI_SUPPORT */
+#ifdef WDS_SUPPORT
+ if (IS_ENTRY_WDS(&pAd->MacTab.Content[Elem->Wcid]))
+ {
+ apidx = pAd->MacTab.Content[Elem->Wcid].MatchWDSTabIdx;
+ ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.MBSSID[MAIN_MBSSID].Bssid, pAddr);
+ }
+ else
+#endif /* WDS_SUPPORT */
+ {
+ apidx = pAd->MacTab.Content[Elem->Wcid].apidx;
+ ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ ADDframe.Category = CATEGORY_BA;
+ ADDframe.Action = ADDBA_RESP;
+ ADDframe.Token = pAddreqFrame->Token;
+ /* What is the Status code?? need to check.*/
+ ADDframe.StatusCode = Status;
+ ADDframe.BaParm.BAPolicy = IMMED_BA;
+ ADDframe.BaParm.AMSDUSupported = 0;
+ ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID;
+ ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
+ if (ADDframe.BaParm.BufSize == 0)
+ {
+ ADDframe.BaParm.BufSize = 64;
+ }
+ ADDframe.TimeOutValue = 0; /* pAddreqFrame->TimeOutValue; */
+
+#ifdef UNALIGNMENT_SUPPORT
+ {
+ BA_PARM tmpBaParm;
+
+ NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&ADDframe.BaParm), sizeof(BA_PARM));
+ *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm));
+ NdisMoveMemory((PUCHAR)(&ADDframe.BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM));
+ }
+#else
+ *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm));
+#endif /* UNALIGNMENT_SUPPORT */
+
+ ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
+ ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_ADDBA_RSP), &ADDframe,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID,
+ ADDframe.BaParm.BufSize));
+}
+
+
+VOID PeerAddBARspAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+
+{
+ /*UCHAR Idx, i;*/
+ /*PUCHAR pOutBuffer = NULL;*/
+ PFRAME_ADDBA_RSP pFrame = NULL;
+ /*PBA_ORI_ENTRY pBAEntry;*/
+
+ /*ADDBA Response from unknown peer, ignore this.*/
+ if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid));
+
+ /*hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);*/
+
+ if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen))
+ {
+ pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode));
+ switch (pFrame->StatusCode)
+ {
+ case 0:
+ /* I want a BAsession with this peer as an originator. */
+ BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame);
+ break;
+ default:
+ /* check status == USED ??? */
+ BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE);
+ break;
+ }
+ /* Rcv Decline StatusCode*/
+ if ((pFrame->StatusCode == 37)
+ )
+ {
+ pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID;
+ }
+ }
+}
+
+VOID PeerDelBAAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+
+{
+ /*UCHAR Idx;*/
+ /*PUCHAR pOutBuffer = NULL;*/
+ PFRAME_DELBA_REQ pDelFrame = NULL;
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__));
+ /*DELBA Request from unknown peer, ignore this.*/
+ if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen))
+ {
+ pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]);
+ if (pDelFrame->DelbaParm.Initiator == ORIGINATOR)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n"));
+ BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode));
+ /*hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);*/
+ BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE);
+ }
+ }
+}
+
+
+BOOLEAN CntlEnqueueForRecv(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Wcid,
+ IN ULONG MsgLen,
+ IN PFRAME_BA_REQ pMsg)
+{
+ PFRAME_BA_REQ pFrame = pMsg;
+ /*PRTMP_REORDERBUF pBuffer;*/
+ /*PRTMP_REORDERBUF pDmaBuf;*/
+ PBA_REC_ENTRY pBAEntry;
+ /*BOOLEAN Result;*/
+ ULONG Idx;
+ /*UCHAR NumRxPkt;*/
+ UCHAR TID;/*, i;*/
+
+ TID = (UCHAR)pFrame->BARControl.TID;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__, Wcid, TID));
+ /*hex_dump("BAR", (PCHAR) pFrame, MsgLen);*/
+ /* Do nothing if the driver is starting halt state.*/
+ /* This might happen when timer already been fired before cancel timer with mlmehalt*/
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return FALSE;
+
+ /* First check the size, it MUST not exceed the mlme queue size*/
+ if (MsgLen > MGMT_DMA_BUFFER_SIZE) /* 1600B */
+ {
+ DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
+ return FALSE;
+ }
+ else if (MsgLen != sizeof(FRAME_BA_REQ))
+ {
+ DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
+ return FALSE;
+ }
+ else if (MsgLen != sizeof(FRAME_BA_REQ))
+ {
+ DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
+ return FALSE;
+ }
+
+ if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8))
+ {
+ /* if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.*/
+ Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq ));
+
+ if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ))
+ {
+ /*DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq));*/
+ ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq);
+ pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1);
+ }
+ /*ba_refresh_reordering_mpdus(pAd, pBAEntry);*/
+ return TRUE;
+}
+
+/*
+Description : Send PSMP Action frame If PSMP mode switches.
+*/
+VOID SendPSMPAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR Psmp)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ FRAME_PSMP_ACTION Frame;
+ ULONG FrameLen;
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR apidx;
+#endif /* CONFIG_AP_SUPPORT */
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
+ return;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Wcid]))
+ {
+ apidx = pAd->MacTab.Content[Wcid].MatchAPCLITabIdx;
+ ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
+ }
+ else
+#endif /* APCLI_SUPPORT */
+#ifdef WDS_SUPPORT
+ if (IS_ENTRY_WDS(&pAd->MacTab.Content[Wcid]))
+ {
+ apidx = pAd->MacTab.Content[Wcid].MatchWDSTabIdx;
+ ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.MBSSID[MAIN_MBSSID].Bssid, pAd->MacTab.Content[Wcid].Addr);
+ }
+ else
+#endif /* WDS_SUPPORT */
+ {
+ apidx = pAd->MacTab.Content[Wcid].apidx;
+ ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ Frame.Category = CATEGORY_HT;
+ Frame.Action = SMPS_ACTION;
+ switch (Psmp)
+ {
+ case MMPS_ENABLE:
+ Frame.Psmp = 0;
+ break;
+ case MMPS_DYNAMIC:
+ Frame.Psmp = 3;
+ break;
+ case MMPS_STATIC:
+ Frame.Psmp = 1;
+ break;
+ }
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_PSMP_ACTION), &Frame,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp));
+}
+
+
+#define RADIO_MEASUREMENT_REQUEST_ACTION 0
+
+typedef struct GNU_PACKED _BEACON_REQUEST {
+ UCHAR RegulatoryClass;
+ UCHAR ChannelNumber;
+ USHORT RandomInterval;
+ USHORT MeasurementDuration;
+ UCHAR MeasurementMode;
+ UCHAR BSSID[MAC_ADDR_LEN];
+ UCHAR ReportingCondition;
+ UCHAR Threshold;
+ UCHAR SSIDIE[2]; /* 2 byte*/
+} BEACON_REQUEST;
+
+typedef struct GNU_PACKED _MEASUREMENT_REQ
+{
+ UCHAR ID;
+ UCHAR Length;
+ UCHAR Token;
+ UCHAR RequestMode;
+ UCHAR Type;
+} MEASUREMENT_REQ;
+
+#ifdef CONFIG_AP_SUPPORT
+VOID SendBeaconRequest(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ FRAME_RM_REQ_ACTION Frame;
+ ULONG FrameLen;
+ BEACON_REQUEST BeaconReq;
+ MEASUREMENT_REQ MeasureReg;
+ UCHAR apidx;
+
+ if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Wcid]))
+ return;
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("Radio - SendBeaconRequest() allocate memory failed \n"));
+ return;
+ }
+ apidx = pAd->MacTab.Content[Wcid].apidx;
+ ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
+
+ Frame.Category = CATEGORY_RM;
+ Frame.Action = RADIO_MEASUREMENT_REQUEST_ACTION;
+ Frame.Token = 1;
+ Frame.Repetition = 0; /* executed once*/
+
+ BeaconReq.RegulatoryClass = 32; /* ?????*/
+ BeaconReq.ChannelNumber = 255; /* all channels*/
+ BeaconReq.RandomInterval = 0;
+ BeaconReq.MeasurementDuration = 10; /* 10 TU*/
+ BeaconReq.MeasurementMode = 1; /* Active mode */
+ COPY_MAC_ADDR(BeaconReq.BSSID, BROADCAST_ADDR);
+ BeaconReq.ReportingCondition = 254; /* report not necesssary*/
+ BeaconReq.Threshold = 0; /* minimum RCPI*/
+ BeaconReq.SSIDIE[0] = 0;
+ BeaconReq.SSIDIE[1] = 0; /* wildcard SSID zero length */
+
+
+ MeasureReg.ID = IE_MEASUREMENT_REQUEST;
+ MeasureReg.Token = 0;
+ MeasureReg.RequestMode = 0;
+ MeasureReg.Type = 5; /* Beacon Request*/
+ MeasureReg.Length = sizeof(MEASUREMENT_REQ)+sizeof(BEACON_REQUEST)-2;
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_RM_REQ_ACTION), &Frame,
+ sizeof(MEASUREMENT_REQ), &MeasureReg,
+ sizeof(BEACON_REQUEST), &BeaconReq,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_TRACE,("Radio - SendBeaconRequest\n"));
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+
+void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ PNDIS_PACKET pRxPkt;
+ UCHAR Header802_3[LENGTH_802_3];
+
+/*
+ 1. get 802.3 Header
+ 2. remove LLC
+ a. pointer pRxBlk->pData to payload
+ b. modify pRxBlk->DataSize
+*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ ASSERT(pRxBlk->pRxPacket);
+
+ pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
+
+ RTMP_OS_PKT_INIT(pRxBlk->pRxPacket,
+ get_netdev_from_bssid(pAd, FromWhichBSSID),
+ pRxBlk->pData, pRxBlk->DataSize);
+
+
+ /* copy 802.3 header, if necessary*/
+ if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* maybe insert VLAN tag to the received packet */
+ UCHAR VLAN_Size = 0;
+ UCHAR *data_p;
+ USHORT VLAN_VID = 0, VLAN_Priority = 0;
+
+ /* VLAN related */
+ MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+
+#ifdef WDS_VLAN_SUPPORT
+ if (VLAN_VID == 0) /* maybe WDS packet */
+ WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+#endif /* WDS_VLAN_SUPPORT */
+
+ if (VLAN_VID != 0)
+ VLAN_Size = LENGTH_802_1Q;
+
+ data_p = OS_PKT_HEAD_BUF_EXTEND(pRxPkt, LENGTH_802_3+VLAN_Size);
+ RT_VLAN_8023_HEADER_COPY(pAd, VLAN_VID, VLAN_Priority,
+ Header802_3, LENGTH_802_3,
+ data_p, FromWhichBSSID, TPID);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+}
+
+
+#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
+ do \
+ { \
+ if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
+ { \
+ Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
+ } \
+ else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
+ { \
+ Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
+ } \
+ else \
+ { \
+ Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
+ } \
+ } while (0);
+
+#define INDICATE_LEGACY_OR_AMSDU_HDR_TRNS(_pAd, _pRxBlk, _fromWhichBSSID) \
+ do \
+ { \
+ if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
+ { \
+ Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
+ } \
+ else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
+ { \
+ Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
+ } \
+ else \
+ { \
+ Indicate_Legacy_Packet_Hdr_Trns(_pAd, _pRxBlk, _fromWhichBSSID); \
+ } \
+ } while (0);
+
+static VOID ba_enqueue_reordering_packet(
+ IN PRTMP_ADAPTER pAd,
+ IN PBA_REC_ENTRY pBAEntry,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ struct reordering_mpdu *mpdu_blk;
+ UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence;
+
+ mpdu_blk = ba_mpdu_blk_alloc(pAd);
+ if ((mpdu_blk != NULL) &&
+ (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP)))
+ {
+ /* Write RxD buffer address & allocated buffer length */
+ NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+
+ mpdu_blk->Sequence = Sequence;
+ mpdu_blk->OpMode = pRxBlk->OpMode;
+
+ mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
+
+ convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID);
+
+ STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
+
+
+ /* it is necessary for reordering packet to record
+ which BSS it come from
+ */
+ RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
+
+ mpdu_blk->pPacket = pRxBlk->pRxPacket;
+
+ if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE)
+ {
+ /* had been already within reordering list don't indicate */
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS);
+ ba_mpdu_blk_free(pAd, mpdu_blk);
+ }
+
+ ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
+ NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n",
+ pBAEntry->list.qlen));
+ /*
+ * flush all pending reordering mpdus
+ * and receving mpdu to upper layer
+ * make tcp/ip to take care reordering mechanism
+ */
+ /*ba_refresh_reordering_mpdus(pAd, pBAEntry);*/
+ ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
+
+ pBAEntry->LastIndSeq = Sequence;
+ INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+ }
+}
+
+
+#ifdef HDR_TRANS_SUPPORT
+static VOID ba_enqueue_reordering_packet_hdr_trns(
+ IN PRTMP_ADAPTER pAd,
+ IN PBA_REC_ENTRY pBAEntry,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ struct reordering_mpdu *mpdu_blk;
+ UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence;
+
+ mpdu_blk = ba_mpdu_blk_alloc(pAd);
+ if ((mpdu_blk != NULL) &&
+ (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP)))
+ {
+
+ /* Write RxD buffer address & allocated buffer length */
+ NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+
+ mpdu_blk->Sequence = Sequence;
+ mpdu_blk->OpMode = pRxBlk->OpMode;
+
+ mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
+
+ convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID);
+
+
+ RTMP_OS_PKT_INIT(pRxBlk->pRxPacket,
+ get_netdev_from_bssid(pAd, FromWhichBSSID),
+ pRxBlk->pTransData, pRxBlk->TransDataSize);
+
+
+ STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
+
+
+ /* it is necessary for reordering packet to record
+ which BSS it come from
+ */
+ //RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
+
+
+ mpdu_blk->pPacket = pRxBlk->pRxPacket;
+
+ if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE)
+ {
+ /* had been already within reordering list don't indicate */
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS);
+ ba_mpdu_blk_free(pAd, mpdu_blk);
+ }
+
+ ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
+ NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n",
+ pBAEntry->list.qlen));
+
+ /*
+ * flush all pending reordering mpdus
+ * and receving mpdu to upper layer
+ * make tcp/ip to take care reordering mechanism
+ */
+ /*ba_refresh_reordering_mpdus(pAd, pBAEntry);*/
+ ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
+
+ pBAEntry->LastIndSeq = Sequence;
+ INDICATE_LEGACY_OR_AMSDU_HDR_TRNS(pAd, pRxBlk, FromWhichBSSID);
+ }
+}
+#endif /* HDR_TRANS_SUPPORT */
+
+
+/*
+ ==========================================================================
+ Description:
+ Indicate this packet to upper layer or put it into reordering buffer
+
+ Parametrs:
+ pRxBlk : carry necessary packet info 802.11 format
+ FromWhichBSSID : the packet received from which BSS
+
+ Return :
+ none
+
+ Note :
+ the packet queued into reordering buffer need to cover to 802.3 format
+ or pre_AMSDU format
+ ==========================================================================
+ */
+
+VOID Indicate_AMPDU_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ USHORT Idx;
+ PBA_REC_ENTRY pBAEntry = NULL;
+ UINT16 Sequence = pRxBlk->pHeader->Sequence;
+ ULONG Now32;
+ UCHAR Wcid = pRxBlk->pRxWI->RxWIWirelessCliID;
+ UCHAR TID = pRxBlk->pRxWI->RxWITID;
+
+
+ if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN))
+ {
+ static int err_size;
+
+ err_size++;
+ if (err_size > 20) {
+ DBGPRINT(RT_DEBUG_TRACE, ("AMPDU DataSize = %d\n", pRxBlk->DataSize));
+ hex_dump("802.11 Header", (UCHAR *)pRxBlk->pHeader, 24);
+ hex_dump("Payload", pRxBlk->pData, 64);
+ err_size = 0;
+ }
+
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+
+
+ if (Wcid < MAX_LEN_OF_MAC_TABLE)
+ {
+ Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+ if (Idx == 0)
+ {
+ /* Rec BA Session had been torn down */
+ INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+ return;
+ }
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ }
+ else
+ {
+ /* impossible !!!*/
+ ASSERT(0);
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ ASSERT(pBAEntry);
+
+ /* update last rx time*/
+ NdisGetSystemUpTime(&Now32);
+
+ pBAEntry->rcvSeq = Sequence;
+
+
+ ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
+ pBAEntry->LastIndSeqAtTimer = Now32;
+
+
+ /* Reset Last Indicate Sequence*/
+ /* */
+ if (pBAEntry->LastIndSeq == RESET_RCV_SEQ)
+ {
+ ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL));
+
+ /* reset rcv sequence of BA session */
+ pBAEntry->LastIndSeq = Sequence;
+ pBAEntry->LastIndSeqAtTimer = Now32;
+ INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+ return;
+ }
+
+
+ /* I. Check if in order.*/
+ if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
+ {
+ USHORT LastIndSeq;
+
+ pBAEntry->LastIndSeq = Sequence;
+ INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+ LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
+ if (LastIndSeq != RESET_RCV_SEQ)
+ {
+ pBAEntry->LastIndSeq = LastIndSeq;
+ }
+ pBAEntry->LastIndSeqAtTimer = Now32;
+ }
+
+ /* II. Drop Duplicated Packet*/
+ else if (Sequence == pBAEntry->LastIndSeq)
+ {
+
+ /* drop and release packet*/
+ pBAEntry->nDropPacket++;
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ }
+
+ /* III. Drop Old Received Packet*/
+ else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
+ {
+
+ /* drop and release packet*/
+ pBAEntry->nDropPacket++;
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ }
+
+ /* IV. Receive Sequence within Window Size*/
+ else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ))
+ {
+ ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
+ }
+
+ /* V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer*/
+ else
+ {
+ LONG WinStartSeq, TmpSeq;
+
+
+ TmpSeq = Sequence - (pBAEntry->BAWinSize) -1;
+ if (TmpSeq < 0)
+ {
+ TmpSeq = (MAXSEQ+1) + TmpSeq;
+ }
+ WinStartSeq = (TmpSeq+1) & MAXSEQ;
+ ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
+ pBAEntry->LastIndSeq = WinStartSeq; /*TmpSeq; */
+
+ pBAEntry->LastIndSeqAtTimer = Now32;
+
+ ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
+
+ TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
+ if (TmpSeq != RESET_RCV_SEQ)
+ {
+ pBAEntry->LastIndSeq = TmpSeq;
+ }
+ }
+}
+
+
+#ifdef HDR_TRANS_SUPPORT
+VOID Indicate_AMPDU_Packet_Hdr_Trns(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ USHORT Idx;
+ PBA_REC_ENTRY pBAEntry = NULL;
+ UINT16 Sequence = pRxBlk->pHeader->Sequence;
+ ULONG Now32;
+ UCHAR Wcid = pRxBlk->pRxWI->RxWIWirelessCliID;
+ UCHAR TID = pRxBlk->pRxWI->RxWITID;
+
+
+ if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->TransDataSize > 1514))
+ {
+ static int err_size;
+
+ err_size++;
+ if (err_size > 20) {
+ DBGPRINT(RT_DEBUG_TRACE, ("AMPDU DataSize = %d\n", pRxBlk->DataSize));
+ hex_dump("802.11 Header", (UCHAR *)pRxBlk->pHeader, 24);
+ hex_dump("Payload", pRxBlk->pData, 64);
+ err_size = 0;
+ }
+
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+
+
+ if (Wcid < MAX_LEN_OF_MAC_TABLE)
+ {
+ Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+ if (Idx == 0)
+ {
+ /* Rec BA Session had been torn down */
+ INDICATE_LEGACY_OR_AMSDU_HDR_TRNS(pAd, pRxBlk, FromWhichBSSID);
+ return;
+ }
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ }
+ else
+ {
+ /* impossible !!!*/
+ ASSERT(0);
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ ASSERT(pBAEntry);
+
+ /* update last rx time*/
+ NdisGetSystemUpTime(&Now32);
+
+ pBAEntry->rcvSeq = Sequence;
+
+
+ ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
+ pBAEntry->LastIndSeqAtTimer = Now32;
+
+
+ /* Reset Last Indicate Sequence*/
+ /* */
+ if (pBAEntry->LastIndSeq == RESET_RCV_SEQ)
+ {
+ ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL));
+
+ /* reset rcv sequence of BA session */
+ pBAEntry->LastIndSeq = Sequence;
+ pBAEntry->LastIndSeqAtTimer = Now32;
+ INDICATE_LEGACY_OR_AMSDU_HDR_TRNS(pAd, pRxBlk, FromWhichBSSID);
+ return;
+ }
+
+ /* I. Check if in order.*/
+ if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
+ {
+ USHORT LastIndSeq;
+
+ pBAEntry->LastIndSeq = Sequence;
+ INDICATE_LEGACY_OR_AMSDU_HDR_TRNS(pAd, pRxBlk, FromWhichBSSID);
+ LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
+ if (LastIndSeq != RESET_RCV_SEQ)
+ {
+ pBAEntry->LastIndSeq = LastIndSeq;
+ }
+ pBAEntry->LastIndSeqAtTimer = Now32;
+ }
+
+ /* II. Drop Duplicated Packet*/
+ else if (Sequence == pBAEntry->LastIndSeq)
+ {
+
+
+ /* drop and release packet*/
+ pBAEntry->nDropPacket++;
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ }
+
+ /* III. Drop Old Received Packet*/
+ else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
+ {
+
+
+ /* drop and release packet*/
+ pBAEntry->nDropPacket++;
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ }
+
+ /* IV. Receive Sequence within Window Size*/
+ else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ))
+ {
+ ba_enqueue_reordering_packet_hdr_trns(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
+ }
+
+ /* V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer*/
+ else
+ {
+ LONG WinStartSeq, TmpSeq;
+
+
+ printk("999999999\n");
+
+ TmpSeq = Sequence - (pBAEntry->BAWinSize) -1;
+ if (TmpSeq < 0)
+ {
+ TmpSeq = (MAXSEQ+1) + TmpSeq;
+ }
+ WinStartSeq = (TmpSeq+1) & MAXSEQ;
+ ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
+ pBAEntry->LastIndSeq = WinStartSeq; /*TmpSeq; */
+
+ pBAEntry->LastIndSeqAtTimer = Now32;
+
+ ba_enqueue_reordering_packet_hdr_trns(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
+
+ TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
+ if (TmpSeq != RESET_RCV_SEQ)
+ {
+ pBAEntry->LastIndSeq = TmpSeq;
+ }
+ }
+}
+#endif /* HDR_TRANS_SUPPORT */
+
+
+VOID BaReOrderingBufferMaintain(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG Now32;
+ UCHAR Wcid;
+ USHORT Idx;
+ UCHAR TID;
+ PBA_REC_ENTRY pBAEntry = NULL;
+ PMAC_TABLE_ENTRY pEntry = NULL;
+
+ /* update last rx time*/
+ NdisGetSystemUpTime(&Now32);
+
+ for (Wcid = 1; Wcid < MAX_LEN_OF_MAC_TABLE; Wcid++)
+ {
+ pEntry = &pAd->MacTab.Content[Wcid];
+ if (IS_ENTRY_NONE(pEntry))
+ continue;
+
+ for (TID= 0; TID < NUM_OF_TID; TID++)
+ {
+ Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
+ }
+ }
+}
+#endif /* DOT11_N_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/client_wds.c b/cleopatre/devkit/mt7601udrv/common/client_wds.c
new file mode 100644
index 0000000000..b5edbfc31a
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/client_wds.c
@@ -0,0 +1,197 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ client_wds.c
+
+ Abstract:
+*/
+
+
+#ifdef CLIENT_WDS
+
+#include "rt_config.h"
+
+VOID CliWds_ProxyTabInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ INT idx;
+ ULONG i;
+
+ NdisAllocateSpinLock(pAd, &pAd->ApCfg.CliWdsTabLock);
+
+/* pAd->ApCfg.pCliWdsEntryPool = kmalloc(sizeof(CLIWDS_PROXY_ENTRY) * CLIWDS_POOL_SIZE, GFP_ATOMIC);*/
+ os_alloc_mem(pAd, (UCHAR **)&(pAd->ApCfg.pCliWdsEntryPool), sizeof(CLIWDS_PROXY_ENTRY) * CLIWDS_POOL_SIZE);
+ if (pAd->ApCfg.pCliWdsEntryPool)
+ {
+ NdisZeroMemory(pAd->ApCfg.pCliWdsEntryPool, sizeof(CLIWDS_PROXY_ENTRY) * CLIWDS_POOL_SIZE);
+ initList(&pAd->ApCfg.CliWdsEntryFreeList);
+ for (i = 0; i < CLIWDS_POOL_SIZE; i++)
+ insertTailList(&pAd->ApCfg.CliWdsEntryFreeList, (PLIST_ENTRY)(pAd->ApCfg.pCliWdsEntryPool + (ULONG)i));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pCliWdsEntryPool", __FUNCTION__));
+ }
+
+ for (idx = 0; idx < CLIWDS_HASH_TAB_SIZE; idx++)
+ initList(&pAd->ApCfg.CliWdsProxyTab[idx]);
+
+ return;
+}
+
+
+VOID CliWds_ProxyTabDestory(
+ IN PRTMP_ADAPTER pAd)
+{
+ INT idx;
+ PCLIWDS_PROXY_ENTRY pCliWdsEntry;
+
+ NdisFreeSpinLock(&pAd->ApCfg.CliWdsTabLock);
+
+ for (idx = 0; idx < CLIWDS_HASH_TAB_SIZE; idx++)
+ {
+ pCliWdsEntry =
+ (PCLIWDS_PROXY_ENTRY)pAd->ApCfg.CliWdsProxyTab[idx].pHead;
+ while(pCliWdsEntry)
+ {
+ PCLIWDS_PROXY_ENTRY pCliWdsEntryNext = pCliWdsEntry->pNext;
+ CliWdsEntyFree(pAd, pCliWdsEntry);
+ pCliWdsEntry = pCliWdsEntryNext;
+ }
+ }
+
+ if (pAd->ApCfg.pCliWdsEntryPool)
+/* kfree(pAd->ApCfg.pCliWdsEntryPool);*/
+ os_free_mem(NULL, pAd->ApCfg.pCliWdsEntryPool);
+ pAd->ApCfg.pCliWdsEntryPool = NULL;
+
+ return;
+}
+
+
+PCLIWDS_PROXY_ENTRY CliWdsEntyAlloc(
+ IN PRTMP_ADAPTER pAd)
+{
+ PCLIWDS_PROXY_ENTRY pCliWdsEntry;
+
+ RTMP_SEM_LOCK(&pAd->ApCfg.CliWdsTabLock);
+
+ pCliWdsEntry = (PCLIWDS_PROXY_ENTRY)removeHeadList(&pAd->ApCfg.CliWdsEntryFreeList);
+
+ RTMP_SEM_UNLOCK(&pAd->ApCfg.CliWdsTabLock);
+
+ return pCliWdsEntry;
+}
+
+
+VOID CliWdsEntyFree(
+ IN PRTMP_ADAPTER pAd,
+ IN PCLIWDS_PROXY_ENTRY pCliWdsEntry)
+{
+ RTMP_SEM_LOCK(&pAd->ApCfg.CliWdsTabLock);
+
+ insertTailList(&pAd->ApCfg.CliWdsEntryFreeList, (PLIST_ENTRY)pCliWdsEntry);
+
+ RTMP_SEM_UNLOCK(&pAd->ApCfg.CliWdsTabLock);
+
+ return;
+}
+
+
+PUCHAR CliWds_ProxyLookup(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pMac)
+{
+ UINT8 HashId = (*(pMac + 5) & (CLIWDS_HASH_TAB_SIZE - 1));
+ PCLIWDS_PROXY_ENTRY pCliWdsEntry;
+
+ pCliWdsEntry =
+ (PCLIWDS_PROXY_ENTRY)pAd->ApCfg.CliWdsProxyTab[HashId].pHead;
+ while (pCliWdsEntry)
+ {
+ if (MAC_ADDR_EQUAL(pMac, pCliWdsEntry->Addr))
+ {
+ ULONG Now;
+ NdisGetSystemUpTime(&Now);
+
+ pCliWdsEntry->LastRefTime = Now;
+ if (VALID_WCID(pCliWdsEntry->Aid))
+ return pAd->MacTab.Content[pCliWdsEntry->Aid].Addr;
+ else
+ return NULL;
+ }
+ pCliWdsEntry = pCliWdsEntry->pNext;
+ }
+ return NULL;
+}
+
+
+VOID CliWds_ProxyTabUpdate(
+ IN PRTMP_ADAPTER pAd,
+ IN SHORT Aid,
+ IN PUCHAR pMac)
+{
+ UINT8 HashId = (*(pMac + 5) & (CLIWDS_HASH_TAB_SIZE - 1));
+ PCLIWDS_PROXY_ENTRY pCliWdsEntry;
+
+ if (CliWds_ProxyLookup(pAd, pMac) != NULL)
+ return;
+
+ pCliWdsEntry = CliWdsEntyAlloc(pAd);
+ if (pCliWdsEntry)
+ {
+ ULONG Now;
+ NdisGetSystemUpTime(&Now);
+
+ pCliWdsEntry->Aid = Aid;
+ COPY_MAC_ADDR(&pCliWdsEntry->Addr, pMac);
+ pCliWdsEntry->LastRefTime = Now;
+ pCliWdsEntry->pNext = NULL;
+ insertTailList(&pAd->ApCfg.CliWdsProxyTab[HashId], (PLIST_ENTRY)pCliWdsEntry);
+ }
+ return;
+}
+
+
+VOID CliWds_ProxyTabMaintain(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG idx;
+ PCLIWDS_PROXY_ENTRY pCliWdsEntry;
+ ULONG Now;
+
+ NdisGetSystemUpTime(&Now);
+ for (idx = 0; idx < CLIWDS_HASH_TAB_SIZE; idx++)
+ {
+ pCliWdsEntry = (PCLIWDS_PROXY_ENTRY)(pAd->ApCfg.CliWdsProxyTab[idx].pHead);
+ while(pCliWdsEntry)
+ {
+ PCLIWDS_PROXY_ENTRY pCliWdsEntryNext = pCliWdsEntry->pNext;
+ if (RTMP_TIME_AFTER(Now, pCliWdsEntry->LastRefTime + (CLI_WDS_ENTRY_AGEOUT * OS_HZ / 1000)))
+ {
+ delEntryList(&pAd->ApCfg.CliWdsProxyTab[idx], (PLIST_ENTRY)pCliWdsEntry);
+ CliWdsEntyFree(pAd, pCliWdsEntry);
+ }
+ pCliWdsEntry = pCliWdsEntryNext;
+ }
+ }
+ return;
+}
+
+#endif /* CLIENT_WDS */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_aes.c b/cleopatre/devkit/mt7601udrv/common/cmm_aes.c
new file mode 100644
index 0000000000..b254c63ce6
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_aes.c
@@ -0,0 +1,1142 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ cmm_aes.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Wu 02-25-02 Initial
+*/
+
+#include "rt_config.h"
+
+
+
+/*****************************/
+/******** SBOX Table *********/
+/*****************************/
+
+UCHAR SboxTable[256] =
+{
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+};
+
+VOID xor_32(
+ IN PUCHAR a,
+ IN PUCHAR b,
+ OUT PUCHAR out)
+{
+ INT i;
+
+ for (i=0;i<4; i++)
+ {
+ out[i] = a[i] ^ b[i];
+ }
+}
+
+VOID xor_128(
+ IN PUCHAR a,
+ IN PUCHAR b,
+ OUT PUCHAR out)
+{
+ INT i;
+
+ for (i=0;i<16; i++)
+ {
+ out[i] = a[i] ^ b[i];
+ }
+}
+
+UCHAR RTMPCkipSbox(
+ IN UCHAR a)
+{
+ return SboxTable[(int)a];
+}
+
+VOID next_key(
+ IN PUCHAR key,
+ IN INT round)
+{
+ UCHAR rcon;
+ UCHAR sbox_key[4];
+ UCHAR rcon_table[12] =
+ {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+ 0x1b, 0x36, 0x36, 0x36
+ };
+
+ sbox_key[0] = RTMPCkipSbox(key[13]);
+ sbox_key[1] = RTMPCkipSbox(key[14]);
+ sbox_key[2] = RTMPCkipSbox(key[15]);
+ sbox_key[3] = RTMPCkipSbox(key[12]);
+
+ rcon = rcon_table[round];
+
+ xor_32(&key[0], sbox_key, &key[0]);
+ key[0] = key[0] ^ rcon;
+
+ xor_32(&key[4], &key[0], &key[4]);
+ xor_32(&key[8], &key[4], &key[8]);
+ xor_32(&key[12], &key[8], &key[12]);
+}
+
+VOID byte_sub(
+ IN PUCHAR in,
+ OUT PUCHAR out)
+{
+ INT i;
+
+ for (i=0; i< 16; i++)
+ {
+ out[i] = RTMPCkipSbox(in[i]);
+ }
+}
+
+/************************************/
+/* bitwise_xor() */
+/* A 128 bit, bitwise exclusive or */
+/************************************/
+
+void bitwise_xor(unsigned char *ina, unsigned char *inb, unsigned char *out)
+{
+ int i;
+ for (i=0; i<16; i++)
+ {
+ out[i] = ina[i] ^ inb[i];
+ }
+}
+
+VOID shift_row(
+ IN PUCHAR in,
+ OUT PUCHAR out)
+{
+ out[0] = in[0];
+ out[1] = in[5];
+ out[2] = in[10];
+ out[3] = in[15];
+ out[4] = in[4];
+ out[5] = in[9];
+ out[6] = in[14];
+ out[7] = in[3];
+ out[8] = in[8];
+ out[9] = in[13];
+ out[10] = in[2];
+ out[11] = in[7];
+ out[12] = in[12];
+ out[13] = in[1];
+ out[14] = in[6];
+ out[15] = in[11];
+}
+
+VOID mix_column(
+ IN PUCHAR in,
+ OUT PUCHAR out)
+{
+ INT i;
+ UCHAR add1b[4];
+ UCHAR add1bf7[4];
+ UCHAR rotl[4];
+ UCHAR swap_halfs[4];
+ UCHAR andf7[4];
+ UCHAR rotr[4];
+ UCHAR temp[4];
+ UCHAR tempb[4];
+
+ for (i=0 ; i<4; i++)
+ {
+ if ((in[i] & 0x80)== 0x80)
+ add1b[i] = 0x1b;
+ else
+ add1b[i] = 0x00;
+ }
+
+ swap_halfs[0] = in[2]; /* Swap halfs */
+ swap_halfs[1] = in[3];
+ swap_halfs[2] = in[0];
+ swap_halfs[3] = in[1];
+
+ rotl[0] = in[3]; /* Rotate left 8 bits */
+ rotl[1] = in[0];
+ rotl[2] = in[1];
+ rotl[3] = in[2];
+
+ andf7[0] = in[0] & 0x7f;
+ andf7[1] = in[1] & 0x7f;
+ andf7[2] = in[2] & 0x7f;
+ andf7[3] = in[3] & 0x7f;
+
+ for (i = 3; i>0; i--) /* logical shift left 1 bit */
+ {
+ andf7[i] = andf7[i] << 1;
+ if ((andf7[i-1] & 0x80) == 0x80)
+ {
+ andf7[i] = (andf7[i] | 0x01);
+ }
+ }
+ andf7[0] = andf7[0] << 1;
+ andf7[0] = andf7[0] & 0xfe;
+
+ xor_32(add1b, andf7, add1bf7);
+
+ xor_32(in, add1bf7, rotr);
+
+ temp[0] = rotr[0]; /* Rotate right 8 bits */
+ rotr[0] = rotr[1];
+ rotr[1] = rotr[2];
+ rotr[2] = rotr[3];
+ rotr[3] = temp[0];
+
+ xor_32(add1bf7, rotr, temp);
+ xor_32(swap_halfs, rotl,tempb);
+ xor_32(temp, tempb, out);
+}
+
+
+/************************************************/
+/* construct_mic_header1() */
+/* Builds the first MIC header block from */
+/* header fields. */
+/************************************************/
+
+void construct_mic_header1(
+ unsigned char *mic_header1,
+ int header_length,
+ unsigned char *mpdu)
+{
+ mic_header1[0] = (unsigned char)((header_length - 2) / 256);
+ mic_header1[1] = (unsigned char)((header_length - 2) % 256);
+ mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */
+ mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */
+ mic_header1[4] = mpdu[4]; /* A1 */
+ mic_header1[5] = mpdu[5];
+ mic_header1[6] = mpdu[6];
+ mic_header1[7] = mpdu[7];
+ mic_header1[8] = mpdu[8];
+ mic_header1[9] = mpdu[9];
+ mic_header1[10] = mpdu[10]; /* A2 */
+ mic_header1[11] = mpdu[11];
+ mic_header1[12] = mpdu[12];
+ mic_header1[13] = mpdu[13];
+ mic_header1[14] = mpdu[14];
+ mic_header1[15] = mpdu[15];
+}
+
+/************************************************/
+/* construct_mic_header2() */
+/* Builds the last MIC header block from */
+/* header fields. */
+/************************************************/
+
+void construct_mic_header2(
+ unsigned char *mic_header2,
+ unsigned char *mpdu,
+ int a4_exists,
+ int qc_exists)
+{
+ int i;
+
+ for (i = 0; i<16; i++) mic_header2[i]=0x00;
+
+ mic_header2[0] = mpdu[16]; /* A3 */
+ mic_header2[1] = mpdu[17];
+ mic_header2[2] = mpdu[18];
+ mic_header2[3] = mpdu[19];
+ mic_header2[4] = mpdu[20];
+ mic_header2[5] = mpdu[21];
+
+ /* In Sequence Control field, mute sequence numer bits (12-bit) */
+ mic_header2[6] = mpdu[22] & 0x0f; /* SC */
+ mic_header2[7] = 0x00; /* mpdu[23]; */
+
+ if ((!qc_exists) & a4_exists)
+ {
+ for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */
+
+ }
+
+ if (qc_exists && (!a4_exists))
+ {
+ mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
+ mic_header2[9] = mpdu[25] & 0x00;
+ }
+
+ if (qc_exists && a4_exists)
+ {
+ for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */
+
+ mic_header2[14] = mpdu[30] & 0x0f;
+ mic_header2[15] = mpdu[31] & 0x00;
+ }
+}
+
+
+/************************************************/
+/* construct_mic_iv() */
+/* Builds the MIC IV from header fields and PN */
+/************************************************/
+
+void construct_mic_iv(
+ unsigned char *mic_iv,
+ int qc_exists,
+ int a4_exists,
+ unsigned char *mpdu,
+ unsigned int payload_length,
+ unsigned char *pn_vector)
+{
+ int i;
+
+ mic_iv[0] = 0x59;
+ if (qc_exists && a4_exists)
+ mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */
+ if (qc_exists && !a4_exists)
+ mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */
+ if (!qc_exists)
+ mic_iv[1] = 0x00;
+ for (i = 2; i < 8; i++)
+ mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */
+#ifdef CONSISTENT_PN_ORDER
+ for (i = 8; i < 14; i++)
+ mic_iv[i] = pn_vector[i - 8]; /* mic_iv[8:13] = PN[0:5] */
+#else
+ for (i = 8; i < 14; i++)
+ mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */
+#endif
+ i = (payload_length / 256);
+ i = (payload_length % 256);
+ mic_iv[14] = (unsigned char) (payload_length / 256);
+ mic_iv[15] = (unsigned char) (payload_length % 256);
+
+}
+
+/****************************************/
+/* aes128k128d() */
+/* Performs a 128 bit AES encrypt with */
+/* 128 bit data. */
+/****************************************/
+void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphertext)
+{
+ int round;
+ int i;
+ unsigned char intermediatea[16];
+ unsigned char intermediateb[16];
+ unsigned char round_key[16];
+
+ for(i=0; i<16; i++) round_key[i] = key[i];
+
+ for (round = 0; round < 11; round++)
+ {
+ if (round == 0)
+ {
+ xor_128(round_key, data, ciphertext);
+ next_key(round_key, round);
+ }
+ else if (round == 10)
+ {
+ byte_sub(ciphertext, intermediatea);
+ shift_row(intermediatea, intermediateb);
+ xor_128(intermediateb, round_key, ciphertext);
+ }
+ else /* 1 - 9 */
+ {
+ byte_sub(ciphertext, intermediatea);
+ shift_row(intermediatea, intermediateb);
+ mix_column(&intermediateb[0], &intermediatea[0]);
+ mix_column(&intermediateb[4], &intermediatea[4]);
+ mix_column(&intermediateb[8], &intermediatea[8]);
+ mix_column(&intermediateb[12], &intermediatea[12]);
+ xor_128(intermediatea, round_key, ciphertext);
+ next_key(round_key, round);
+ }
+ }
+
+}
+
+void construct_ctr_preload(
+ unsigned char *ctr_preload,
+ int a4_exists,
+ int qc_exists,
+ unsigned char *mpdu,
+ unsigned char *pn_vector,
+ int c)
+{
+
+ int i = 0;
+ for (i=0; i<16; i++) ctr_preload[i] = 0x00;
+ i = 0;
+
+ ctr_preload[0] = 0x01; /* flag */
+ if (qc_exists && a4_exists) ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */
+ if (qc_exists && !a4_exists) ctr_preload[1] = mpdu[24] & 0x0f;
+
+ for (i = 2; i < 8; i++)
+ ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
+#ifdef CONSISTENT_PN_ORDER
+ for (i = 8; i < 14; i++)
+ ctr_preload[i] = pn_vector[i - 8]; /* ctr_preload[8:13] = PN[0:5] */
+#else
+ for (i = 8; i < 14; i++)
+ ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */
+#endif
+ ctr_preload[14] = (unsigned char) (c / 256); /* Ctr */
+ ctr_preload[15] = (unsigned char) (c % 256);
+
+}
+
+BOOLEAN RTMPSoftDecryptAES(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN ULONG DataByteCnt,
+ IN PCIPHER_KEY pWpaKey)
+{
+ UINT HeaderLen;
+ UCHAR PN[6];
+ UINT payload_len;
+ UINT num_blocks;
+ UINT payload_remainder;
+ USHORT fc;
+ UCHAR fc0;
+ UCHAR fc1;
+ UINT frame_type;
+ UINT frame_subtype;
+ UINT from_ds;
+ UINT to_ds;
+ INT a4_exists;
+ INT qc_exists;
+ UCHAR aes_out[16];
+ int payload_index;
+ UINT i;
+ UCHAR ctr_preload[16];
+ UCHAR chain_buffer[16];
+ UCHAR padded_buffer[16];
+ UCHAR mic_iv[16];
+ UCHAR mic_header1[16];
+ UCHAR mic_header2[16];
+ UCHAR MIC[8];
+ UCHAR TrailMIC[8];
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE);
+#endif
+
+ fc0 = *pData;
+ fc1 = *(pData + 1);
+
+ fc = *((PUSHORT)pData);
+
+ frame_type = ((fc0 >> 2) & 0x03);
+ frame_subtype = ((fc0 >> 4) & 0x0f);
+
+ from_ds = (fc1 & 0x2) >> 1;
+ to_ds = (fc1 & 0x1);
+
+ a4_exists = (from_ds & to_ds);
+ qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */
+ (frame_subtype == 0x09) || /* Likely to change. */
+ (frame_subtype == 0x0a) ||
+ (frame_subtype == 0x0b)
+ );
+
+ HeaderLen = 24;
+
+ if (a4_exists)
+ HeaderLen += 6;
+
+ if (qc_exists)
+ HeaderLen += 2;
+
+ if (pWpaKey->KeyLen == 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptAES failed!(the Length can not be 0)\n"));
+ return FALSE;
+ }
+
+ PN[0] = *(pData+ HeaderLen);
+ PN[1] = *(pData+ HeaderLen + 1);
+ PN[2] = *(pData+ HeaderLen + 4);
+ PN[3] = *(pData+ HeaderLen + 5);
+ PN[4] = *(pData+ HeaderLen + 6);
+ PN[5] = *(pData+ HeaderLen + 7);
+
+ payload_len = DataByteCnt - HeaderLen - 8 - 8; /* 8 bytes for CCMP header , 8 bytes for MIC*/
+ payload_remainder = (payload_len) % 16;
+ num_blocks = (payload_len) / 16;
+
+
+
+ /* Find start of payload*/
+ payload_index = HeaderLen + 8; /*IV+EIV*/
+
+ for (i=0; i< num_blocks; i++)
+ {
+ construct_ctr_preload(ctr_preload,
+ a4_exists,
+ qc_exists,
+ pData,
+ PN,
+ i+1 );
+
+ aes128k128d(pWpaKey->Key, ctr_preload, aes_out);
+
+ bitwise_xor(aes_out, pData + payload_index, chain_buffer);
+ NdisMoveMemory(pData + payload_index - 8, chain_buffer, 16);
+ payload_index += 16;
+ }
+
+
+ /* If there is a short final block, then pad it*/
+ /* encrypt it and copy the unpadded part back */
+
+ if (payload_remainder > 0)
+ {
+ construct_ctr_preload(ctr_preload,
+ a4_exists,
+ qc_exists,
+ pData,
+ PN,
+ num_blocks + 1);
+
+ NdisZeroMemory(padded_buffer, 16);
+ NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder);
+
+ aes128k128d(pWpaKey->Key, ctr_preload, aes_out);
+
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ NdisMoveMemory(pData + payload_index - 8, chain_buffer, payload_remainder);
+ payload_index += payload_remainder;
+ }
+
+
+ /* Descrypt the MIC*/
+ construct_ctr_preload(ctr_preload,
+ a4_exists,
+ qc_exists,
+ pData,
+ PN,
+ 0);
+ NdisZeroMemory(padded_buffer, 16);
+ NdisMoveMemory(padded_buffer, pData + payload_index, 8);
+
+ aes128k128d(pWpaKey->Key, ctr_preload, aes_out);
+
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+
+ NdisMoveMemory(TrailMIC, chain_buffer, 8);
+
+
+
+ /* Calculate MIC*/
+
+
+ /*Force the protected frame bit on*/
+ *(pData + 1) = *(pData + 1) | 0x40;
+
+ /* Find start of payload*/
+ /* Because the CCMP header has been removed*/
+ payload_index = HeaderLen;
+
+ construct_mic_iv(
+ mic_iv,
+ qc_exists,
+ a4_exists,
+ pData,
+ payload_len,
+ PN);
+
+ construct_mic_header1(
+ mic_header1,
+ HeaderLen,
+ pData);
+
+ construct_mic_header2(
+ mic_header2,
+ pData,
+ a4_exists,
+ qc_exists);
+
+ aes128k128d(pWpaKey->Key, mic_iv, aes_out);
+ bitwise_xor(aes_out, mic_header1, chain_buffer);
+ aes128k128d(pWpaKey->Key, chain_buffer, aes_out);
+ bitwise_xor(aes_out, mic_header2, chain_buffer);
+ aes128k128d(pWpaKey->Key, chain_buffer, aes_out);
+
+ /* iterate through each 16 byte payload block */
+ for (i = 0; i < num_blocks; i++)
+ {
+ bitwise_xor(aes_out, pData + payload_index, chain_buffer);
+ payload_index += 16;
+ aes128k128d(pWpaKey->Key, chain_buffer, aes_out);
+ }
+
+ /* Add on the final payload block if it needs padding */
+ if (payload_remainder > 0)
+ {
+ NdisZeroMemory(padded_buffer, 16);
+ NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder);
+
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ aes128k128d(pWpaKey->Key, chain_buffer, aes_out);
+ }
+
+ /* aes_out contains padded mic, discard most significant*/
+ /* 8 bytes to generate 64 bit MIC*/
+ for (i = 0 ; i < 8; i++) MIC[i] = aes_out[i];
+
+ if (!NdisEqualMemory(MIC, TrailMIC, 8))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptAES, MIC Error !\n")); /* MIC error. */
+ return FALSE;
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE);
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Construct AAD of CCMP.
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+ It's described in IEEE Std 802.11-2007.
+ The AAD is constructed from the MPDU header.
+
+ ========================================================================
+*/
+VOID RTMPConstructCCMPAAD(
+ IN PUCHAR pHdr,
+ IN BOOLEAN isDataFrame,
+ IN UINT8 a4_exists,
+ IN UINT8 qc_exists,
+ OUT UCHAR *aad_hdr,
+ OUT UINT *aad_len)
+{
+ UINT len = 0;
+
+ /* Frame control -
+ Subtype bits (bits 4 5 6) in a Data MPDU masked to 0
+ Retry bit (bit 11) masked to 0
+ PwrMgt bit (bit 12) masked to 0
+ MoreData bit (bit 13) masked to 0
+ Protected Frame bit (bit 14) always set to 1 */
+ if (isDataFrame)
+ aad_hdr[0] = (*pHdr) & 0x8f;
+ else
+ aad_hdr[0] = (*pHdr);
+ aad_hdr[1] = (*(pHdr + 1)) & 0xc7;
+ aad_hdr[1] = aad_hdr[1] | 0x40;
+ len = 2;
+
+ /* Append Addr 1, 2 & 3 */
+ NdisMoveMemory(&aad_hdr[len], pHdr + 4, 3 * MAC_ADDR_LEN);
+ len += (3 * MAC_ADDR_LEN);
+
+ /* SC -
+ MPDU Sequence Control field, with the Sequence Number
+ subfield (bits 4-15 of the Sequence Control field)
+ masked to 0. The Fragment Number subfield is not modified. */
+ aad_hdr[len] = (*(pHdr + 22)) & 0x0f;
+ aad_hdr[len + 1] = 0x00;
+ len += 2;
+
+
+ /* Append the Addr4 field if present. */
+ if (a4_exists)
+ {
+ NdisMoveMemory(&aad_hdr[len], pHdr + 24, MAC_ADDR_LEN);
+ len += MAC_ADDR_LEN;
+ }
+
+ /* QC -
+ QoS Control field, if present, a 2-octet field that includes
+ the MSDU priority. The QC TID field is used in the
+ construction of the AAD and the remaining QC fields are
+ set to 0 for the AAD calculation (bits 4 to 15 are set to 0). */
+ if (qc_exists & a4_exists)
+ {
+ aad_hdr[len] = (*(pHdr + 30)) & 0x0f; /* Qos_TC */
+ aad_hdr[len + 1] = 0x00;
+ len += 2;
+ }
+ else if (qc_exists & !a4_exists)
+ {
+ aad_hdr[len] = (*(pHdr + 24)) & 0x0f; /* Qos_TC */
+ aad_hdr[len + 1] = 0x00;
+ len += 2;
+ }
+
+ *aad_len = len;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Construct NONCE header of CCMP.
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPConstructCCMPNonce(
+ IN PUCHAR pHdr,
+ IN UINT8 a4_exists,
+ IN UINT8 qc_exists,
+ IN BOOLEAN isMgmtFrame,
+ IN UCHAR *pn,
+ OUT UCHAR *nonce_hdr,
+ OUT UINT *nonce_hdr_len)
+{
+ UINT n_offset = 0;
+ INT i;
+
+ /* Decide the Priority Octet
+ The Priority sub-field of the Nonce Flags field shall
+ be set to the fixed value 0 when there is no QC field
+ present in the MPDU header. When the QC field is present,
+ bits 0 to 3 of the Priority field shall be set to the
+ value of the QC TID (bits 0 to 3 of the QC field).*/
+ if (qc_exists && a4_exists)
+ nonce_hdr[0] = (*(pHdr + 30)) & 0x0f;
+ if (qc_exists && !a4_exists)
+ nonce_hdr[0] = (*(pHdr + 24)) & 0x0f;
+
+ n_offset += 1;
+
+ /* Fill in MPDU Address A2 field */
+ NdisMoveMemory(&nonce_hdr[n_offset], pHdr + 10, MAC_ADDR_LEN);
+ n_offset += MAC_ADDR_LEN;
+
+ /* Fill in the PN. The PN field occupies octets 7¡V12.
+ The octets of PN shall be ordered so that PN0 is at octet index 12
+ and PN5 is at octet index 7. */
+ for (i = 0; i < 6; i++)
+ nonce_hdr[n_offset + i] = pn[5 - i];
+ n_offset += LEN_PN;
+
+ *nonce_hdr_len = n_offset;
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Construct CCMP header.
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+ It's a 8-octets header.
+
+ ========================================================================
+*/
+VOID RTMPConstructCCMPHdr(
+ IN UINT8 key_idx,
+ IN UCHAR *pn,
+ OUT UCHAR *ccmp_hdr)
+{
+ NdisZeroMemory(ccmp_hdr, LEN_CCMP_HDR);
+
+ ccmp_hdr[0] = pn[0];
+ ccmp_hdr[1] = pn[1];
+ ccmp_hdr[3] = (key_idx <<6) | 0x20;
+ ccmp_hdr[4] = pn[2];
+ ccmp_hdr[5] = pn[3];
+ ccmp_hdr[6] = pn[4];
+ ccmp_hdr[7] = pn[5];
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+BOOLEAN RTMPSoftEncryptCCMP(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pHdr,
+ IN PUCHAR pIV,
+ IN PUCHAR pKey,
+ INOUT PUCHAR pData,
+ IN UINT32 DataLen)
+{
+ UINT8 frame_type, frame_subtype;
+ UINT8 from_ds, to_ds;
+ UINT8 a4_exists, qc_exists;
+ UINT8 aad_hdr[30];
+ UINT aad_len = 0;
+ UINT8 nonce_hdr[13];
+ UINT32 nonce_hdr_len = 0;
+ UINT32 out_len = DataLen + 8;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pHdr, DIR_READ, FALSE);
+#endif
+
+ /* Initial variable */
+ NdisZeroMemory(aad_hdr, 30);
+ NdisZeroMemory(nonce_hdr, 13);
+
+ /* Indicate type and subtype of Frame Control field */
+ frame_type = (((*pHdr) >> 2) & 0x03);
+ frame_subtype = (((*pHdr) >> 4) & 0x0f);
+
+ /* Indicate the fromDS and ToDS */
+ from_ds = ((*(pHdr + 1)) & 0x2) >> 1;
+ to_ds = ((*(pHdr + 1)) & 0x1);
+
+ /* decide if the Address 4 exist or QoS exist */
+ a4_exists = (from_ds & to_ds);
+ qc_exists = 0;
+ if (frame_type == BTYPE_DATA)
+ {
+ qc_exists = ((frame_subtype == SUBTYPE_QDATA) ||
+ (frame_subtype == SUBTYPE_QDATA_CFACK) ||
+ (frame_subtype == SUBTYPE_QDATA_CFPOLL) ||
+ (frame_subtype == SUBTYPE_QDATA_CFACK_CFPOLL));
+ }
+
+ /* Construct AAD header */
+ RTMPConstructCCMPAAD(pHdr,
+ (frame_type == BTYPE_DATA),
+ a4_exists,
+ qc_exists,
+ aad_hdr,
+ &aad_len);
+
+ /* Construct NONCE header */
+ RTMPConstructCCMPNonce(pHdr,
+ a4_exists,
+ qc_exists,
+ (frame_type == BTYPE_MGMT),
+ pIV,
+ nonce_hdr,
+ &nonce_hdr_len);
+
+ /* CCM originator processing -
+ Use the temporal key, AAD, nonce, and MPDU data to
+ form the cipher text and MIC. */
+ if (AES_CCM_Encrypt(pData, DataLen,
+ pKey, 16,
+ nonce_hdr, nonce_hdr_len,
+ aad_hdr, aad_len, LEN_CCMP_MIC,
+ pData, &out_len))
+ return FALSE;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pHdr, DIR_READ, FALSE);
+#endif
+
+ return TRUE;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Decrypt data with CCMP.
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+BOOLEAN RTMPSoftDecryptCCMP(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pHdr,
+ IN PCIPHER_KEY pKey,
+ INOUT PUCHAR pData,
+ INOUT UINT16 *DataLen)
+{
+ UINT8 frame_type, frame_subtype;
+ UINT8 from_ds, to_ds;
+ UINT8 a4_exists, qc_exists;
+ UINT8 aad_hdr[30];
+ UINT aad_len = 0;
+ UINT8 pn[LEN_PN];
+ PUCHAR cipherData_ptr;
+ UINT32 cipherData_len;
+ UINT8 nonce_hdr[13];
+ UINT32 nonce_hdr_len = 0;
+ UINT32 out_len = *DataLen;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pHdr, DIR_READ, FALSE);
+#endif
+
+ /* Check the key is valid */
+ if (pKey->KeyLen == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The key is not available !\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ /* Initial variable */
+ NdisZeroMemory(aad_hdr, 30);
+ NdisZeroMemory(nonce_hdr, 13);
+
+ /* Indicate type and subtype of Frame Control field */
+ frame_type = (((*pHdr) >> 2) & 0x03);
+ frame_subtype = (((*pHdr) >> 4) & 0x0f);
+
+ /* Indicate the fromDS and ToDS */
+ from_ds = ((*(pHdr + 1)) & 0x2) >> 1;
+ to_ds = ((*(pHdr + 1)) & 0x1);
+
+ /* decide if the Address 4 exist or QoS exist */
+ a4_exists = (from_ds & to_ds);
+ qc_exists = 0;
+ if (frame_type == BTYPE_DATA)
+ {
+ qc_exists = ((frame_subtype == SUBTYPE_QDATA) ||
+ (frame_subtype == SUBTYPE_QDATA_CFACK) ||
+ (frame_subtype == SUBTYPE_QDATA_CFPOLL) ||
+ (frame_subtype == SUBTYPE_QDATA_CFACK_CFPOLL));
+ }
+
+ /* Extract PN and from CCMP header */
+ pn[0] = pData[0];
+ pn[1] = pData[1];
+ pn[2] = pData[4];
+ pn[3] = pData[5];
+ pn[4] = pData[6];
+ pn[5] = pData[7];
+
+ /* skip ccmp header */
+ cipherData_ptr = pData + LEN_CCMP_HDR;
+ cipherData_len = *DataLen - LEN_CCMP_HDR;
+
+ /* Construct AAD header */
+ RTMPConstructCCMPAAD(pHdr,
+ (frame_type == BTYPE_DATA),
+ a4_exists,
+ qc_exists,
+ aad_hdr,
+ &aad_len);
+
+ /* Construct NONCE header */
+ RTMPConstructCCMPNonce(pHdr,
+ a4_exists,
+ qc_exists,
+ (frame_type == BTYPE_MGMT),
+ pn,
+ nonce_hdr,
+ &nonce_hdr_len);
+
+ /* CCM recipient processing -
+ uses the temporal key, AAD, nonce, MIC,
+ and MPDU cipher text data */
+ if (AES_CCM_Decrypt(cipherData_ptr, cipherData_len,
+ pKey->Key, 16,
+ nonce_hdr, nonce_hdr_len,
+ aad_hdr, aad_len, LEN_CCMP_MIC,
+ pData, &out_len))
+ return FALSE;
+
+ *DataLen = out_len;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pHdr, DIR_READ, FALSE);
+#endif
+
+ return TRUE;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ CCMP test vector
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID CCMP_test_vector(
+ IN PRTMP_ADAPTER pAd,
+ IN INT input)
+{
+ UINT8 Key_ID = 0;
+ /*UINT8 A1[6] = {0x0f, 0xd2, 0xe1, 0x28, 0xa5, 0x7c};*/
+ /*UINT8 A2[6] = {0x50, 0x30, 0xf1, 0x84, 0x44, 0x08};*/
+ /*UINT8 A3[6] = {0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba};*/
+ UINT8 TK[16] = {0xc9, 0x7c, 0x1f, 0x67, 0xce, 0x37, 0x11, 0x85,
+ 0x51, 0x4a, 0x8a, 0x19, 0xf2, 0xbd, 0xd5, 0x2f};
+ UINT8 PN[6] = {0x0C, 0xE7, 0x76, 0x97, 0x03, 0xB5};
+ UINT8 HDR[24]= {0x08, 0x48, 0xc3, 0x2c, 0x0f, 0xd2, 0xe1, 0x28,
+ 0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08,
+ 0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x80, 0x33};
+ UINT8 AAD[22] = {0x08, 0x40, 0x0f, 0xd2, 0xe1, 0x28, 0xa5, 0x7c,
+ 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xab, 0xae,
+ 0xa5, 0xb8, 0xfc, 0xba, 0x00, 0x00};
+ UINT8 CCMP_HDR[8] = {0x0c, 0xe7, 0x00, 0x20, 0x76, 0x97, 0x03, 0xb5};
+ UINT8 CCM_NONCE[13] = {0x00, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xb5,
+ 0x03, 0x97, 0x76, 0xe7, 0x0c};
+ UINT8 P_TEXT_DATA[20] = {0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae,
+ 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb,
+ 0x7e, 0x78, 0xa0, 0x50};
+ UINT8 C_TEXT_DATA[28] = {0xf3, 0xd0, 0xa2, 0xfe, 0x9a, 0x3d, 0xbf, 0x23,
+ 0x42, 0xa6, 0x43, 0xe4, 0x32, 0x46, 0xe8, 0x0c,
+ 0x3c, 0x04, 0xd0, 0x19, 0x78, 0x45, 0xce, 0x0b,
+ 0x16, 0xf9, 0x76, 0x23};
+ UINT8 res_buf[100];
+ UINT res_len = 0;
+
+ printk("== CCMP test vector == \n");
+
+ /* Check AAD */
+ NdisZeroMemory(res_buf, 100);
+ res_len = 0;
+ RTMPConstructCCMPAAD(HDR, TRUE, 0, 0, res_buf, &res_len);
+ if (res_len == 22 && NdisEqualMemory(res_buf, AAD, res_len))
+ printk("Construct AAD is OK!!!\n");
+ else
+ {
+ printk("\n!!!Construct AAD is FAILURE!!!\n\n");
+ hex_dump("Calculate AAD", res_buf, res_len);
+ }
+ /* Check NONCE */
+ NdisZeroMemory(res_buf, 100);
+ res_len = 0;
+ RTMPConstructCCMPNonce(HDR, 0, 0, FALSE, PN, res_buf, &res_len);
+ if (res_len == 13 && NdisEqualMemory(res_buf, CCM_NONCE, res_len))
+ printk("Construct NONCE is OK!!!\n");
+ else
+ {
+ printk("\n!!!Construct NONCE is FAILURE!!!\n\n");
+ hex_dump("Calculate NONCE", res_buf, res_len);
+ }
+ /* Check CCMP-Header */
+ NdisZeroMemory(res_buf, 100);
+ res_len = 0;
+ RTMPConstructCCMPHdr(Key_ID, PN, res_buf);
+ if (NdisEqualMemory(res_buf, CCMP_HDR, 8))
+ printk("Construct CCMP_HDR is OK!!!\n");
+ else
+ {
+ printk("\n!!!Construct CCMP_HDR is FAILURE!!!\n\n");
+ hex_dump("Calculate CCMP_HDR", res_buf, 8);
+ }
+
+ /* Encrypt action */
+ NdisZeroMemory(res_buf, 100);
+ NdisMoveMemory(res_buf, P_TEXT_DATA, sizeof(P_TEXT_DATA));
+ res_len = sizeof(C_TEXT_DATA);
+ if (AES_CCM_Encrypt(res_buf, sizeof(P_TEXT_DATA),
+ TK, sizeof(TK),
+ CCM_NONCE, sizeof(CCM_NONCE),
+ AAD, sizeof(AAD), 8,
+ res_buf, &res_len) == 0)
+ {
+ if (res_len == sizeof(C_TEXT_DATA) &&
+ NdisEqualMemory(res_buf, C_TEXT_DATA, res_len))
+ printk("CCM_Encrypt is OK!!!\n");
+ else
+ {
+ printk("\n!!!CCM_Encrypt is FAILURE!!!\n\n");
+ hex_dump("CCM_Encrypt", res_buf, res_len);
+ }
+ }
+
+ /* Decrypt action */
+ NdisZeroMemory(res_buf, 100);
+ NdisMoveMemory(res_buf, C_TEXT_DATA, sizeof(C_TEXT_DATA));
+ res_len = sizeof(P_TEXT_DATA);
+ if (AES_CCM_Decrypt(res_buf, sizeof(C_TEXT_DATA), TK, 16,
+ CCM_NONCE, sizeof(CCM_NONCE),
+ AAD, sizeof(AAD), 8,
+ res_buf, &res_len) == 0)
+ {
+ if (res_len == sizeof(P_TEXT_DATA) &&
+ NdisEqualMemory(res_buf, P_TEXT_DATA, res_len))
+ printk("CCM_Decrypt is OK!!!\n");
+ else
+ {
+ printk("\n!!!CCM_Decrypt is FAILURE!!!\n\n");
+ hex_dump("CCM_Decrypt", res_buf, res_len);
+ }
+ }
+
+ printk("== CCMP test vector == \n");
+
+ }
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_asic.c b/cleopatre/devkit/mt7601udrv/common/cmm_asic.c
new file mode 100644
index 0000000000..03ff71a9ad
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_asic.c
@@ -0,0 +1,2699 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ cmm_asic.c
+
+ Abstract:
+ Functions used to communicate with ASIC
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+*/
+
+#include "rt_config.h"
+
+
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Set MAC register value according operation mode.
+ OperationMode AND bNonGFExist are for MM and GF Proteciton.
+ If MM or GF mask is not set, those passing argument doesn't not take effect.
+
+ Operation mode meaning:
+ = 0 : Pure HT, no preotection.
+ = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
+ = 0x10: No Transmission in 40M is protected.
+ = 0x11: Transmission in both 40M and 20M shall be protected
+ if (bNonGFExist)
+ we should choose not to use GF. But still set correct ASIC registers.
+ ========================================================================
+*/
+VOID AsicUpdateProtect(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT OperationMode,
+ IN UCHAR SetMask,
+ IN BOOLEAN bDisableBGProtect,
+ IN BOOLEAN bNonGFExist)
+{
+ PROT_CFG_STRUC ProtCfg, ProtCfg4;
+ UINT32 Protect[6];
+ USHORT offset;
+ UCHAR i;
+ UINT32 MacReg = 0;
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ return;
+#endif /* RALINK_ATE */
+
+#ifdef DOT11_N_SUPPORT
+ if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
+ return;
+
+ if (pAd->BATable.numDoneOriginator)
+ {
+ /* enable the RTS/CTS to avoid channel collision*/
+ SetMask |= ALLN_SETPROTECT;
+ OperationMode = 8;
+ }
+#endif /* DOT11_N_SUPPORT */
+
+ /* Config ASIC RTS threshold register*/
+ RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
+ MacReg &= 0xFF0000FF;
+ /* If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096*/
+ if ((
+#ifdef DOT11_N_SUPPORT
+ (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
+#endif /* DOT11_N_SUPPORT */
+ (pAd->CommonCfg.bAggregationCapable == TRUE))
+ && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
+ {
+ MacReg |= (0x1000 << 8);
+ }
+ else
+ {
+ MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
+ }
+
+ RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
+
+ /* Initial common protection settings*/
+ RTMPZeroMemory(Protect, sizeof(Protect));
+ ProtCfg4.word = 0;
+ ProtCfg.word = 0;
+ ProtCfg.field.TxopAllowGF40 = 1;
+ ProtCfg.field.TxopAllowGF20 = 1;
+ ProtCfg.field.TxopAllowMM40 = 1;
+ ProtCfg.field.TxopAllowMM20 = 1;
+ ProtCfg.field.TxopAllowOfdm = 1;
+ ProtCfg.field.TxopAllowCck = 1;
+ ProtCfg.field.RTSThEn = 1;
+ ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+
+ /* update PHY mode and rate*/
+ if (pAd->OpMode == OPMODE_AP)
+ {
+ /* update PHY mode and rate*/
+ if (pAd->CommonCfg.Channel > 14)
+ ProtCfg.field.ProtectRate = 0x4000;
+ ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
+ }
+ else if (pAd->OpMode == OPMODE_STA)
+ {
+ // Decide Protect Rate for Legacy packet
+ if (pAd->CommonCfg.Channel > 14)
+ {
+ ProtCfg.field.ProtectRate = 0x4000; // OFDM 6Mbps
+ }
+ else
+ {
+ ProtCfg.field.ProtectRate = 0x0000; // CCK 1Mbps
+ if (pAd->CommonCfg.MinTxRate > RATE_11)
+ ProtCfg.field.ProtectRate |= 0x4000; // OFDM 6Mbps
+ }
+ }
+
+ /* Handle legacy(B/G) protection*/
+ if (bDisableBGProtect)
+ {
+ /*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;*/
+ ProtCfg.field.ProtectCtrl = 0;
+ Protect[0] = ProtCfg.word;
+ Protect[1] = ProtCfg.word;
+ pAd->FlgCtsEnabled = 0; /* CTS-self is not used */
+ }
+ else
+ {
+ /*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;*/
+ ProtCfg.field.ProtectCtrl = 0; /* CCK do not need to be protected*/
+ Protect[0] = ProtCfg.word;
+ ProtCfg.field.ProtectCtrl = ASIC_CTS; /* OFDM needs using CCK to protect*/
+ Protect[1] = ProtCfg.word;
+ pAd->FlgCtsEnabled = 1; /* CTS-self is used */
+ }
+
+#ifdef DOT11_N_SUPPORT
+ /* Decide HT frame protection.*/
+ if ((SetMask & ALLN_SETPROTECT) != 0)
+ {
+ switch(OperationMode)
+ {
+ case 0x0:
+ /* NO PROTECT */
+ /* 1.All STAs in the BSS are 20/40 MHz HT*/
+ /* 2. in ai 20/40MHz BSS*/
+ /* 3. all STAs are 20MHz in a 20MHz BSS*/
+ /* Pure HT. no protection.*/
+
+ /* MM20_PROT_CFG*/
+ /* Reserved (31:27)*/
+ /* PROT_TXOP(25:20) -- 010111*/
+ /* PROT_NAV(19:18) -- 01 (Short NAV protection)*/
+ /* PROT_CTRL(17:16) -- 00 (None)*/
+ /* PROT_RATE(15:0) -- 0x4004 (OFDM 24M)*/
+ Protect[2] = 0x01744004;
+
+ /* MM40_PROT_CFG*/
+ /* Reserved (31:27)*/
+ /* PROT_TXOP(25:20) -- 111111*/
+ /* PROT_NAV(19:18) -- 01 (Short NAV protection)*/
+ /* PROT_CTRL(17:16) -- 00 (None) */
+ /* PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)*/
+ Protect[3] = 0x03f44084;
+
+ /* CF20_PROT_CFG*/
+ /* Reserved (31:27)*/
+ /* PROT_TXOP(25:20) -- 010111*/
+ /* PROT_NAV(19:18) -- 01 (Short NAV protection)*/
+ /* PROT_CTRL(17:16) -- 00 (None)*/
+ /* PROT_RATE(15:0) -- 0x4004 (OFDM 24M)*/
+ Protect[4] = 0x01744004;
+
+ /* CF40_PROT_CFG*/
+ /* Reserved (31:27)*/
+ /* PROT_TXOP(25:20) -- 111111*/
+ /* PROT_NAV(19:18) -- 01 (Short NAV protection)*/
+ /* PROT_CTRL(17:16) -- 00 (None)*/
+ /* PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)*/
+ Protect[5] = 0x03f44084;
+
+ if (bNonGFExist)
+ {
+ /* PROT_NAV(19:18) -- 01 (Short NAV protectiion)*/
+ /* PROT_CTRL(17:16) -- 01 (RTS/CTS)*/
+ Protect[4] = 0x01754004;
+ Protect[5] = 0x03f54084;
+ }
+ pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
+
+#ifdef DOT11_VHT_AC
+#ifdef RT65xx
+ // TODO: shiang-6590, fix me for this protection mechanism
+ if (IS_RT65XX(pAd))
+ {
+ // Temporary tuen on RTS in VHT, MAC: TX_PROT_CFG6, TX_PROT_CFG7, TX_PROT_CFG8
+ PROT_CFG_STRUC vht_port_cfg;
+
+ RTMP_IO_READ32(pAd, TX_PROT_CFG6, &vht_port_cfg.word);
+ vht_port_cfg.field.ProtectCtrl = 0;
+ RTMP_IO_WRITE32(pAd, TX_PROT_CFG6, vht_port_cfg.word);
+
+ RTMP_IO_READ32(pAd, TX_PROT_CFG7, &vht_port_cfg.word);
+ vht_port_cfg.field.ProtectCtrl = 0;
+ RTMP_IO_WRITE32(pAd, TX_PROT_CFG7, vht_port_cfg.word);
+
+ RTMP_IO_READ32(pAd, TX_PROT_CFG8, &vht_port_cfg.word);
+ vht_port_cfg.field.ProtectCtrl = 0;
+ RTMP_IO_WRITE32(pAd, TX_PROT_CFG8, vht_port_cfg.word);
+ }
+#endif /* RT65xx */
+#endif /* DOT11_VHT_AC */
+
+
+ break;
+
+ case 1:
+ /* This is "HT non-member protection mode."*/
+ /* If there may be non-HT STAs my BSS*/
+ ProtCfg.word = 0x01744004; /* PROT_CTRL(17:16) : 0 (None)*/
+ ProtCfg4.word = 0x03f44084; /* duplicaet legacy 24M. BW set 1.*/
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
+ {
+ ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18..*/
+ ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083; */
+ }
+ /*Assign Protection method for 20&40 MHz packets*/
+ ProtCfg.field.ProtectCtrl = ASIC_RTS;
+ ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+ ProtCfg4.field.ProtectCtrl = ASIC_RTS;
+ ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
+ Protect[2] = ProtCfg.word;
+ Protect[3] = ProtCfg4.word;
+ Protect[4] = ProtCfg.word;
+ Protect[5] = ProtCfg4.word;
+ pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
+
+#ifdef DOT11_VHT_AC
+#ifdef RT65xx
+ // TODO: shiang-6590, fix me for this protection mechanism
+ if (IS_RT65XX(pAd))
+ {
+ // Temporary tuen on RTS in VHT, MAC: TX_PROT_CFG6, TX_PROT_CFG7, TX_PROT_CFG8
+ PROT_CFG_STRUC vht_port_cfg;
+
+ RTMP_IO_READ32(pAd, TX_PROT_CFG6, &vht_port_cfg.word);
+ vht_port_cfg.field.ProtectCtrl = ASIC_RTS;
+ RTMP_IO_WRITE32(pAd, TX_PROT_CFG6, vht_port_cfg.word);
+
+ RTMP_IO_READ32(pAd, TX_PROT_CFG7, &vht_port_cfg.word);
+ vht_port_cfg.field.ProtectCtrl = ASIC_RTS;
+ RTMP_IO_WRITE32(pAd, TX_PROT_CFG7, vht_port_cfg.word);
+
+ RTMP_IO_READ32(pAd, TX_PROT_CFG8, &vht_port_cfg.word);
+ vht_port_cfg.field.ProtectCtrl = ASIC_RTS;
+ RTMP_IO_WRITE32(pAd, TX_PROT_CFG8, vht_port_cfg.word);
+ }
+#endif /* RT65xx */
+#endif /* DOT11_VHT_AC */
+
+ break;
+
+ case 2:
+ /* If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets*/
+ ProtCfg.word = 0x01744004; /* PROT_CTRL(17:16) : 0 (None)*/
+ ProtCfg4.word = 0x03f44084; /* duplicaet legacy 24M. BW set 1.*/
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
+ {
+ ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18..*/
+ ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083; */
+ }
+ /*Assign Protection method for 40MHz packets*/
+ ProtCfg4.field.ProtectCtrl = ASIC_RTS;
+ ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
+ Protect[2] = ProtCfg.word;
+ Protect[3] = ProtCfg4.word;
+ if (bNonGFExist)
+ {
+ ProtCfg.field.ProtectCtrl = ASIC_RTS;
+ ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+ }
+ Protect[4] = ProtCfg.word;
+ Protect[5] = ProtCfg4.word;
+
+ pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
+
+#ifdef DOT11_VHT_AC
+#ifdef RT65xx
+ // TODO: shiang-6590, fix me for this protection mechanism
+ if (IS_RT65XX(pAd))
+ {
+ // Temporary tuen on RTS in VHT, MAC: TX_PROT_CFG6, TX_PROT_CFG7, TX_PROT_CFG8
+ PROT_CFG_STRUC vht_port_cfg;
+
+ RTMP_IO_READ32(pAd, TX_PROT_CFG6, &vht_port_cfg.word);
+ vht_port_cfg.field.ProtectCtrl = 0;
+ RTMP_IO_WRITE32(pAd, TX_PROT_CFG6, vht_port_cfg.word);
+
+ RTMP_IO_READ32(pAd, TX_PROT_CFG7, &vht_port_cfg.word);
+ vht_port_cfg.field.ProtectCtrl = ASIC_RTS;
+ RTMP_IO_WRITE32(pAd, TX_PROT_CFG7, vht_port_cfg.word);
+
+ RTMP_IO_READ32(pAd, TX_PROT_CFG8, &vht_port_cfg.word);
+ vht_port_cfg.field.ProtectCtrl = ASIC_RTS;
+ RTMP_IO_WRITE32(pAd, TX_PROT_CFG8, vht_port_cfg.word);
+ }
+#endif /* RT65xx */
+#endif /* DOT11_VHT_AC */
+ break;
+
+ case 3:
+ /* HT mixed mode. PROTECT ALL!*/
+ /* Assign Rate*/
+ ProtCfg.word = 0x01744004; /*duplicaet legacy 24M. BW set 1.*/
+ ProtCfg4.word = 0x03f44084;
+ /* both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the*/
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
+ {
+ ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18..*/
+ ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083*/
+ }
+ /*Assign Protection method for 20&40 MHz packets*/
+ ProtCfg.field.ProtectCtrl = ASIC_RTS;
+ ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+ ProtCfg4.field.ProtectCtrl = ASIC_RTS;
+ ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
+ Protect[2] = ProtCfg.word;
+ Protect[3] = ProtCfg4.word;
+ Protect[4] = ProtCfg.word;
+ Protect[5] = ProtCfg4.word;
+ pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
+
+#ifdef DOT11_VHT_AC
+#ifdef RT65xx
+ // TODO: shiang-6590, fix me for this protection mechanism
+ if (IS_RT65XX(pAd))
+ {
+ // Temporary tuen on RTS in VHT, MAC: TX_PROT_CFG6, TX_PROT_CFG7, TX_PROT_CFG8
+ PROT_CFG_STRUC vht_port_cfg;
+
+ RTMP_IO_READ32(pAd, TX_PROT_CFG6, &vht_port_cfg.word);
+ vht_port_cfg.field.ProtectCtrl = ASIC_RTS;
+ RTMP_IO_WRITE32(pAd, TX_PROT_CFG6, vht_port_cfg.word);
+
+ RTMP_IO_READ32(pAd, TX_PROT_CFG7, &vht_port_cfg.word);
+ vht_port_cfg.field.ProtectCtrl = ASIC_RTS;
+ RTMP_IO_WRITE32(pAd, TX_PROT_CFG7, vht_port_cfg.word);
+
+ RTMP_IO_READ32(pAd, TX_PROT_CFG8, &vht_port_cfg.word);
+ vht_port_cfg.field.ProtectCtrl = ASIC_RTS;
+ RTMP_IO_WRITE32(pAd, TX_PROT_CFG8, vht_port_cfg.word);
+ }
+#endif /* RT65xx */
+#endif /* DOT11_VHT_AC */
+ break;
+
+ case 8:
+ /* Special on for Atheros problem n chip.*/
+ ProtCfg.word = 0x01754004; /*duplicaet legacy 24M. BW set 1.*/
+ ProtCfg4.word = 0x03f54084;
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
+ {
+ ProtCfg.word = 0x01750003; /*ERP use Protection bit is set, use protection rate at Clause 18..*/
+ ProtCfg4.word = 0x03f50003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083*/
+ }
+
+ Protect[2] = ProtCfg.word; /*0x01754004;*/
+ Protect[3] = ProtCfg4.word; /*0x03f54084;*/
+ Protect[4] = ProtCfg.word; /*0x01754004;*/
+ Protect[5] = ProtCfg4.word; /*0x03f54084;*/
+ pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
+ break;
+ }
+ }
+#endif /* DOT11_N_SUPPORT */
+
+ offset = CCK_PROT_CFG;
+ for (i = 0;i < 6;i++)
+ {
+ if ((SetMask & (1<< i)))
+ {
+ RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
+ }
+}
+}
+
+
+VOID AsicBBPAdjust(RTMP_ADAPTER *pAd)
+{
+ // TODO: shiang-6590, now this function only used for AP mode, why we need this differentation?
+ if (pAd->chipOps.ChipBBPAdjust != NULL)
+ pAd->chipOps.ChipBBPAdjust(pAd);
+}
+
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicSwitchChannel(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR Channel,
+ IN BOOLEAN bScan)
+{
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_SUSPEND);
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef AP_QLOAD_SUPPORT
+ /* clear all statistics count for QBSS Load */
+ QBSS_LoadStatusClear(pAd);
+#endif /* AP_QLOAD_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pAd->chipOps.ChipSwitchChannel)
+ pAd->chipOps.ChipSwitchChannel(pAd, Channel, bScan);
+ else
+ DBGPRINT(RT_DEBUG_ERROR, ("For this chip, no specified channel switch function!\n"));
+
+ /* R66 should be set according to Channel and use 20MHz when scanning*/
+ if (bScan)
+ RTMPSetAGCInitValue(pAd, BW_20);
+ else
+ RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ This function is required for 2421 only, and should not be used during
+ site survey. It's only required after NIC decided to stay at a channel
+ for a longer period.
+ When this function is called, it's always after AsicSwitchChannel().
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicLockChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel)
+{
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+
+
+#ifdef RTMP_TEMPERATURE_COMPENSATION
+VOID InitLookupTable(
+ IN PRTMP_ADAPTER pAd)
+{
+ int Idx, IdxTmp;
+ int i;
+ enum IEEE80211_BAND band;
+ int band_nums = 1;
+ const int Offset = 7;
+ EEPROM_WORD_STRUC WordStruct = {{0}};
+ UCHAR PlusStepNum[IEEE80211_BAND_NUMS][8] = {{0, 1, 3, 2, 3, 3, 3, 2}, {0, 1, 3, 2, 3, 3, 3, 2}};
+ UCHAR MinusStepNum[IEEE80211_BAND_NUMS][8] = {{1, 1, 1, 1, 1, 1, 0, 1}, {1, 1, 1, 1, 1, 1, 0, 1}};
+ UCHAR Step[IEEE80211_BAND_NUMS] = {10, 10};
+ UCHAR RFValue = 0, BbpValue = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==> InitLookupTable\n"));
+
+ /* Read from EEPROM, as parameters for lookup table for G band */
+ RT28xx_EEPROM_READ16(pAd, 0x6e, WordStruct.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4G] EEPROM 6e = %x\n", WordStruct.word));
+ PlusStepNum[IEEE80211_BAND_2G][0] = (WordStruct.field.Byte0 & 0x0F);
+ PlusStepNum[IEEE80211_BAND_2G][1] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F);
+ PlusStepNum[IEEE80211_BAND_2G][2] = (WordStruct.field.Byte1 & 0x0F);
+ PlusStepNum[IEEE80211_BAND_2G][3] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F);
+
+ RT28xx_EEPROM_READ16(pAd, 0x70, WordStruct.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4G] EEPROM 70 = %x\n", WordStruct.word));
+ PlusStepNum[IEEE80211_BAND_2G][4] = (WordStruct.field.Byte0 & 0x0F);
+ PlusStepNum[IEEE80211_BAND_2G][5] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F);
+ PlusStepNum[IEEE80211_BAND_2G][6] = (WordStruct.field.Byte1 & 0x0F);
+ PlusStepNum[IEEE80211_BAND_2G][7] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F);
+
+ RT28xx_EEPROM_READ16(pAd, 0x72, WordStruct.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4G] EEPROM 72 = %x\n", WordStruct.word));
+ MinusStepNum[IEEE80211_BAND_2G][0] = (WordStruct.field.Byte0 & 0x0F);
+ MinusStepNum[IEEE80211_BAND_2G][1] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F);
+ MinusStepNum[IEEE80211_BAND_2G][2] = (WordStruct.field.Byte1 & 0x0F);
+ MinusStepNum[IEEE80211_BAND_2G][3] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F);
+
+ RT28xx_EEPROM_READ16(pAd, 0x74, WordStruct.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4] EEPROM 74 = %x\n", WordStruct.word));
+ MinusStepNum[IEEE80211_BAND_2G][4] = (WordStruct.field.Byte0 & 0x0F);
+ MinusStepNum[IEEE80211_BAND_2G][5] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F);
+ MinusStepNum[IEEE80211_BAND_2G][6] = (WordStruct.field.Byte1 & 0x0F);
+ MinusStepNum[IEEE80211_BAND_2G][7] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F);
+
+ RT28xx_EEPROM_READ16(pAd, 0x76, WordStruct.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4G] EEPROM 76 = %x\n", WordStruct.word));
+ pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_2G] = (WordStruct.field.Byte0 & 0x0F);
+ Step[IEEE80211_BAND_2G] = (WordStruct.field.Byte0 >> 4);
+ pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_2G] = (CHAR)WordStruct.field.Byte1;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4G] Plus = %u %u %u %u %u %u %u %u\n",
+ PlusStepNum[IEEE80211_BAND_2G][0],
+ PlusStepNum[IEEE80211_BAND_2G][1],
+ PlusStepNum[IEEE80211_BAND_2G][2],
+ PlusStepNum[IEEE80211_BAND_2G][3],
+ PlusStepNum[IEEE80211_BAND_2G][4],
+ PlusStepNum[IEEE80211_BAND_2G][5],
+ PlusStepNum[IEEE80211_BAND_2G][6],
+ PlusStepNum[IEEE80211_BAND_2G][7]
+ ));
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4G] Minus = %u %u %u %u %u %u %u %u\n",
+ MinusStepNum[IEEE80211_BAND_2G][0],
+ MinusStepNum[IEEE80211_BAND_2G][1],
+ MinusStepNum[IEEE80211_BAND_2G][2],
+ MinusStepNum[IEEE80211_BAND_2G][3],
+ MinusStepNum[IEEE80211_BAND_2G][4],
+ MinusStepNum[IEEE80211_BAND_2G][5],
+ MinusStepNum[IEEE80211_BAND_2G][6],
+ MinusStepNum[IEEE80211_BAND_2G][7]
+ ));
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4G] tssi gain/step = %u\n", pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_2G]));
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4] Step = %u\n", Step[IEEE80211_BAND_2G]));
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4] RefTemp_2G = %d\n", pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_2G]));
+
+#ifdef A_BAND_SUPPORT
+ if (RFIC_IS_5G_BAND(pAd))
+ {
+ /* Read from EEPROM, as parameters for lookup table for A band */
+ RT28xx_EEPROM_READ16(pAd, 0xd4, WordStruct.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] EEPROM d4 = %x\n", WordStruct.word));
+ PlusStepNum[IEEE80211_BAND_5G][0] = (WordStruct.field.Byte0 & 0x0F);
+ PlusStepNum[IEEE80211_BAND_5G][1] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F);
+ PlusStepNum[IEEE80211_BAND_5G][2] = (WordStruct.field.Byte1 & 0x0F);
+ PlusStepNum[IEEE80211_BAND_5G][3] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F);
+
+ RT28xx_EEPROM_READ16(pAd, 0xd6, WordStruct.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] EEPROM d6 = %x\n", WordStruct.word));
+ PlusStepNum[IEEE80211_BAND_5G][4] = (WordStruct.field.Byte0 & 0x0F);
+ PlusStepNum[IEEE80211_BAND_5G][5] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F);
+ PlusStepNum[IEEE80211_BAND_5G][6] = (WordStruct.field.Byte1 & 0x0F);
+ PlusStepNum[IEEE80211_BAND_5G][7] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F);
+
+ RT28xx_EEPROM_READ16(pAd, 0xd8, WordStruct.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] EEPROM d8 = %x\n", WordStruct.word));
+ MinusStepNum[IEEE80211_BAND_5G][0] = (WordStruct.field.Byte0 & 0x0F);
+ MinusStepNum[IEEE80211_BAND_5G][1] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F);
+ MinusStepNum[IEEE80211_BAND_5G][2] = (WordStruct.field.Byte1 & 0x0F);
+ MinusStepNum[IEEE80211_BAND_5G][3] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F);
+
+ RT28xx_EEPROM_READ16(pAd, 0xda, WordStruct.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] EEPROM da = %x\n", WordStruct.word));
+ MinusStepNum[IEEE80211_BAND_5G][4] = (WordStruct.field.Byte0 & 0x0F);
+ MinusStepNum[IEEE80211_BAND_5G][5] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F);
+ MinusStepNum[IEEE80211_BAND_5G][6] = (WordStruct.field.Byte1 & 0x0F);
+ MinusStepNum[IEEE80211_BAND_5G][7] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F);
+
+ RT28xx_EEPROM_READ16(pAd, 0xdc, WordStruct.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] EEPROM dc = %x\n", WordStruct.word));
+ pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_5G] = (WordStruct.field.Byte0 & 0x0F);
+ Step[IEEE80211_BAND_5G] = (WordStruct.field.Byte0 >> 4);
+ pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_5G] = (CHAR)WordStruct.field.Byte1;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] Plus = %u %u %u %u %u %u %u %u\n",
+ PlusStepNum[IEEE80211_BAND_5G][0],
+ PlusStepNum[IEEE80211_BAND_5G][1],
+ PlusStepNum[IEEE80211_BAND_5G][2],
+ PlusStepNum[IEEE80211_BAND_5G][3],
+ PlusStepNum[IEEE80211_BAND_5G][4],
+ PlusStepNum[IEEE80211_BAND_5G][5],
+ PlusStepNum[IEEE80211_BAND_5G][6],
+ PlusStepNum[IEEE80211_BAND_5G][7]
+ ));
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] Minus = %u %u %u %u %u %u %u %u\n",
+ MinusStepNum[IEEE80211_BAND_5G][0],
+ MinusStepNum[IEEE80211_BAND_5G][1],
+ MinusStepNum[IEEE80211_BAND_5G][2],
+ MinusStepNum[IEEE80211_BAND_5G][3],
+ MinusStepNum[IEEE80211_BAND_5G][4],
+ MinusStepNum[IEEE80211_BAND_5G][5],
+ MinusStepNum[IEEE80211_BAND_5G][6],
+ MinusStepNum[IEEE80211_BAND_5G][7]
+ ));
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] tssi gain/step = %u\n", pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_5G]));
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] Step = %u\n", Step[IEEE80211_BAND_5G]));
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] RefTemp_2G = %d\n", pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_5G]));
+
+ band_nums = IEEE80211_BAND_NUMS;
+ }
+#endif /* A_BAND_SUPPORT */
+
+
+ for (band = IEEE80211_BAND_2G; band < band_nums; band++)
+ {
+ /* positive */
+ i = 0;
+ IdxTmp = 1;
+
+ pAd->TxPowerCtrl.LookupTable[band][1 + Offset] = Step[band] / 2;
+ pAd->TxPowerCtrl.LookupTable[band][0 + Offset] = pAd->TxPowerCtrl.LookupTable[band][1 + Offset] - Step[band];
+ for (Idx = 2; Idx < 26;)/* Idx++ )*/
+ {
+ if (PlusStepNum[band][i] != 0 || i >= 8)
+ {
+ if (Idx >= IdxTmp + PlusStepNum[band][i] && i < 8)
+ {
+ pAd->TxPowerCtrl.LookupTable[band][Idx + Offset] = pAd->TxPowerCtrl.LookupTable[band][Idx - 1 + Offset] + (Step[band] - (i+1) + 1);
+ IdxTmp = IdxTmp + PlusStepNum[band][i];
+ i += 1;
+ }
+ else
+ {
+ pAd->TxPowerCtrl.LookupTable[band][Idx + Offset] = pAd->TxPowerCtrl.LookupTable[band][Idx - 1 + Offset] + (Step[band] - (i+1) + 1);
+ }
+ Idx++;
+ }
+ else
+ {
+ i += 1;
+ }
+ }
+
+ /* negative */
+ i = 0;
+ IdxTmp = 1;
+ for (Idx = 1; Idx < 8;)/* Idx++ )*/
+ {
+ if (MinusStepNum[band][i] != 0 || i >= 8)
+ {
+ if ((Idx + 1) >= IdxTmp + MinusStepNum[band][i] && i < 8)
+ {
+ pAd->TxPowerCtrl.LookupTable[band][-Idx + Offset] = pAd->TxPowerCtrl.LookupTable[band][-Idx + 1 + Offset] - (Step[band] + (i+1) - 1);
+ IdxTmp = IdxTmp + MinusStepNum[band][i];
+ i += 1;
+ }
+ else
+ {
+ pAd->TxPowerCtrl.LookupTable[band][-Idx + Offset] = pAd->TxPowerCtrl.LookupTable[band][-Idx + 1 + Offset] - (Step[band] + (i+1) - 1);
+ }
+ Idx++;
+ }
+ else
+ {
+ i += 1;
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] Lookup table as below:\n"));
+ for (Idx = 0; Idx < 33; Idx++)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation band(%d)] %d, %d\n", band, Idx - Offset, pAd->TxPowerCtrl.LookupTable[band][Idx]));
+ }
+ }
+
+ /* Set BBP_R47 */
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BbpValue);
+ BbpValue = (BbpValue & 0xf7); /* bit3 = 0 */
+ BbpValue = (BbpValue | 0x80); /* bit7 = 1, bit4 = 0 */
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BbpValue);
+
+ /* Set RF_R27 */
+ RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
+ /* Set [7:6] to 01. For method 2, it is set at initialization. */
+ RFValue = ((RFValue & 0x7f) | 0x40);
+ RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
+ DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] Set RF_R27 to 0x%x\n", RFValue));
+}
+
+
+VOID AsicGetAutoAgcOffsetForTemperatureSensor(
+ IN PRTMP_ADAPTER pAd,
+ IN PCHAR pDeltaPwr,
+ IN PCHAR pTotalDeltaPwr,
+ IN PCHAR pAgcCompensate,
+ IN PCHAR pDeltaPowerByBbpR1)
+{
+ RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
+ const TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable;
+ TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTableEntry0 = NULL; /* Ant0 */
+ TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTableEntry1 = NULL; /* Ant1 */
+ BBP_R49_STRUC BbpR49;
+ BOOLEAN bAutoTxAgc = FALSE;
+ PCHAR pTxAgcCompensate = NULL;
+ UCHAR RFValue = 0;
+ CHAR TuningTableUpperBound = 0, TuningTableIndex0 = 0, TuningTableIndex1 = 0;
+ INT CurrentTemp = 0;
+ INT RefTemp;
+ INT *LookupTable;
+ INT LookupTableIndex = pAd->TxPowerCtrl.LookupTableIndex + TEMPERATURE_COMPENSATION_LOOKUP_TABLE_OFFSET;
+
+ DBGPRINT(RT_DEBUG_INFO, ("-->%s\n", __FUNCTION__));
+
+ BbpR49.byte = 0;
+ *pTotalDeltaPwr = 0;
+
+#ifdef A_BAND_SUPPORT
+ if (pAd->CommonCfg.Channel > 14)
+ {
+ /* a band channel */
+ bAutoTxAgc = pAd->bAutoTxAgcA;
+ pTxAgcCompensate = &pAd->TxAgcCompensateA;
+ TxPowerTuningTable = pChipCap->TxPowerTuningTable_5G;
+ RefTemp = pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_5G];
+ LookupTable = &pAd->TxPowerCtrl.LookupTable[IEEE80211_BAND_5G][0];
+ TuningTableUpperBound = pChipCap->TxAlcTxPowerUpperBound_5G;
+ }
+ else
+#endif /* A_BAND_SUPPORT */
+ {
+ /* bg band channel */
+ bAutoTxAgc = pAd->bAutoTxAgcG;
+ pTxAgcCompensate = &pAd->TxAgcCompensateG;
+ TxPowerTuningTable = pChipCap->TxPowerTuningTable_2G;
+ RefTemp = pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_2G];
+ LookupTable = &pAd->TxPowerCtrl.LookupTable[IEEE80211_BAND_2G][0];
+ TuningTableUpperBound = pChipCap->TxAlcTxPowerUpperBound_2G;
+ }
+
+ /* AutoTxAgc in EEPROM means temperature compensation enabled/diablded. */
+ if (bAutoTxAgc)
+ {
+ /* Current temperature */
+#ifdef RT65xx
+ if (IS_RT65XX(pAd))
+ {
+ UINT32 bbp_val;
+ RTMP_BBP_IO_READ32(pAd, CORE_R35, &bbp_val);
+ CurrentTemp = (UCHAR)(bbp_val & 0xff);
+ }
+ else
+#endif /* RT65xx */
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49.byte);
+ CurrentTemp = (CHAR)BbpR49.byte;
+ }
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] BBP_R49 = %02x, current temp = %d\n", BbpR49.byte, CurrentTemp));
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] RefTemp = %d\n", RefTemp));
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] index = %d\n", pAd->TxPowerCtrl.LookupTableIndex));
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] f(%d)= %d\n", pAd->TxPowerCtrl.LookupTableIndex - 1, LookupTable[LookupTableIndex - 1]));
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] f(%d)= %d\n", pAd->TxPowerCtrl.LookupTableIndex, LookupTable[LookupTableIndex]));
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] f(%d)= %d\n", pAd->TxPowerCtrl.LookupTableIndex + 1, LookupTable[LookupTableIndex + 1]));
+ if (CurrentTemp > RefTemp + LookupTable[LookupTableIndex + 1] + ((LookupTable[LookupTableIndex + 1] - LookupTable[LookupTableIndex]) >> 2) &&
+ LookupTableIndex < 32)
+ {
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] ++\n"));
+ LookupTableIndex++;
+ pAd->TxPowerCtrl.LookupTableIndex++;
+ }
+ else if (CurrentTemp < RefTemp + LookupTable[LookupTableIndex] - ((LookupTable[LookupTableIndex] - LookupTable[LookupTableIndex - 1]) >> 2) &&
+ LookupTableIndex > 0)
+ {
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] --\n"));
+ LookupTableIndex--;
+ pAd->TxPowerCtrl.LookupTableIndex--;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] ==\n"));
+ }
+
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] idxTxPowerTable=%d, idxTxPowerTable2=%d, TuningTableUpperBound=%d\n",
+ pAd->TxPowerCtrl.idxTxPowerTable + pAd->TxPowerCtrl.LookupTableIndex,
+ pAd->TxPowerCtrl.idxTxPowerTable2 + pAd->TxPowerCtrl.LookupTableIndex,
+ TuningTableUpperBound));
+
+ TuningTableIndex0 = pAd->TxPowerCtrl.idxTxPowerTable
+ + pAd->TxPowerCtrl.LookupTableIndex
+#ifdef DOT11_N_SUPPORT
+ + pAd->TxPower[pAd->CommonCfg.CentralChannel-1].Power;
+#else
+ + pAd->TxPower[pAd->CommonCfg.Channel-1].Power;
+#endif /* DOT11_N_SUPPORT */
+ /* The boundary verification */
+ TuningTableIndex0 = (TuningTableIndex0 > TuningTableUpperBound) ? TuningTableUpperBound : TuningTableIndex0;
+ TuningTableIndex0 = (TuningTableIndex0 < LOWERBOUND_TX_POWER_TUNING_ENTRY) ?
+ LOWERBOUND_TX_POWER_TUNING_ENTRY : TuningTableIndex0;
+ TxPowerTuningTableEntry0 = &TxPowerTuningTable[TuningTableIndex0 + TX_POWER_TUNING_ENTRY_OFFSET];
+
+ TuningTableIndex1 = pAd->TxPowerCtrl.idxTxPowerTable2
+ + pAd->TxPowerCtrl.LookupTableIndex
+#ifdef DOT11_N_SUPPORT
+ + pAd->TxPower[pAd->CommonCfg.CentralChannel-1].Power2;
+#else
+ + pAd->TxPower[pAd->CommonCfg.Channel-1].Power2;
+#endif /* DOT11_N_SUPPORT */
+ /* The boundary verification */
+ TuningTableIndex1 = (TuningTableIndex1 > TuningTableUpperBound) ? TuningTableUpperBound : TuningTableIndex1;
+ TuningTableIndex1 = (TuningTableIndex1 < LOWERBOUND_TX_POWER_TUNING_ENTRY) ?
+ LOWERBOUND_TX_POWER_TUNING_ENTRY : TuningTableIndex1;
+ TxPowerTuningTableEntry1 = &TxPowerTuningTable[TuningTableIndex1 + TX_POWER_TUNING_ENTRY_OFFSET];
+
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] (tx0)RF_TX_ALC = %x, MAC_PowerDelta = %d, TuningTableIndex = %d\n",
+ TxPowerTuningTableEntry0->RF_TX_ALC, TxPowerTuningTableEntry0->MAC_PowerDelta, TuningTableIndex0));
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] (tx1)RF_TX_ALC = %x, MAC_PowerDelta = %d, TuningTableIndex = %d\n",
+ TxPowerTuningTableEntry1->RF_TX_ALC, TxPowerTuningTableEntry1->MAC_PowerDelta, TuningTableIndex1));
+
+ /* Update RF_R49 [0:5] */
+ RT30xxReadRFRegister(pAd, RF_R49, &RFValue);
+ RFValue = ((RFValue & ~0x3F) | TxPowerTuningTableEntry0->RF_TX_ALC);
+ if ((RFValue & 0x3F) > 0x27) /* The valid range of the RF R49 (<5:0>tx0_alc<5:0>) is 0x00~0x27 */
+ {
+ RFValue = ((RFValue & ~0x3F) | 0x27);
+ }
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] Update RF_R49[0:5] to 0x%x\n", TxPowerTuningTableEntry0->RF_TX_ALC));
+ RT30xxWriteRFRegister(pAd, RF_R49, RFValue);
+
+ /* Update RF_R50 [0:5] */
+ RT30xxReadRFRegister(pAd, RF_R50, &RFValue);
+ RFValue = ((RFValue & ~0x3F) | TxPowerTuningTableEntry1->RF_TX_ALC);
+ if ((RFValue & 0x3F) > 0x27) /* The valid range of the RF R49 (<5:0>tx0_alc<5:0>) is 0x00~0x27 */
+ {
+ RFValue = ((RFValue & ~0x3F) | 0x27);
+ }
+ DBGPRINT(RT_DEBUG_INFO, ("[temp. compensation] Update RF_R50[0:5] to 0x%x\n", TxPowerTuningTableEntry1->RF_TX_ALC));
+ RT30xxWriteRFRegister(pAd, RF_R50, RFValue);
+
+ *pTotalDeltaPwr = TxPowerTuningTableEntry0->MAC_PowerDelta;
+
+ }
+
+ *pAgcCompensate = *pTxAgcCompensate;
+ DBGPRINT(RT_DEBUG_INFO, ("<--%s\n", __FUNCTION__));
+}
+#endif /* RTMP_TEMPERATURE_COMPENSATION */
+
+
+VOID AsicResetBBPAgent(
+IN PRTMP_ADAPTER pAd)
+{
+ BBP_CSR_CFG_STRUC BbpCsr;
+
+ /* Still need to find why BBP agent keeps busy, but in fact, hardware still function ok. Now clear busy first. */
+ /* IF chipOps.AsicResetBbpAgent == NULL, run "else" part */
+ RTMP_CHIP_ASIC_RESET_BBP_AGENT(pAd);
+ else
+ {
+ DBGPRINT(RT_DEBUG_INFO, ("Reset BBP Agent busy bit.!! \n"));
+ RTMP_IO_READ32(pAd, H2M_BBP_AGENT, &BbpCsr.word);
+ BbpCsr.field.Busy = 0;
+ RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word);
+}
+
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Set My BSSID
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicSetBssid(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pBssid)
+{
+ ULONG Addr4;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
+ PRINT_MAC(pBssid)));
+
+ Addr4 = (ULONG)(pBssid[0]) |
+ (ULONG)(pBssid[1] << 8) |
+ (ULONG)(pBssid[2] << 16) |
+ (ULONG)(pBssid[3] << 24);
+ RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
+
+#ifdef HDR_TRANS_SUPPORT
+ RTMP_IO_WRITE32(pAd, HT_MAC_BSSID_DW0, Addr4);
+#endif /* HDR_TRANS_SUPPORT */
+
+ Addr4 = 0;
+ /* always one BSSID in STA mode*/
+ Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
+
+
+ RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
+
+#ifdef HDR_TRANS_SUPPORT
+ /*
+ point WCID MAC table to 0x1800
+ This is for debug.
+ But HDR_TRANS doesn't work if you remove it.
+ Check after IC formal release.
+ */
+ Addr4 |= 0x18000000;
+ RTMP_IO_WRITE32(pAd, HT_MAC_BSSID_DW1, Addr4);
+#endif /* HDR_TRANS_SUPPORT */
+
+}
+
+
+VOID AsicSetMcastWC(RTMP_ADAPTER *pAd)
+{
+ MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
+
+ pEntry->Sst = SST_ASSOC;
+ pEntry->Aid = MCAST_WCID; /* Softap supports 1 BSSID and use WCID=0 as multicast Wcid index*/
+ pEntry->PsMode = PWR_ACTIVE;
+ pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
+ //offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicDelWcidTab(RTMP_ADAPTER *pAd, UCHAR Wcid)
+{
+ UINT32 offset;
+
+ DBGPRINT(RT_DEBUG_INFO, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
+
+ offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
+ RTMP_IO_WRITE32(pAd, offset, 0x0);
+ offset += 4;
+ RTMP_IO_WRITE32(pAd, offset, 0x0);
+}
+
+#ifdef DOT11_N_SUPPORT
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicEnableRDG(
+ IN PRTMP_ADAPTER pAd)
+{
+ TX_LINK_CFG_STRUC TxLinkCfg;
+ UINT32 Data = 0;
+
+ RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
+ TxLinkCfg.field.TxRDGEn = 1;
+ RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
+
+ RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+ Data &= 0xFFFFFF00;
+ Data |= 0x80;
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicDisableRDG(
+ IN PRTMP_ADAPTER pAd)
+{
+ TX_LINK_CFG_STRUC TxLinkCfg;
+ UINT32 Data = 0;
+
+
+
+ RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
+ TxLinkCfg.field.TxRDGEn = 0;
+ RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
+
+ RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+
+ Data &= 0xFFFFFF00;
+ /*Data |= 0x20;*/
+#ifndef WIFI_TEST
+ /*if ( pAd->CommonCfg.bEnableTxBurst ) */
+ /* Data |= 0x60; for performance issue not set the TXOP to 0*/
+#endif
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
+#ifdef DOT11_N_SUPPORT
+ && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
+#endif /* DOT11_N_SUPPORT */
+ )
+ {
+ /* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode*/
+ if (pAd->CommonCfg.bEnableTxBurst)
+ Data |= 0x20;
+ }
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+
+}
+#endif /* DOT11_N_SUPPORT */
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicDisableSync(
+ IN PRTMP_ADAPTER pAd)
+{
+ BCN_TIME_CFG_STRUC csr;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
+
+ /* 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect*/
+ /* that NIC will never wakes up because TSF stops and no more */
+ /* TBTT interrupts*/
+ pAd->TbttTickCount = 0;
+ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+ csr.field.bBeaconGen = 0;
+ csr.field.bTBTTEnable = 0;
+ csr.field.TsfSyncMode = 0;
+ csr.field.bTsfTicking = 0;
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicEnableBssSync(
+ IN PRTMP_ADAPTER pAd)
+{
+ BCN_TIME_CFG_STRUC csr;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
+
+ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+/* RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000);*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; /* ASIC register in units of 1/16 TU*/
+ csr.field.bTsfTicking = 1;
+ csr.field.TsfSyncMode = 3; /* sync TSF similar as in ADHOC mode?*/
+ csr.field.bBeaconGen = 1; /* AP should generate BEACON*/
+ csr.field.bTBTTEnable = 1;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Note:
+ BEACON frame in shared memory should be built ok before this routine
+ can be called. Otherwise, a garbage frame maybe transmitted out every
+ Beacon period.
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicEnableIbssSync(
+ IN PRTMP_ADAPTER pAd)
+{
+ BCN_TIME_CFG_STRUC csr9;
+ PUCHAR ptr;
+ UINT i;
+ ULONG beaconBaseLocation = 0;
+ USHORT beaconLen = (USHORT) pAd->BeaconTxWI.TxWIMPDUByteCnt;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+ UINT32 longptr;
+
+#ifdef RT_BIG_ENDIAN
+ {
+ TXWI_STRUC localTxWI;
+
+ NdisMoveMemory((PUCHAR)&localTxWI, (PUCHAR)&pAd->BeaconTxWI, TXWISize);
+ RTMPWIEndianChange(pAd, (PUCHAR)&localTxWI, TYPE_TXWI);
+ beaconLen = (USHORT) localTxWI.TxWIMPDUByteCnt;
+ }
+#endif /* RT_BIG_ENDIAN */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(TxWIMPDUByteCnt=%d, beaconLen=%d)\n", pAd->BeaconTxWI.TxWIMPDUByteCnt, beaconLen));
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. TxWIMPDUByteCnt = %d)\n", pAd->BeaconTxWI.TxWIMPDUByteCnt));
+
+ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
+ csr9.field.bBeaconGen = 0;
+ csr9.field.bTBTTEnable = 0;
+ csr9.field.bTsfTicking = 0;
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
+ beaconBaseLocation = HW_BEACON_BASE0(pAd);
+
+
+#ifdef RTMP_MAC_USB
+ /* move BEACON TXD and frame content to on-chip memory*/
+ ptr = (PUCHAR)&pAd->BeaconTxWI;
+ for (i=0; i < TXWISize; i+=2)
+ {
+ longptr = *ptr + (*(ptr+1)<<8);
+ RTMP_CHIP_UPDATE_BEACON(pAd, HW_BEACON_BASE0(pAd) + i, longptr, 2);
+ ptr += 2;
+ }
+
+ /* start right after the 16-byte TXWI field*/
+ ptr = pAd->BeaconBuf;
+ /*for (i=0; i< pAd->BeaconTxWI.TxWIMPDUByteCnt; i+=2)*/
+ for (i=0; i< beaconLen; i+=2)
+ {
+ longptr = *ptr + (*(ptr+1)<<8);
+ RTMP_CHIP_UPDATE_BEACON(pAd, HW_BEACON_BASE0(pAd) + TXWISize + i, longptr, 2);
+ ptr +=2;
+ }
+#endif /* RTMP_MAC_USB */
+
+
+
+ /* For Wi-Fi faily generated beacons between participating stations. */
+ /* Set TBTT phase adaptive adjustment step to 8us (default 16us)*/
+ /* don't change settings 2006-5- by Jerry*/
+ /*RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010);*/
+
+ /* start sending BEACON*/
+ csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; /* ASIC register in units of 1/16 TU*/
+ csr9.field.bTsfTicking = 1;
+ /*
+ (STA ad-hoc mode) Upon the reception of BEACON frame from associated BSS,
+ local TSF is updated with remote TSF only if the remote TSF is greater than local TSF
+ */
+ csr9.field.TsfSyncMode = 2; /* sync TSF in IBSS mode*/
+ csr9.field.bTBTTEnable = 1;
+ csr9.field.bBeaconGen = 1;
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicSetEdcaParm(
+ IN PRTMP_ADAPTER pAd,
+ IN PEDCA_PARM pEdcaParm)
+{
+ EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
+ AC_TXOP_CSR0_STRUC csr0;
+ AC_TXOP_CSR1_STRUC csr1;
+ AIFSN_CSR_STRUC AifsnCsr;
+ CWMIN_CSR_STRUC CwminCsr;
+ CWMAX_CSR_STRUC CwmaxCsr;
+ int i;
+
+ Ac0Cfg.word = 0;
+ Ac1Cfg.word = 0;
+ Ac2Cfg.word = 0;
+ Ac3Cfg.word = 0;
+ if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i]) || IS_ENTRY_APCLI(&pAd->MacTab.Content[i]))
+ CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
+ }
+
+ /*========================================================*/
+ /* MAC Register has a copy .*/
+ /*========================================================*/
+/*#ifndef WIFI_TEST*/
+ if( pAd->CommonCfg.bEnableTxBurst )
+ {
+ /* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode*/
+ Ac0Cfg.field.AcTxop = 0x20; /* Suggest by John for TxBurst in HT Mode*/
+ }
+ else
+ Ac0Cfg.field.AcTxop = 0; /* QID_AC_BE*/
+/*#else*/
+/* Ac0Cfg.field.AcTxop = 0; QID_AC_BE*/
+/*#endif */
+ Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
+ Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
+ Ac0Cfg.field.Aifsn = 2;
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
+
+ Ac1Cfg.field.AcTxop = 0; /* QID_AC_BK*/
+ Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
+ Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
+ Ac1Cfg.field.Aifsn = 2;
+ RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
+
+ if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B))
+ {
+ Ac2Cfg.field.AcTxop = 192; /* AC_VI: 192*32us ~= 6ms*/
+ Ac3Cfg.field.AcTxop = 96; /* AC_VO: 96*32us ~= 3ms*/
+ }
+ else
+ {
+ Ac2Cfg.field.AcTxop = 96; /* AC_VI: 96*32us ~= 3ms*/
+ Ac3Cfg.field.AcTxop = 48; /* AC_VO: 48*32us ~= 1.5ms*/
+ }
+ Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
+ Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
+ Ac2Cfg.field.Aifsn = 2;
+ RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
+ Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
+ Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
+ Ac3Cfg.field.Aifsn = 2;
+ RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
+
+ /*========================================================*/
+ /* DMA Register has a copy too.*/
+ /*========================================================*/
+ csr0.field.Ac0Txop = 0; /* QID_AC_BE*/
+ csr0.field.Ac1Txop = 0; /* QID_AC_BK*/
+ RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
+ if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B))
+ {
+ csr1.field.Ac2Txop = 192; /* AC_VI: 192*32us ~= 6ms*/
+ csr1.field.Ac3Txop = 96; /* AC_VO: 96*32us ~= 3ms*/
+ }
+ else
+ {
+ csr1.field.Ac2Txop = 96; /* AC_VI: 96*32us ~= 3ms*/
+ csr1.field.Ac3Txop = 48; /* AC_VO: 48*32us ~= 1.5ms*/
+ }
+ RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
+
+ CwminCsr.word = 0;
+ CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
+ CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
+ CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
+ CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
+ RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
+
+ CwmaxCsr.word = 0;
+ CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
+ CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
+ CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
+ CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
+ RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
+
+ RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
+
+ NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
+
+ }
+ else
+ {
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
+ /*========================================================*/
+ /* MAC Register has a copy.*/
+ /*========================================================*/
+
+ /* Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27*/
+ /* To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.*/
+
+ /*pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; rt2860c need this */
+
+ Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
+ Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
+ Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
+ Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; /*+1;*/
+
+ Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
+ Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; /*+2; */
+ Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
+ Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; /*+1;*/
+
+
+ Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
+ {
+ Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
+ Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
+ }
+ /*sync with window 20110524*/
+ Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI] + 1; /* 5.2.27 T6 Pass Tx VI+BE, but will impack 5.2.27/28 T7. Tx VI*/
+
+#ifdef INF_AMAZON_SE
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ Ac2Cfg.field.Aifsn = 0x3; /*for WiFi WMM A1-T07.*/
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* INF_AMAZON_SE */
+
+
+ Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
+ Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
+ Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
+ Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
+/* For WMM Test PASS */
+#ifdef CONFIG_AP_SUPPORT
+#ifdef RTMP_MAC_USB
+#ifdef MT7601
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if ( IS_MT7601(pAd) && Ac3Cfg.field.Aifsn > 0)
+ Ac3Cfg.field.Aifsn --;
+ }
+#endif /* MT7601 */
+#endif /* RTMP_MAC_USB */
+#endif /* CONFIG_AP_SUPPORT */
+
+/*#ifdef WIFI_TEST*/
+ if (pAd->CommonCfg.bWiFiTest)
+ {
+ if (Ac3Cfg.field.AcTxop == 102)
+ {
+ Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
+ Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
+ Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
+ Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
+ Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
+ }
+ }
+/*#endif WIFI_TEST */
+
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
+ RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
+ RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
+ RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
+
+ /*========================================================*/
+ /* DMA Register has a copy too.*/
+ /*========================================================*/
+ csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
+ csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
+ RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
+
+ csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
+ csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
+ RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
+
+ CwminCsr.word = 0;
+ CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
+ CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
+ CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO];
+#endif /* CONFIG_AP_SUPPORT */
+ RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
+
+ CwmaxCsr.word = 0;
+ CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
+ CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
+ CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
+ CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
+ RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
+
+ AifsnCsr.word = 0;
+ AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_BE];*/
+ AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_BK];*/
+ AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_VI];*/
+#ifdef INF_AMAZON_SE
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_VO]*/
+ AifsnCsr.field.Aifsn2 = 0x2; /*pEdcaParm->Aifsn[QID_AC_VI]; for WiFi WMM A1-T07.*/
+ }
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* INF_AMAZON_SE */
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_VO]*/
+#endif /* CONFIG_AP_SUPPORT */
+ RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
+
+ NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
+ if (!ADHOC_ON(pAd))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
+ DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
+ pEdcaParm->Aifsn[0],
+ pEdcaParm->Cwmin[0],
+ pEdcaParm->Cwmax[0],
+ pEdcaParm->Txop[0]<<5,
+ pEdcaParm->bACM[0]));
+ DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
+ pEdcaParm->Aifsn[1],
+ pEdcaParm->Cwmin[1],
+ pEdcaParm->Cwmax[1],
+ pEdcaParm->Txop[1]<<5,
+ pEdcaParm->bACM[1]));
+ DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
+ pEdcaParm->Aifsn[2],
+ pEdcaParm->Cwmin[2],
+ pEdcaParm->Cwmax[2],
+ pEdcaParm->Txop[2]<<5,
+ pEdcaParm->bACM[2]));
+ DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
+ pEdcaParm->Aifsn[3],
+ pEdcaParm->Cwmin[3],
+ pEdcaParm->Cwmax[3],
+ pEdcaParm->Txop[3]<<5,
+ pEdcaParm->bACM[3]));
+ }
+
+ }
+
+ pAd->CommonCfg.RestoreBurstMode = Ac0Cfg.word;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicSetSlotTime(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bUseShortSlotTime)
+{
+ ULONG SlotTime;
+ UINT32 RegValue = 0;
+
+
+ if (bUseShortSlotTime && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED))
+ return;
+ else if ((!bUseShortSlotTime) && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED)))
+ return;
+
+ if (bUseShortSlotTime)
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
+ else
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
+
+ SlotTime = (bUseShortSlotTime)? 9 : 20;
+
+
+
+ /* For some reasons, always set it to short slot time.*/
+ /* ToDo: Should consider capability with 11B*/
+
+ RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
+ RegValue = RegValue & 0xFFFFFF00;
+
+ RegValue |= SlotTime;
+
+ RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
+}
+
+/*
+ ========================================================================
+ Description:
+ Add Shared key information into ASIC.
+ Update shared key, TxMic and RxMic to Asic Shared key table
+ Update its cipherAlg to Asic Shared key Mode.
+
+ Return:
+ ========================================================================
+*/
+VOID AsicAddSharedKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssIndex,
+ IN UCHAR KeyIdx,
+ IN PCIPHER_KEY pCipherKey)
+{
+ ULONG offset; /*, csr0;*/
+ SHAREDKEY_MODE_STRUC csr1;
+
+ PUCHAR pKey = pCipherKey->Key;
+ PUCHAR pTxMic = pCipherKey->TxMic;
+ PUCHAR pRxMic = pCipherKey->RxMic;
+ UCHAR CipherAlg = pCipherKey->CipherAlg;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
+/*============================================================================================*/
+
+ DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
+ DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
+ if (pRxMic)
+ {
+ DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
+ }
+ if (pTxMic)
+ {
+ DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
+ }
+/*============================================================================================*/
+
+ /* fill key material - key + TX MIC + RX MIC*/
+
+
+#ifdef RTMP_MAC_USB
+{
+ offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
+ RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY, FALSE);
+
+ offset += MAX_LEN_OF_SHARE_KEY;
+ if (pTxMic)
+ {
+ RTUSBMultiWrite(pAd, offset, pTxMic, 8, FALSE);
+ }
+
+ offset += 8;
+ if (pRxMic)
+ {
+ RTUSBMultiWrite(pAd, offset, pRxMic, 8, FALSE);
+ }
+}
+#endif /* RTMP_MAC_USB */
+
+
+ /* Update cipher algorithm. WSTA always use BSS0*/
+ RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
+ DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
+ if ((BssIndex%2) == 0)
+ {
+ if (KeyIdx == 0)
+ csr1.field.Bss0Key0CipherAlg = CipherAlg;
+ else if (KeyIdx == 1)
+ csr1.field.Bss0Key1CipherAlg = CipherAlg;
+ else if (KeyIdx == 2)
+ csr1.field.Bss0Key2CipherAlg = CipherAlg;
+ else
+ csr1.field.Bss0Key3CipherAlg = CipherAlg;
+ }
+ else
+ {
+ if (KeyIdx == 0)
+ csr1.field.Bss1Key0CipherAlg = CipherAlg;
+ else if (KeyIdx == 1)
+ csr1.field.Bss1Key1CipherAlg = CipherAlg;
+ else if (KeyIdx == 2)
+ csr1.field.Bss1Key2CipherAlg = CipherAlg;
+ else
+ csr1.field.Bss1Key3CipherAlg = CipherAlg;
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
+ RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
+
+}
+
+/* IRQL = DISPATCH_LEVEL*/
+VOID AsicRemoveSharedKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssIndex,
+ IN UCHAR KeyIdx)
+{
+ /*ULONG SecCsr0;*/
+ SHAREDKEY_MODE_STRUC csr1;
+
+ DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
+
+ RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
+ if ((BssIndex%2) == 0)
+ {
+ if (KeyIdx == 0)
+ csr1.field.Bss0Key0CipherAlg = 0;
+ else if (KeyIdx == 1)
+ csr1.field.Bss0Key1CipherAlg = 0;
+ else if (KeyIdx == 2)
+ csr1.field.Bss0Key2CipherAlg = 0;
+ else
+ csr1.field.Bss0Key3CipherAlg = 0;
+ }
+ else
+ {
+ if (KeyIdx == 0)
+ csr1.field.Bss1Key0CipherAlg = 0;
+ else if (KeyIdx == 1)
+ csr1.field.Bss1Key1CipherAlg = 0;
+ else if (KeyIdx == 2)
+ csr1.field.Bss1Key2CipherAlg = 0;
+ else
+ csr1.field.Bss1Key3CipherAlg = 0;
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
+ RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
+ ASSERT(BssIndex < 4);
+ ASSERT(KeyIdx < 4);
+
+}
+
+VOID AsicUpdateWCIDIVEIV(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT WCID,
+ IN ULONG uIV,
+ IN ULONG uEIV)
+{
+ ULONG offset;
+
+ offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
+
+ RTMP_IO_WRITE32(pAd, offset, uIV);
+ RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: wcid(%d) 0x%08lx, 0x%08lx \n",
+ __FUNCTION__, WCID, uIV, uEIV));
+}
+
+VOID AsicUpdateRxWCIDTable(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT WCID,
+ IN PUCHAR pAddr)
+{
+ ULONG offset;
+ ULONG Addr;
+
+ offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
+ Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
+ RTMP_IO_WRITE32(pAd, offset, Addr);
+ Addr = pAddr[4] + (pAddr[5] << 8);
+ RTMP_IO_WRITE32(pAd, offset + 4, Addr);
+}
+
+/*
+ ========================================================================
+ Description:
+ Add Client security information into ASIC WCID table and IVEIV table.
+ Return:
+
+ Note :
+ The key table selection rule :
+ 1. Wds-links and Mesh-links always use Pair-wise key table.
+ 2. When the CipherAlg is TKIP, AES, SMS4 or the dynamic WEP is enabled,
+ it needs to set key into Pair-wise Key Table.
+ 3. The pair-wise key security mode is set NONE, it means as no security.
+ 4. In STA Adhoc mode, it always use shared key table.
+ 5. Otherwise, use shared key table
+
+ ========================================================================
+*/
+VOID AsicUpdateWcidAttributeEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssIdx,
+ IN UCHAR KeyIdx,
+ IN UCHAR CipherAlg,
+ IN UINT8 Wcid,
+ IN UINT8 KeyTabFlag)
+{
+ WCID_ATTRIBUTE_STRUC WCIDAttri;
+ USHORT offset;
+
+ /* Initialize the content of WCID Attribue */
+ WCIDAttri.word = 0;
+
+ /* The limitation of HW WCID table */
+ if (/*Wcid < 1 ||*/ Wcid > 254)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s: Wcid is invalid (%d). \n",
+ __FUNCTION__, Wcid));
+ return;
+ }
+
+ /* Update the pairwise key security mode.
+ Use bit10 and bit3~1 to indicate the pairwise cipher mode */
+ WCIDAttri.field.PairKeyModeExt = ((CipherAlg & 0x08) >> 3);
+ WCIDAttri.field.PairKeyMode = (CipherAlg & 0x07);
+
+ /* Update the MBSS index.
+ Use bit11 and bit6~4 to indicate the BSS index */
+ WCIDAttri.field.BSSIdxExt = ((BssIdx & 0x08) >> 3);
+ WCIDAttri.field.BSSIdx = (BssIdx & 0x07);
+
+#ifdef WAPI_SUPPORT
+ /* Update WAPI related information */
+ if (CipherAlg == CIPHER_SMS4)
+ {
+ if (KeyTabFlag == SHAREDKEYTABLE)
+ WCIDAttri.field.WAPI_MCBC = 1;
+ WCIDAttri.field.WAPIKeyIdx = ((KeyIdx == 0) ? 0 : 1);
+ }
+#endif /* WAPI_SUPPORT */
+
+ /* Assign Key Table selection */
+ WCIDAttri.field.KeyTab = KeyTabFlag;
+
+ /* Update related information to ASIC */
+ offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
+ RTMP_IO_WRITE32(pAd, offset, WCIDAttri.word);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s : WCID #%d, KeyIndex #%d, Alg=%s\n", __FUNCTION__, Wcid, KeyIdx, CipherName[CipherAlg]));
+ DBGPRINT(RT_DEBUG_TRACE, (" WCIDAttri = 0x%x \n", WCIDAttri.word));
+
+}
+
+
+/*
+ ========================================================================
+ Description:
+ Add Pair-wise key material into ASIC.
+ Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
+
+ Return:
+ ========================================================================
+*/
+VOID AsicAddPairwiseKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR WCID,
+ IN PCIPHER_KEY pCipherKey)
+{
+ INT i;
+ ULONG offset;
+ PUCHAR pKey = pCipherKey->Key;
+ PUCHAR pTxMic = pCipherKey->TxMic;
+ PUCHAR pRxMic = pCipherKey->RxMic;
+ UCHAR CipherAlg = pCipherKey->CipherAlg;
+
+ /* EKEY*/
+ offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
+#ifdef RTMP_MAC_USB
+ RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY, FALSE);
+#endif /* RTMP_MAC_USB */
+ for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
+ {
+ UINT32 Value;
+ RTMP_IO_READ32(pAd, offset + i, &Value);
+ }
+
+ offset += MAX_LEN_OF_PEER_KEY;
+
+ /* MIC KEY*/
+ if (pTxMic)
+ {
+#ifdef RTMP_MAC_USB
+ RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8, FALSE);
+#endif /* RTMP_MAC_USB */
+ }
+ offset += 8;
+ if (pRxMic)
+ {
+#ifdef RTMP_MAC_USB
+ RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8, FALSE);
+#endif /* RTMP_MAC_USB */
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
+ DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
+ if (pRxMic)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
+ }
+ if (pTxMic)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
+ }
+}
+
+/*
+ ========================================================================
+ Description:
+ Remove Pair-wise key material from ASIC.
+
+ Return:
+ ========================================================================
+*/
+VOID AsicRemovePairwiseKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid)
+{
+ /* Set the specific WCID attribute entry as OPEN-NONE */
+ AsicUpdateWcidAttributeEntry(pAd,
+ BSS0,
+ 0,
+ CIPHER_NONE,
+ Wcid,
+ PAIRWISEKEYTABLE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s : Wcid #%d \n", __FUNCTION__, Wcid));
+}
+
+BOOLEAN AsicSendCommandToMcu(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR Command,
+ IN UCHAR Token,
+ IN UCHAR Arg0,
+ IN UCHAR Arg1,
+ IN BOOLEAN in_atomic)
+{
+#ifdef RT65xx
+ // TODO: shiang-6590, fix me, currently firmware is not ready yet, so ignore it!
+ if (IS_RT65XX(pAd))
+ return TRUE;
+#endif /* RT65xx */
+
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ return TRUE;
+#endif /* MT7601 */
+
+ if (pAd->chipOps.sendCommandToMcu)
+ return pAd->chipOps.sendCommandToMcu(pAd, Command, Token, Arg0, Arg1, in_atomic);
+ else
+ return FALSE;
+}
+
+
+BOOLEAN AsicSendCommandToMcuBBP(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Command,
+ IN UCHAR Token,
+ IN UCHAR Arg0,
+ IN UCHAR Arg1,
+ IN BOOLEAN FlgIsNeedLocked)
+{
+#ifdef RT65xx
+ // TODO: shiang-6590, fix me, currently firmware is not ready yet, so ignore it!
+ if (IS_RT65XX(pAd)) {
+ return TRUE;
+ }
+#endif /* RT65xx */
+
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ return TRUE;
+#endif /* MT7601 */
+
+ if (pAd->chipOps.sendCommandToMcu)
+ return pAd->chipOps.sendCommandToMcu(pAd, Command, Token, Arg0, Arg1, FlgIsNeedLocked);
+ else
+ return FALSE;
+}
+
+/*
+ ========================================================================
+ Description:
+ For 1x1 chipset : 2070 / 3070 / 3090 / 3370 / 3390 / 5370 / 5390
+ Usage : 1. Set Default Antenna as initialize
+ 2. Antenna Diversity switching used
+ 3. iwpriv command switch Antenna
+
+ Return:
+ ========================================================================
+ */
+VOID AsicSetRxAnt(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Ant)
+{
+ if (pAd->chipOps.SetRxAnt)
+ pAd->chipOps.SetRxAnt(pAd, Ant);
+}
+
+
+VOID AsicTurnOffRFClk(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel)
+{
+ if (pAd->chipOps.AsicRfTurnOff)
+ {
+ pAd->chipOps.AsicRfTurnOff(pAd);
+ }
+ else
+ {
+#if defined(RT28xx) || defined(RT2880) || defined(RT2883)
+ /* RF R2 bit 18 = 0*/
+ UINT32 R1 = 0, R2 = 0, R3 = 0;
+ UCHAR index;
+ RTMP_RF_REGS *RFRegTable;
+
+ RFRegTable = RF2850RegTable;
+#endif /* defined(RT28xx) || defined(RT2880) || defined(RT2883) */
+
+ switch (pAd->RfIcType)
+ {
+#if defined(RT28xx) || defined(RT2880) || defined(RT2883)
+#if defined(RT28xx) || defined(RT2880)
+ case RFIC_2820:
+ case RFIC_2850:
+ case RFIC_2720:
+ case RFIC_2750:
+#endif /* defined(RT28xx) || defined(RT2880) */
+ for (index = 0; index < NUM_OF_2850_CHNL; index++)
+ {
+ if (Channel == RFRegTable[index].Channel)
+ {
+ R1 = RFRegTable[index].R1 & 0xffffdfff;
+ R2 = RFRegTable[index].R2 & 0xfffbffff;
+ R3 = RFRegTable[index].R3 & 0xfff3ffff;
+
+ RTMP_RF_IO_WRITE32(pAd, R1);
+ RTMP_RF_IO_WRITE32(pAd, R2);
+
+ /* Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. */
+ /* Set RF R2 bit18=0, R3 bit[18:19]=0*/
+ /*if (pAd->StaCfg.bRadio == FALSE)*/
+ if (1)
+ {
+ RTMP_RF_IO_WRITE32(pAd, R3);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
+ Channel, pAd->RfIcType, R2, R3));
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
+ Channel, pAd->RfIcType, R2));
+ break;
+ }
+ }
+ break;
+#endif /* defined(RT28xx) || defined(RT2880) || defined(RT2883) */
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d : Unkonwn RFIC=%d\n",
+ Channel, pAd->RfIcType));
+ break;
+ }
+ }
+}
+
+
+#ifdef WAPI_SUPPORT
+VOID AsicUpdateWAPIPN(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT WCID,
+ IN ULONG pn_low,
+ IN ULONG pn_high)
+{
+ if (IS_HW_WAPI_SUPPORT(pAd))
+ {
+ ULONG offset;
+
+ offset = WAPI_PN_TABLE_BASE + (WCID * WAPI_PN_ENTRY_SIZE);
+
+ RTMP_IO_WRITE32(pAd, offset, pn_low);
+ RTMP_IO_WRITE32(pAd, offset + 4, pn_high);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s : Not support HW_WAPI_PN_TABLE\n",
+ __FUNCTION__));
+ }
+
+}
+#endif /* WAPI_SUPPORT */
+
+
+
+#ifdef VCORECAL_SUPPORT
+VOID AsicVCORecalibration(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR RFValue = 0;
+ UINT32 TxPinCfg = 0;
+ UINT8 mode = pAd->chipCap.FlgIsVcoReCalMode;
+
+ if (mode == VCO_CAL_DISABLE)
+ return;
+
+#ifdef RTMP_INTERNAL_TX_ALC
+#endif /* RTMP_INTERNAL_TX_ALC */
+
+ RTMP_IO_READ32(pAd, TX_PIN_CFG, &TxPinCfg);
+ TxPinCfg &= 0xFCFFFFF0;
+ RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
+
+ switch (mode)
+ {
+
+#ifdef RLT_RF
+ case VCO_CAL_MODE_3:
+
+ rlt_rf_write(pAd, RF_BANK0, RF_R04, 0x0A);
+ rlt_rf_write(pAd, RF_BANK0, RF_R05, 0x20);
+ rlt_rf_read(pAd, RF_BANK0, RF_R04, &RFValue);
+ RFValue = RFValue | 0x80; /* bit 7=vcocal_en*/
+ rlt_rf_write(pAd, RF_BANK0, RF_R04, RFValue);
+ break;
+#endif /* RLT_RF */
+
+ default:
+ return;
+ }
+
+ RtmpOsMsDelay(1);
+
+ RTMP_IO_READ32(pAd, TX_PIN_CFG, &TxPinCfg);
+ if (pAd->CommonCfg.Channel <= 14)
+ {
+ if (pAd->Antenna.field.TxPath == 1)
+ TxPinCfg |= 0x2;
+ else if (pAd->Antenna.field.TxPath == 2)
+ TxPinCfg |= 0xA;
+ else if (pAd->Antenna.field.TxPath == 3)
+ TxPinCfg |= 0x0200000A;
+ }
+ else
+ {
+ if (pAd->Antenna.field.TxPath == 1)
+ TxPinCfg |= 0x1;
+ else if (pAd->Antenna.field.TxPath == 2)
+ TxPinCfg |= 0x5;
+ else if (pAd->Antenna.field.TxPath == 3)
+ TxPinCfg |= 0x01000005;
+ }
+ RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
+
+#ifdef TXBF_SUPPORT
+ // Do a Divider Calibration and update BBP registers
+ if (pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn
+#ifdef DBG_CTRL_SUPPORT
+ && (pAd->CommonCfg.DebugFlags & DBF_DISABLE_CAL)==0
+#endif /* DBG_CTRL_SUPPORT */
+ )
+ {
+ ITxBFDividerCalibration(pAd, 2, 0, NULL);
+ }
+
+ if (pAd->CommonCfg.ETxBfEnCond)
+ {
+ INT idx;
+
+ for (idx = 1; idx < MAX_LEN_OF_MAC_TABLE; idx++)
+ {
+ MAC_TABLE_ENTRY *pEntry;
+
+ pEntry = &pAd->MacTab.Content[idx];
+ if ((IS_ENTRY_CLIENT(pEntry)) && (pEntry->eTxBfEnCond))
+ {
+ BOOLEAN Cancelled;
+
+ RTMPCancelTimer(&pEntry->eTxBfProbeTimer, &Cancelled);
+
+ pEntry->bfState = READY_FOR_SNDG0;
+ eTxBFProbing(pAd, pEntry);
+ }
+ }
+ }
+#endif // TXBF_SUPPORT //
+}
+#endif /* VCORECAL_SUPPORT */
+
+
+#ifdef STREAM_MODE_SUPPORT
+// StreamModeRegVal - return MAC reg value for StreamMode setting
+UINT32 StreamModeRegVal(
+ IN RTMP_ADAPTER *pAd)
+{
+ UINT32 streamWord;
+
+ switch (pAd->CommonCfg.StreamMode)
+ {
+ case 1:
+ streamWord = 0x030000;
+ break;
+ case 2:
+ streamWord = 0x0c0000;
+ break;
+ case 3:
+ streamWord = 0x0f0000;
+ break;
+ default:
+ streamWord = 0x0;
+ break;
+ }
+
+ return streamWord;
+}
+
+
+/*
+ ========================================================================
+ Description:
+ configure the stream mode of specific MAC or all MAC and set to ASIC.
+
+ Prameters:
+ pAd ---
+ pMacAddr ---
+ bClear --- disable the stream mode for specific macAddr when
+ (pMacAddr!=NULL)
+
+ Return:
+ ========================================================================
+*/
+VOID AsicSetStreamMode(
+ IN RTMP_ADAPTER *pAd,
+ IN PUCHAR pMacAddr,
+ IN INT chainIdx,
+ IN BOOLEAN bEnabled)
+{
+ UINT32 streamWord;
+ UINT32 regAddr, regVal;
+
+
+ if (!pAd->chipCap.FlgHwStreamMode)
+ return;
+
+ streamWord = StreamModeRegVal(pAd);
+ if (!bEnabled)
+ streamWord = 0;
+
+ regAddr = TX_CHAIN_ADDR0_L + chainIdx * 4;
+ RTMP_IO_WRITE32(pAd, regAddr,
+ (UINT32)(pMacAddr[0]) |
+ (UINT32)(pMacAddr[1] << 8) |
+ (UINT32)(pMacAddr[2] << 16) |
+ (UINT32)(pMacAddr[3] << 24));
+
+ RTMP_IO_READ32(pAd, regAddr + 4, &regVal);
+ regVal &= (~0x000f0000);
+ RTMP_IO_WRITE32(pAd, regAddr + 4,
+ (regVal | streamWord) |
+ (UINT32)(pMacAddr[4]) |
+ (UINT32)(pMacAddr[5] << 8));
+
+}
+
+
+VOID RtmpStreamModeInit(
+ IN RTMP_ADAPTER *pAd)
+{
+ int chainIdx;
+ UCHAR *pMacAddr;
+
+ if (pAd->chipCap.FlgHwStreamMode == FALSE)
+ return;
+
+ for (chainIdx = 0; chainIdx < STREAM_MODE_STA_NUM; chainIdx++)
+ {
+ pMacAddr = &pAd->CommonCfg.StreamModeMac[chainIdx][0];
+ AsicSetStreamMode(pAd, pMacAddr, chainIdx, TRUE);
+ }
+}
+#endif // STREAM_MODE_SUPPORT //
+
+
+#ifdef DOT11_N_SUPPORT
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicEnableRalinkBurstMode(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 Data = 0;
+
+ RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+ pAd->CommonCfg.RestoreBurstMode = Data;
+ Data &= 0xFFF00000;
+ Data |= 0x86380;
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicDisableRalinkBurstMode(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 Data = 0;
+
+ RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+
+ Data = pAd->CommonCfg.RestoreBurstMode;
+ Data &= 0xFFFFFF00;
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
+#ifdef DOT11_N_SUPPORT
+ && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
+#endif // DOT11_N_SUPPORT //
+ )
+ {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE))
+ Data |= 0x80;
+ else if (pAd->CommonCfg.bEnableTxBurst)
+ Data |= 0x20;
+ }
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+}
+#endif // DOT11_N_SUPPORT //
+
+
+#ifdef WOW_SUPPORT
+#ifdef RTMP_MAC_USB
+
+/* switch firmware
+ a) before into WOW mode, switch firmware to WOW-enable firmware
+ b) exit from WOW mode, switch firmware to normal firmware
+*/
+VOID AsicLoadWOWFirmware(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN WOW)
+{
+ if (WOW)
+ pAd->WOW_Cfg.bWOWFirmware = TRUE;
+ else
+ pAd->WOW_Cfg.bWOWFirmware = FALSE;
+
+ RtmpAsicLoadFirmware(pAd);
+}
+
+/* In WOW mode, 8051 mcu will send null frame, and pick data from 0x7780
+ * the null frame includes TxWI and 802.11 header */
+VOID AsicWOWSendNullFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR TxRate,
+ IN BOOLEAN bQosNull)
+{
+
+ TXWI_STRUC *TxWI;
+ PUCHAR NullFrame;
+ UINT8 packet_len;
+ PUCHAR ptr;
+ USHORT offset;
+ UINT32 cipher = pAd->StaCfg.GroupCipher;
+ UINT32 Value;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+
+ ComposeNullFrame(pAd);
+ TxWI = (TXWI_STRUC *)&pAd->NullContext[0].TransferBuffer->field.WirelessPacket[TXINFO_SIZE];
+ NullFrame = (PUCHAR)&pAd->NullFrame;
+ packet_len = TxWI->TxWIMPDUByteCnt;
+
+ DBGPRINT(RT_DEBUG_OFF, ("TxWI:\n"));
+ /* copy TxWI to MCU memory */
+ ptr = (PUCHAR)TxWI;
+ for (offset = 0; offset < TXWISize; offset += 4)
+ {
+ RTMPMoveMemory(&Value, ptr+offset, 4);
+ DBGPRINT(RT_DEBUG_OFF, ("offset: %02d %08x\n", offset, Value));
+ RTMP_IO_WRITE32(pAd, HW_NULL2_BASE + offset, Value);
+ }
+
+ DBGPRINT(RT_DEBUG_OFF, ("802.11 header:\n"));
+ /* copy 802.11 header to memory */
+ ptr = (PUCHAR)NullFrame;
+ for (offset = 0; offset < packet_len; offset += 4)
+ {
+ RTMPMoveMemory(&Value, ptr+offset, 4);
+ DBGPRINT(RT_DEBUG_OFF, ("offset: %02d %08x\n", offset, Value));
+ RTMP_IO_WRITE32(pAd, HW_NULL2_BASE + TXWISize + offset, Value);
+ }
+
+ DBGPRINT(RT_DEBUG_OFF, ("Write GroupCipher Mode: %d\n", pAd->StaCfg.GroupCipher));
+
+ RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &Value);
+
+ switch (cipher) /* don't care WEP, because it dosen't have re-key issue */
+ {
+ case Ndis802_11Encryption2Enabled: /* TKIP */
+ Value |= 0x0330;
+ RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, Value);
+ break;
+ case Ndis802_11Encryption3Enabled: /* AES */
+ Value |= 0x0440;
+ RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, Value);
+ break;
+ }
+}
+
+#endif /* RTMP_MAC_USB */
+#endif /* WOW_SUPPORT */
+
+
+INT AsicSetPreTbttInt(RTMP_ADAPTER *pAd, BOOLEAN enable)
+{
+ UINT32 val;
+
+ RTMP_IO_READ32(pAd, INT_TIMER_CFG, &val);
+ val &= 0xffff0000;
+ val |= 6 << 4; /* Pre-TBTT is 6ms before TBTT interrupt. 1~10 ms is reasonable. */
+ RTMP_IO_WRITE32(pAd, INT_TIMER_CFG, val);
+ /* Enable pre-tbtt interrupt */
+ RTMP_IO_READ32(pAd, INT_TIMER_EN, &val);
+ val |=0x1;
+ RTMP_IO_WRITE32(pAd, INT_TIMER_EN, val);
+
+ return TRUE;
+}
+
+
+BOOLEAN AsicWaitPDMAIdle(struct _RTMP_ADAPTER *pAd, INT round, INT wait_us)
+{
+ INT i = 0;
+ WPDMA_GLO_CFG_STRUC GloCfg;
+
+
+ do {
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
+ if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) {
+ DBGPRINT(RT_DEBUG_TRACE, ("==> DMAIdle, GloCfg=0x%x\n", GloCfg.word));
+ return TRUE;
+ }
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return FALSE;
+ RTMPusecDelay(wait_us);
+ }while ((i++) < round);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy, GloCfg=0x%x\n", GloCfg.word));
+
+ return FALSE;
+}
+
+
+#ifdef DOT11_N_SUPPORT
+#if defined(RT65xx) || defined(MT7601)
+#define MAX_AGG_CNT 32
+#elif defined(RT2883) || defined(RT3883)
+#define MAX_AGG_CNT 16
+#else
+#define MAX_AGG_CNT 8
+#endif
+INT AsicReadAggCnt(RTMP_ADAPTER *pAd, ULONG *aggCnt, int cnt_len)
+{
+ UINT32 reg_addr;
+ TX_AGG_CNT_STRUC reg_val;
+ int i, cnt, seg;
+ static USHORT aggReg[] = {
+ TX_AGG_CNT, TX_AGG_CNT3,
+#if MAX_AGG_CNT > 8
+ TX_AGG_CNT4, TX_AGG_CNT7,
+#endif
+#if MAX_AGG_CNT > 16
+ TX_AGG_CNT8, TX_AGG_CNT15,
+#endif
+ };
+
+
+ NdisZeroMemory(aggCnt, cnt_len * sizeof(ULONG));
+ seg = (sizeof(aggReg) /sizeof(USHORT));
+
+ cnt = 0;
+ for (i = 0; i < seg; i += 2)
+ {
+ for (reg_addr = aggReg[i] ; reg_addr <= aggReg[i+1] ; reg_addr += 4)
+ {
+ RTMP_IO_READ32(pAd, reg_addr, &reg_val.word);
+ if (cnt < (cnt_len -1)) {
+ aggCnt[cnt] = reg_val.field.AggCnt_x;
+ aggCnt[cnt+1] = reg_val.field.AggCnt_y;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():Get AggSize at Reg(0x%x) with val(0x%08x) [AGG_%d=>%ld, AGG_%d=>%ld]\n",
+ __FUNCTION__, reg_addr, reg_val.word, cnt, aggCnt[cnt], cnt+1, aggCnt[cnt+1]));
+ cnt += 2;
+ } else {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():Get AggSize at Reg(0x%x) failed, no enough buffer(cnt_len=%d, cnt=%d)\n",
+ __FUNCTION__, reg_addr, cnt_len, cnt));
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+#endif /* DOT11_N_SUPPORT */
+
+
+INT AsicSetChannel(RTMP_ADAPTER *pAd, UCHAR ch, UCHAR bw, UCHAR ext_ch, BOOLEAN bScan)
+{
+ rtmp_bbp_set_bw(pAd, bw);
+
+ /* Tx/RX : control channel setting */
+ rtmp_bbp_set_ctrlch(pAd, ext_ch);
+ rtmp_mac_set_ctrlch(pAd, ext_ch);
+
+ /* Let BBP register at 20MHz to do scan */
+ AsicSwitchChannel(pAd, ch, bScan);
+ AsicLockChannel(pAd, ch);
+
+#ifdef RT28xx
+ RT28xx_ch_tunning(pAd, bw);
+#endif /* RT28xx */
+
+ return 0;
+}
+
+
+#ifdef NEW_WOW_SUPPORT
+VOID RT28xxAndesWOWEnable(
+ IN PRTMP_ADAPTER pAd)
+{
+ NEW_WOW_MASK_CFG_STRUCT mask_cfg;
+ NEW_WOW_SEC_CFG_STRUCT sec_cfg;
+ NEW_WOW_INFRA_CFG_STRUCT infra_cfg;
+ NEW_WOW_P2P_CFG_STRUCT p2p_cfg;
+ NEW_WOW_PARAM_STRUCT wow_param;
+ struct CMD_UNIT CmdUnit;
+ RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
+ INT32 Ret;
+ MAC_TABLE_ENTRY *pEntry = NULL;
+
+
+ NdisZeroMemory(&CmdUnit, sizeof(CmdUnit));
+
+ /* WOW enable */
+ NdisZeroMemory(&wow_param, sizeof(wow_param));
+
+ wow_param.Parameter = WOW_ENABLE; /* WOW enable */
+ wow_param.Value = TRUE;
+
+ CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* feature enable */
+ CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT);
+ CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&wow_param;
+
+ Ret = AsicSendCmdToAndes(pAd, &CmdUnit);
+
+ if (Ret != NDIS_STATUS_SUCCESS)
+ {
+ printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__,
+ CmdUnit.u.ANDES.Type, wow_param.Parameter);
+ return;
+ }
+
+ RtmpOsMsDelay(1);
+ /* mask configuration */
+ NdisZeroMemory(&mask_cfg, sizeof(mask_cfg));
+
+ mask_cfg.Config_Type = WOW_MASK_CFG; /* detect mask config */
+ mask_cfg.Function_Enable = TRUE;
+ mask_cfg.Detect_Mask = 1UL << WOW_MAGIC_PKT; /* magic packet */
+ mask_cfg.Event_Mask = 0;
+
+ CmdUnit.u.ANDES.Type = CMD_WOW_CONFIG; /* WOW config */
+ CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_MASK_CFG_STRUCT);
+ CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&mask_cfg;
+
+ Ret = AsicSendCmdToAndes(pAd, &CmdUnit);
+
+ if (Ret != NDIS_STATUS_SUCCESS)
+ {
+ printk("\x1b[31m%s: send WOW config command failed!!(%d/%d)\x1b[m\n", __FUNCTION__,
+ CmdUnit.u.ANDES.Type, mask_cfg.Config_Type);
+ return;
+ }
+
+ RtmpOsMsDelay(1);
+
+ /* security configuration */
+ if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPAPSK)
+ {
+ NdisZeroMemory(&sec_cfg, sizeof(sec_cfg));
+
+ sec_cfg.Config_Type = WOW_SEC_CFG; /* security config */
+
+ if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK)
+ sec_cfg.WPA_Ver = 0;
+ else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
+ sec_cfg.WPA_Ver = 1;
+
+ pEntry = &pAd->MacTab.Content[BSSID_WCID];
+
+ NdisCopyMemory(sec_cfg.PTK, pEntry->PTK, 64);
+ NdisCopyMemory(sec_cfg.R_COUNTER, pEntry->R_Counter, LEN_KEY_DESC_REPLAY);
+
+ sec_cfg.Key_Id = pAd->StaCfg.DefaultKeyId;
+ sec_cfg.Cipher_Alg = pEntry->WepStatus;
+ printk("\x1b[31m%s: wep status %d\x1b[m\n", __FUNCTION__, pEntry->WepStatus);
+ sec_cfg.Group_Cipher = pAd->StaCfg.GroupCipher;
+ printk("\x1b[31m%s: group status %d\x1b[m\n", __FUNCTION__, sec_cfg.Group_Cipher);
+ printk("\x1b[31m%s: aid %d\x1b[m\n", __FUNCTION__, pEntry->Aid);
+ sec_cfg.WCID = BSSID_WCID;
+
+ CmdUnit.u.ANDES.Type = CMD_WOW_CONFIG; /* WOW config */
+ CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_SEC_CFG_STRUCT);
+ CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&sec_cfg;
+
+ Ret = AsicSendCmdToAndes(pAd, &CmdUnit);
+
+ if (Ret != NDIS_STATUS_SUCCESS)
+ {
+ printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__,
+ CmdUnit.u.ANDES.Type, sec_cfg.Config_Type);
+ return;
+ }
+
+ RtmpOsMsDelay(1);
+ }
+
+ /* Infra configuration */
+
+ NdisZeroMemory(&infra_cfg, sizeof(infra_cfg));
+
+ infra_cfg.Config_Type = WOW_INFRA_CFG; /* infra config */
+
+ COPY_MAC_ADDR(infra_cfg.STA_MAC, pAd->CurrentAddress);
+ COPY_MAC_ADDR(infra_cfg.AP_MAC, pAd->CommonCfg.Bssid);
+
+ CmdUnit.u.ANDES.Type = CMD_WOW_CONFIG; /* WOW config */
+ CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_INFRA_CFG_STRUCT);
+ CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&infra_cfg;
+
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ infra_cfg.AP_Status = TRUE;
+ else
+ infra_cfg.AP_Status = FALSE;
+
+ Ret = AsicSendCmdToAndes(pAd, &CmdUnit);
+
+ if (Ret != NDIS_STATUS_SUCCESS)
+ {
+ printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__,
+ CmdUnit.u.ANDES.Type, infra_cfg.Config_Type);
+ return;
+ }
+
+ RtmpOsMsDelay(1);
+
+
+ /* P2P configuration */
+
+ /* Wakeup Option */
+ NdisZeroMemory(&wow_param, sizeof(wow_param));
+
+ wow_param.Parameter = WOW_WAKEUP; /* Wakeup Option */
+ if (pAd->WOW_Cfg.bInBand)
+ {
+ wow_param.Value = WOW_WAKEUP_BY_USB;
+ }
+ else
+ {
+ INT32 Value;
+
+ wow_param.Value = WOW_WAKEUP_BY_GPIO;
+
+ RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &Value);
+ printk("\x1b[31m%s: 0x80 = %x\x1b[m\n", __FUNCTION__, Value);
+ Value &= ~0x01010000; /* GPIO0(ouput) --> 0(data) */
+ RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, Value);
+ }
+
+ CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* feature enable */
+ CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT);
+ CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&wow_param;
+
+ Ret = AsicSendCmdToAndes(pAd, &CmdUnit);
+
+ if (Ret != NDIS_STATUS_SUCCESS)
+ {
+ printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__,
+ CmdUnit.u.ANDES.Type, wow_param.Parameter);
+ return;
+ }
+
+ RtmpOsMsDelay(1);
+
+
+ /* traffic to Andes */
+ NdisZeroMemory(&wow_param, sizeof(wow_param));
+ wow_param.Parameter = WOW_TRAFFIC; /* Traffic switch */
+ wow_param.Value = WOW_PKT_TO_ANDES; /* incoming packet to FW */
+
+ CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* feature enable */
+ CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT);
+ CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&wow_param.Parameter;
+
+ Ret = AsicSendCmdToAndes(pAd, &CmdUnit);
+
+ if (Ret != NDIS_STATUS_SUCCESS)
+ {
+ printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__,
+ CmdUnit.u.ANDES.Type, wow_param.Parameter);
+ return;
+ }
+
+ RtmpOsMsDelay(1);
+
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
+}
+
+VOID RT28xxAndesWOWDisable(
+ IN PRTMP_ADAPTER pAd)
+{
+ NEW_WOW_PARAM_STRUCT param;
+ struct CMD_UNIT CmdUnit;
+ RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
+ INT32 Ret;
+ UINT32 Value;
+ MAC_TABLE_ENTRY *pEntry = NULL;
+
+ printk("\x1b[31m%s: ...\x1b[m", __FUNCTION__);
+
+ /* clean BulkIn Reset flag */
+ //pAd->Flags &= ~0x80000;
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
+
+ NdisZeroMemory(&CmdUnit, sizeof(CmdUnit));
+
+ /* WOW disable */
+ NdisZeroMemory(&param, sizeof(param));
+ param.Parameter = WOW_ENABLE;
+ param.Value = FALSE;
+
+ CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* WOW enable */
+ CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT);
+ CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&param;
+
+ Ret = AsicSendCmdToAndes(pAd, &CmdUnit);
+
+ if (Ret != NDIS_STATUS_SUCCESS)
+ {
+ printk("\x1b[31m%s: send WOW config command failed!!\x1b[m\n", __FUNCTION__);
+ return;
+ }
+
+ RtmpOsMsDelay(1);
+
+
+ /* traffic to Host */
+ NdisZeroMemory(&param, sizeof(param));
+ param.Parameter = WOW_TRAFFIC;
+ param.Value = WOW_PKT_TO_HOST;
+
+ CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE;
+ CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT);
+ CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&param;
+
+ Ret = AsicSendCmdToAndes(pAd, &CmdUnit);
+
+ if (Ret != NDIS_STATUS_SUCCESS)
+ {
+ printk("\x1b[31m%s: send WOW config command failed!!\x1b[m\n", __FUNCTION__);
+ return;
+ }
+
+ RtmpOsMsDelay(1);
+
+
+ /* Restore MAC TX/RX */
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value |= 0xC;
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+
+ RTUSBBulkReceive(pAd);
+ RTUSBBulkCmdRspEventReceive(pAd);
+
+ //printk("\x1b[31m%s: pendingRx %d\x1b[m\n", __FUNCTION__, pAd->PendingRx);
+ //printk("\x1b[31m%s: BulkInReq %d\x1b[m\n", __FUNCTION__, pAd->BulkInReq);
+
+ /* restore hardware remote wakeup flag */
+ RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &Value);
+ printk("\x1b[31m%s: 0x80 %08x\x1b[m\n", __FUNCTION__, Value);
+ Value &= ~0x80;
+ RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, Value);
+
+ if (pAd->WOW_Cfg.bInBand == FALSE)
+ {
+ INT32 Value;
+
+ RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &Value);
+ printk("\x1b[31m%s: 0x80 = %x\x1b[m\n", __FUNCTION__, Value);
+ Value &= ~0x01010000; /* GPIO0(ouput) --> 0(data) */
+ RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, Value);
+ }
+}
+
+#endif /* NEW_WOW_SUPPORT */
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_cfg.c b/cleopatre/devkit/mt7601udrv/common/cmm_cfg.c
new file mode 100644
index 0000000000..5bd9773cdf
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_cfg.c
@@ -0,0 +1,1494 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ****************************************************************************
+
+ Module Name:
+ cmm_cfg.c
+
+ Abstract:
+ Ralink WiFi Driver configuration related subroutines
+
+ Revision History:
+ Who When What
+ --------- ---------- ----------------------------------------------
+*/
+
+
+
+#include "rt_config.h"
+#ifdef DOT11_N_SUPPORT
+#if defined(RT65xx) || defined(MT7601)
+#define MAX_AGG_CNT 32
+#elif defined(RT2883) || defined(RT3883)
+#define MAX_AGG_CNT 16
+#else
+#define MAX_AGG_CNT 8
+#endif
+/* DisplayTxAgg - display Aggregation statistics from MAC */
+void DisplayTxAgg (RTMP_ADAPTER *pAd)
+{
+ ULONG totalCount;
+ ULONG aggCnt[MAX_AGG_CNT + 2];
+ int i;
+
+ AsicReadAggCnt(pAd, aggCnt, sizeof(aggCnt) / sizeof(ULONG));
+ totalCount = aggCnt[0] + aggCnt[1];
+ if (totalCount > 0)
+ for (i=0; i<MAX_AGG_CNT; i++) {
+ DBGPRINT(RT_DEBUG_OFF, ("\t%d MPDU=%ld (%ld%%)\n", i+1, aggCnt[i+2], aggCnt[i+2]*100/totalCount));
+ }
+ printk("====================\n");
+
+}
+#endif /* DOT11_N_SUPPORT */
+
+static BOOLEAN RT_isLegalCmdBeforeInfUp(
+ IN PSTRING SetCmd);
+
+
+INT ComputeChecksum(
+ IN UINT PIN)
+{
+ INT digit_s;
+ UINT accum = 0;
+
+ PIN *= 10;
+ accum += 3 * ((PIN / 10000000) % 10);
+ accum += 1 * ((PIN / 1000000) % 10);
+ accum += 3 * ((PIN / 100000) % 10);
+ accum += 1 * ((PIN / 10000) % 10);
+ accum += 3 * ((PIN / 1000) % 10);
+ accum += 1 * ((PIN / 100) % 10);
+ accum += 3 * ((PIN / 10) % 10);
+
+ digit_s = (accum % 10);
+ return ((10 - digit_s) % 10);
+} /* ComputeChecksum*/
+
+UINT GenerateWpsPinCode(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bFromApcli,
+ IN UCHAR apidx)
+{
+ UCHAR macAddr[MAC_ADDR_LEN];
+ UINT iPin;
+ UINT checksum;
+
+ NdisZeroMemory(macAddr, MAC_ADDR_LEN);
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (bFromApcli)
+ NdisMoveMemory(&macAddr[0], pAd->ApCfg.ApCliTab[apidx].CurrentAddress, MAC_ADDR_LEN);
+ else
+#endif /* APCLI_SUPPORT */
+ NdisMoveMemory(&macAddr[0], pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ iPin = macAddr[3] * 256 * 256 + macAddr[4] * 256 + macAddr[5];
+
+ iPin = iPin % 10000000;
+
+
+ checksum = ComputeChecksum( iPin );
+ iPin = iPin*10 + checksum;
+
+ return iPin;
+}
+
+
+static char *phy_mode_str[]={"CCK", "OFDM", "HTMIX", "GF", "VHT"};
+char* get_phymode_str(int Mode)
+{
+ if (Mode >= MODE_CCK && Mode <= MODE_VHT)
+ return phy_mode_str[Mode];
+ else
+ return "N/A";
+}
+
+
+static UCHAR *phy_bw_str[] = {"20M", "40M", "80M", "10M"};
+char* get_bw_str(int bandwidth)
+{
+ if (bandwidth >= BW_20 && bandwidth <= BW_10)
+ return phy_bw_str[bandwidth];
+ else
+ return "N/A";
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Set Country Region to pAd->CommonCfg.CountryRegion.
+ This command will not work, if the field of CountryRegion in eeprom is programmed.
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT RT_CfgSetCountryRegion(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg,
+ IN INT band)
+{
+ LONG region;
+ UCHAR *pCountryRegion;
+
+ region = simple_strtol(arg, 0, 10);
+
+ if (band == BAND_24G)
+ pCountryRegion = &pAd->CommonCfg.CountryRegion;
+ else
+ pCountryRegion = &pAd->CommonCfg.CountryRegionForABand;
+
+ /*
+ 1. If this value is set before interface up, do not reject this value.
+ 2. Country can be set only when EEPROM not programmed
+ */
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE) && (*pCountryRegion & EEPROM_IS_PROGRAMMED))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("CfgSetCountryRegion():CountryRegion in eeprom was programmed\n"));
+ return FALSE;
+ }
+
+ if((region >= 0) &&
+ (((band == BAND_24G) &&((region <= REGION_MAXIMUM_BG_BAND) ||
+ (region == REGION_31_BG_BAND) || (region == REGION_32_BG_BAND) || (region == REGION_33_BG_BAND) )) ||
+ ((band == BAND_5G) && (region <= REGION_MAXIMUM_A_BAND) ))
+ )
+ {
+ *pCountryRegion= (UCHAR) region;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("CfgSetCountryRegion():region(%ld) out of range!\n", region));
+ return FALSE;
+ }
+
+ return TRUE;
+
+}
+
+
+static UCHAR CFG_WMODE_MAP[]={
+ PHY_11BG_MIXED, (WMODE_B | WMODE_G), /* 0 => B/G mixed */
+ PHY_11B, (WMODE_B), /* 1 => B only */
+ PHY_11A, (WMODE_A), /* 2 => A only */
+ PHY_11ABG_MIXED, (WMODE_A | WMODE_B | WMODE_G), /* 3 => A/B/G mixed */
+ PHY_11G, WMODE_G, /* 4 => G only */
+ PHY_11ABGN_MIXED, (WMODE_B | WMODE_G | WMODE_GN | WMODE_A | WMODE_AN), /* 5 => A/B/G/GN/AN mixed */
+ PHY_11N_2_4G, (WMODE_GN), /* 6 => N in 2.4G band only */
+ PHY_11GN_MIXED, (WMODE_G | WMODE_GN), /* 7 => G/GN, i.e., no CCK mode */
+ PHY_11AN_MIXED, (WMODE_A | WMODE_AN), /* 8 => A/N in 5 band */
+ PHY_11BGN_MIXED, (WMODE_B | WMODE_G | WMODE_GN), /* 9 => B/G/GN mode*/
+ PHY_11AGN_MIXED, (WMODE_G | WMODE_GN | WMODE_A | WMODE_AN), /* 10 => A/AN/G/GN mode, not support B mode */
+ PHY_11N_5G, (WMODE_AN), /* 11 => only N in 5G band */
+#ifdef DOT11_VHT_AC
+ PHY_11VHT_N_ABG_MIXED, (WMODE_B | WMODE_G | WMODE_GN |WMODE_A | WMODE_AN | WMODE_AC), /* 12 => B/G/GN/A/AN/AC mixed*/
+ PHY_11VHT_N_AG_MIXED, (WMODE_G | WMODE_GN |WMODE_A | WMODE_AN | WMODE_AC), /* 13 => G/GN/A/AN/AC mixed , no B mode */
+ PHY_11VHT_N_A_MIXED, (WMODE_A | WMODE_AN | WMODE_AC), /* 14 => A/AC/AN mixed */
+ PHY_11VHT_N_MIXED, (WMODE_AN | WMODE_AC), /* 15 => AC/AN mixed, but no A mode */
+#endif /* DOT11_VHT_AC */
+ PHY_MODE_MAX, WMODE_INVALID /* default phy mode if not match */
+};
+
+
+static PSTRING BAND_STR[] = {"Invalid", "2.4G", "5G", "2.4G/5G"};
+static PSTRING WMODE_STR[]= {"", "A", "B", "G", "gN", "aN", "AC"};
+
+UCHAR *wmode_2_str(UCHAR wmode)
+{
+ UCHAR *str;
+ INT idx, pos, max_len;
+
+ max_len = WMODE_COMP * 3;
+ if (os_alloc_mem(NULL, &str, max_len) == NDIS_STATUS_SUCCESS)
+ {
+ NdisZeroMemory(str, max_len);
+ pos = 0;
+ for (idx = 0; idx < WMODE_COMP; idx++)
+ {
+ if (wmode & (1 << idx)) {
+ if ((strlen(str) + strlen(WMODE_STR[idx + 1])) >= (max_len - 1))
+ break;
+ if (strlen(str)) {
+ NdisMoveMemory(&str[pos], "/", 1);
+ pos++;
+ }
+ NdisMoveMemory(&str[pos], WMODE_STR[idx + 1], strlen(WMODE_STR[idx + 1]));
+ pos += strlen(WMODE_STR[idx + 1]);
+ }
+ if (strlen(str) >= max_len)
+ break;
+ }
+
+ return str;
+ }
+ else
+ return NULL;
+}
+
+
+UCHAR cfgmode_2_wmode(UCHAR cfg_mode)
+{
+ DBGPRINT(RT_DEBUG_OFF, ("cfg_mode=%d\n", cfg_mode));
+ if (cfg_mode >= PHY_MODE_MAX)
+ cfg_mode = PHY_MODE_MAX;
+
+ return CFG_WMODE_MAP[cfg_mode * 2 + 1];
+}
+
+
+UCHAR wmode_2_cfgmode(UCHAR wmode)
+{
+ INT index;
+ DBGPRINT(RT_DEBUG_OFF, ("wmode=%d\n", wmode));
+
+ for (index = 0; index < PHY_MODE_MAX; index++ )
+ {
+ if ( wmode == CFG_WMODE_MAP[index*2 + 1])
+ return CFG_WMODE_MAP[index*2];
+ }
+
+ return PHY_11ABGN_MIXED;
+}
+
+
+static BOOLEAN wmode_valid(RTMP_ADAPTER *pAd, enum WIFI_MODE wmode)
+{
+ if ((WMODE_CAP_5G(wmode) && (!PHY_CAP_5G(pAd->chipCap.phy_caps))) ||
+ (WMODE_CAP_2G(wmode) && (!PHY_CAP_2G(pAd->chipCap.phy_caps))) ||
+ (WMODE_CAP_N(wmode) && RTMP_TEST_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DOT_11N))
+ )
+ return FALSE;
+ else
+ return TRUE;
+}
+
+
+static BOOLEAN wmode_valid_and_correct(RTMP_ADAPTER *pAd, UCHAR* wmode)
+{
+ BOOLEAN ret = TRUE;
+ UCHAR mode = *wmode;
+
+ if (WMODE_CAP_5G(*wmode) && (!PHY_CAP_5G(pAd->chipCap.phy_caps)))
+ {
+ *wmode = *wmode & ~(WMODE_A | WMODE_AN | WMODE_AC);
+ }
+ else if (WMODE_CAP_2G(*wmode) && (!PHY_CAP_2G(pAd->chipCap.phy_caps)))
+ {
+ *wmode = *wmode & ~(WMODE_B | WMODE_G | WMODE_GN);
+ }
+ else if (WMODE_CAP_N(*wmode) && RTMP_TEST_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DOT_11N))
+ {
+ *wmode = *wmode & ~(WMODE_GN | WMODE_AN);
+ }
+
+ if ( *wmode == 0 )
+ ret = FALSE;
+
+ return ret;
+}
+
+
+BOOLEAN wmode_band_equal(UCHAR smode, UCHAR tmode)
+{
+ BOOLEAN eq = FALSE;
+ UCHAR *str1, *str2;
+
+ if ((WMODE_CAP_5G(smode) == WMODE_CAP_5G(tmode)) &&
+ (WMODE_CAP_2G(smode) == WMODE_CAP_2G(tmode)))
+ eq = TRUE;
+
+ str1 = wmode_2_str(smode);
+ str2 = wmode_2_str(tmode);
+ if (str1 && str2)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("Old WirelessMode:%s(0x%x), "
+ "New WirelessMode:%s(0x%x)!\n",
+ str1, smode, str2, tmode));
+ }
+ if (str1)
+ os_free_mem(NULL, str1);
+ if (str2)
+ os_free_mem(NULL, str2);
+
+ return eq;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Set Wireless Mode
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT RT_CfgSetWirelessMode(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ LONG cfg_mode;
+ UCHAR wmode, *mode_str;
+
+
+ cfg_mode = simple_strtol(arg, 0, 10);
+
+ /* check if chip support 5G band when WirelessMode is 5G band */
+ wmode = cfgmode_2_wmode((UCHAR)cfg_mode);
+ if ((wmode == WMODE_INVALID) || (!wmode_valid_and_correct(pAd, &wmode))) {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("%s(): Invalid wireless mode(%ld), ChipCap(%s)\n",
+ __FUNCTION__, cfg_mode,
+ BAND_STR[pAd->chipCap.phy_caps & 0x3]));
+ return FALSE;
+ }
+
+ if (wmode_band_equal(pAd->CommonCfg.PhyMode, wmode) == TRUE)
+ DBGPRINT(RT_DEBUG_OFF, ("wmode_band_equal(): Band Equal!\n"));
+ else
+ DBGPRINT(RT_DEBUG_OFF, ("wmode_band_equal(): Band Not Equal!\n"));
+
+ pAd->CommonCfg.PhyMode = wmode;
+ pAd->CommonCfg.cfg_wmode = wmode;
+
+ mode_str = wmode_2_str(wmode);
+ if (mode_str)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): Set WMODE=%s(0x%x)\n",
+ __FUNCTION__, mode_str, wmode));
+ os_free_mem(NULL, mode_str);
+ }
+
+ return TRUE;
+}
+
+
+/* maybe can be moved to GPL code, ap_mbss.c, but the code will be open */
+#ifdef CONFIG_AP_SUPPORT
+#ifdef MBSS_SUPPORT
+static UCHAR RT_CfgMbssWirelessModeMaxGet(RTMP_ADAPTER *pAd)
+{
+ UCHAR wmode = 0, *mode_str;
+ INT idx;
+ MULTISSID_STRUCT *wdev;
+
+ for(idx = 0; idx < pAd->ApCfg.BssidNum; idx++) {
+ wdev = &pAd->ApCfg.MBSSID[idx];
+ mode_str = wmode_2_str(wdev->PhyMode);
+ if (mode_str)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(BSS%d): wmode=%s(0x%x)\n",
+ __FUNCTION__, idx, mode_str, wdev->PhyMode));
+ os_free_mem(pAd, mode_str);
+ }
+ wmode |= wdev->PhyMode;
+ }
+
+ mode_str = wmode_2_str(wmode);
+ if (mode_str)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): Combined WirelessMode = %s(0x%x)\n",
+ __FUNCTION__, mode_str, wmode));
+ os_free_mem(pAd, mode_str);
+ }
+ return wmode;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Set Wireless Mode for MBSS
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT RT_CfgSetMbssWirelessMode(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ LONG cfg_mode;
+ UCHAR wmode;
+
+
+ cfg_mode = simple_strtol(arg, 0, 10);
+
+ wmode = cfgmode_2_wmode((UCHAR)cfg_mode);
+ if ((wmode == WMODE_INVALID) || (!wmode_valid(pAd, wmode))) {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("%s(): Invalid wireless mode(%d, wmode=0x%x), ChipCap(%s)\n",
+ __FUNCTION__, cfg_mode, wmode,
+ BAND_STR[pAd->chipCap.phy_caps & 0x3]));
+ return FALSE;
+ }
+
+ if (WMODE_CAP_5G(wmode) && WMODE_CAP_2G(wmode))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("AP cannot support 2.4G/5G band mxied mode!\n"));
+ return FALSE;
+ }
+
+ if (pAd->ApCfg.BssidNum > 1)
+ {
+ /* pAd->CommonCfg.PhyMode = maximum capability of all MBSS */
+ if (wmode_band_equal(pAd->CommonCfg.PhyMode, wmode) == TRUE)
+ {
+ wmode = RT_CfgMbssWirelessModeMaxGet(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("mbss> Maximum phy mode = %d!\n", wmode));
+ }
+ else
+ {
+ UINT32 IdBss;
+
+ /* replace all phy mode with the one with different band */
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("mbss> Different band with the current one!\n"));
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("mbss> Reset band of all BSS to the new one!\n"));
+
+ for(IdBss=0; IdBss<pAd->ApCfg.BssidNum; IdBss++)
+ pAd->ApCfg.MBSSID[IdBss].PhyMode = wmode;
+ }
+ }
+
+ pAd->CommonCfg.PhyMode = wmode;
+ pAd->CommonCfg.cfg_wmode = wmode;
+ return TRUE;
+}
+#endif /* MBSS_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+static BOOLEAN RT_isLegalCmdBeforeInfUp(
+ IN PSTRING SetCmd)
+{
+ BOOLEAN TestFlag;
+ TestFlag = !strcmp(SetCmd, "Debug") ||
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+ !strcmp(SetCmd, "OpMode") ||
+#endif /* CONFIG_APSTA_MIXED_SUPPORT */
+#ifdef EXT_BUILD_CHANNEL_LIST
+ !strcmp(SetCmd, "CountryCode") ||
+ !strcmp(SetCmd, "DfsType") ||
+ !strcmp(SetCmd, "ChannelListAdd") ||
+ !strcmp(SetCmd, "ChannelListShow") ||
+ !strcmp(SetCmd, "ChannelListDel") ||
+#endif /* EXT_BUILD_CHANNEL_LIST */
+#ifdef SINGLE_SKU
+ !strcmp(SetCmd, "ModuleTxpower") ||
+#endif /* SINGLE_SKU */
+ FALSE; /* default */
+ return TestFlag;
+}
+
+
+INT RT_CfgSetShortSlot(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ LONG ShortSlot;
+
+ ShortSlot = simple_strtol(arg, 0, 10);
+
+ if (ShortSlot == 1)
+ pAd->CommonCfg.bUseShortSlotTime = TRUE;
+ else if (ShortSlot == 0)
+ pAd->CommonCfg.bUseShortSlotTime = FALSE;
+ else
+ return FALSE; /*Invalid argument */
+
+ return TRUE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Set WEP KEY base on KeyIdx
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT RT_CfgSetWepKey(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING keyString,
+ IN CIPHER_KEY *pSharedKey,
+ IN INT keyIdx)
+{
+ INT KeyLen;
+ INT i;
+ /*UCHAR CipherAlg = CIPHER_NONE;*/
+ BOOLEAN bKeyIsHex = FALSE;
+
+ /* TODO: Shall we do memset for the original key info??*/
+ memset(pSharedKey, 0, sizeof(CIPHER_KEY));
+ KeyLen = strlen(keyString);
+ switch (KeyLen)
+ {
+ case 5: /*wep 40 Ascii type*/
+ case 13: /*wep 104 Ascii type*/
+ bKeyIsHex = FALSE;
+ pSharedKey->KeyLen = KeyLen;
+ NdisMoveMemory(pSharedKey->Key, keyString, KeyLen);
+ break;
+
+ case 10: /*wep 40 Hex type*/
+ case 26: /*wep 104 Hex type*/
+ for(i=0; i < KeyLen; i++)
+ {
+ if( !isxdigit(*(keyString+i)) )
+ return FALSE; /*Not Hex value;*/
+ }
+ bKeyIsHex = TRUE;
+ pSharedKey->KeyLen = KeyLen/2 ;
+ AtoH(keyString, pSharedKey->Key, pSharedKey->KeyLen);
+ break;
+
+ default: /*Invalid argument */
+ DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetWepKey(keyIdx=%d):Invalid argument (arg=%s)\n", keyIdx, keyString));
+ return FALSE;
+ }
+
+ pSharedKey->CipherAlg = ((KeyLen % 5) ? CIPHER_WEP128 : CIPHER_WEP64);
+ DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetWepKey:(KeyIdx=%d,type=%s, Alg=%s)\n",
+ keyIdx, (bKeyIsHex == FALSE ? "Ascii" : "Hex"), CipherName[pSharedKey->CipherAlg]));
+
+ return TRUE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Set WPA PSK key
+
+ Arguments:
+ pAdapter Pointer to our adapter
+ keyString WPA pre-shared key string
+ pHashStr String used for password hash function
+ hashStrLen Lenght of the hash string
+ pPMKBuf Output buffer of WPAPSK key
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT RT_CfgSetWPAPSKKey(
+ IN RTMP_ADAPTER *pAd,
+ IN PSTRING keyString,
+ IN INT keyStringLen,
+ IN UCHAR *pHashStr,
+ IN INT hashStrLen,
+ OUT PUCHAR pPMKBuf)
+{
+ UCHAR keyMaterial[40];
+
+ if ((keyStringLen < 8) || (keyStringLen > 64))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WPAPSK Key length(%d) error, required 8 ~ 64 characters!(keyStr=%s)\n",
+ keyStringLen, keyString));
+ return FALSE;
+ }
+
+ NdisZeroMemory(pPMKBuf, 32);
+ if (keyStringLen == 64)
+ {
+ AtoH(keyString, pPMKBuf, 32);
+ }
+ else
+ {
+ RtmpPasswordHash(keyString, pHashStr, hashStrLen, keyMaterial);
+ NdisMoveMemory(pPMKBuf, keyMaterial, 32);
+ }
+
+ return TRUE;
+}
+
+INT RT_CfgSetFixedTxPhyMode(PSTRING arg)
+{
+ INT fix_tx_mode = FIXED_TXMODE_HT;
+ ULONG value;
+
+
+ if (rtstrcasecmp(arg, "OFDM") == TRUE)
+ fix_tx_mode = FIXED_TXMODE_OFDM;
+ else if (rtstrcasecmp(arg, "CCK") == TRUE)
+ fix_tx_mode = FIXED_TXMODE_CCK;
+ else if (rtstrcasecmp(arg, "HT") == TRUE)
+ fix_tx_mode = FIXED_TXMODE_HT;
+ else if (rtstrcasecmp(arg, "VHT") == TRUE)
+ fix_tx_mode = FIXED_TXMODE_VHT;
+ else
+ {
+ value = simple_strtol(arg, 0, 10);
+ switch (value)
+ {
+ case FIXED_TXMODE_CCK:
+ case FIXED_TXMODE_OFDM:
+ case FIXED_TXMODE_HT:
+ case FIXED_TXMODE_VHT:
+ fix_tx_mode = value;
+ default:
+ fix_tx_mode = FIXED_TXMODE_HT;
+ }
+ }
+
+ return fix_tx_mode;
+
+}
+
+INT RT_CfgSetMacAddress(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ INT i, mac_len;
+
+ /* Mac address acceptable format 01:02:03:04:05:06 length 17 */
+ mac_len = strlen(arg);
+ if(mac_len != 17)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : invalid length (%d)\n", __FUNCTION__, mac_len));
+ return FALSE;
+ }
+
+ if(strcmp(arg, "00:00:00:00:00:00") == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : invalid mac setting \n", __FUNCTION__));
+ return FALSE;
+ }
+
+ for (i = 0; i < MAC_ADDR_LEN; i++)
+ {
+ AtoH(arg, &pAd->CurrentAddress[i], 1);
+ arg = arg + 3;
+ }
+
+ pAd->bLocalAdminMAC = TRUE;
+ return TRUE;
+}
+
+INT RT_CfgSetTxMCSProc(PSTRING arg, BOOLEAN *pAutoRate)
+{
+ INT Value = simple_strtol(arg, 0, 10);
+ INT TxMcs;
+
+ if ((Value >= 0 && Value <= 23) || (Value == 32)) /* 3*3*/
+ {
+ TxMcs = Value;
+ *pAutoRate = FALSE;
+ }
+ else
+ {
+ TxMcs = MCS_AUTO;
+ *pAutoRate = TRUE;
+ }
+
+ return TxMcs;
+
+}
+
+INT RT_CfgSetAutoFallBack(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ TX_RTY_CFG_STRUC tx_rty_cfg;
+ UCHAR AutoFallBack = (UCHAR)simple_strtol(arg, 0, 10);
+
+ RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word);
+ tx_rty_cfg.field.TxautoFBEnable = (AutoFallBack) ? 1 : 0;
+ RTMP_IO_WRITE32(pAd, TX_RTY_CFG, tx_rty_cfg.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetAutoFallBack::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word));
+ return TRUE;
+}
+
+#ifdef WSC_INCLUDED
+INT RT_CfgSetWscPinCode(
+ IN RTMP_ADAPTER *pAd,
+ IN PSTRING pPinCodeStr,
+ OUT PWSC_CTRL pWscControl)
+{
+ UINT pinCode;
+
+ pinCode = (UINT) simple_strtol(pPinCodeStr, 0, 10); /* When PinCode is 03571361, return value is 3571361.*/
+ if (strlen(pPinCodeStr) == 4)
+ {
+ pWscControl->WscEnrolleePinCode = pinCode;
+ pWscControl->WscEnrolleePinCodeLen = 4;
+ }
+ else if ( ValidateChecksum(pinCode) )
+ {
+ pWscControl->WscEnrolleePinCode = pinCode;
+ pWscControl->WscEnrolleePinCodeLen = 8;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RT_CfgSetWscPinCode(): invalid Wsc PinCode (%d)\n", pinCode));
+ return FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetWscPinCode():Wsc PinCode=%d\n", pinCode));
+
+ return TRUE;
+
+}
+#endif /* WSC_INCLUDED */
+
+/*
+========================================================================
+Routine Description:
+ Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWNAME.
+
+Arguments:
+ pAd - WLAN control block pointer
+ *pData - the communication data pointer
+ Data - the communication data
+
+Return Value:
+ NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE
+
+Note:
+========================================================================
+*/
+INT RtmpIoctl_rt_ioctl_giwname(
+ IN RTMP_ADAPTER *pAd,
+ IN VOID *pData,
+ IN ULONG Data)
+{
+ UCHAR CurOpMode = OPMODE_AP;
+
+ if (CurOpMode == OPMODE_AP)
+ {
+ strcpy(pData, "RTWIFI SoftAP");
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+INT RTMP_COM_IoctlHandle(
+ IN VOID *pAdSrc,
+ IN RTMP_IOCTL_INPUT_STRUCT *wrq,
+ IN INT cmd,
+ IN USHORT subcmd,
+ IN VOID *pData,
+ IN ULONG Data)
+{
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc;
+ POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
+ INT Status = NDIS_STATUS_SUCCESS, i;
+ UCHAR PermanentAddress[MAC_ADDR_LEN];
+ USHORT Addr01, Addr23, Addr45;
+
+
+ pObj = pObj; /* avoid compile warning */
+
+ switch(cmd)
+ {
+ case CMD_RTPRIV_IOCTL_NETDEV_GET:
+ /* get main net_dev */
+ {
+ VOID **ppNetDev = (VOID **)pData;
+ *ppNetDev = (VOID *)(pAd->net_dev);
+ }
+ break;
+
+ case CMD_RTPRIV_IOCTL_NETDEV_SET:
+ /* set main net_dev */
+ pAd->net_dev = pData;
+
+#ifdef CONFIG_AP_SUPPORT
+ pAd->ApCfg.MBSSID[MAIN_MBSSID].MSSIDDev = pData;
+#endif /* CONFIG_AP_SUPPORT */
+ break;
+
+ case CMD_RTPRIV_IOCTL_OPMODE_GET:
+ /* get Operation Mode */
+ *(ULONG *)pData = pAd->OpMode;
+ break;
+
+
+ case CMD_RTPRIV_IOCTL_TASK_LIST_GET:
+ /* get all Tasks */
+ {
+ RT_CMD_WAIT_QUEUE_LIST *pList = (RT_CMD_WAIT_QUEUE_LIST *)pData;
+
+ pList->pMlmeTask = &pAd->mlmeTask;
+#ifdef RTMP_TIMER_TASK_SUPPORT
+ pList->pTimerTask = &pAd->timerTask;
+#endif /* RTMP_TIMER_TASK_SUPPORT */
+ pList->pCmdQTask = &pAd->cmdQTask;
+#ifdef WSC_INCLUDED
+ pList->pWscTask = &pAd->wscTask;
+#endif /* WSC_INCLUDED */
+ }
+ break;
+
+ case CMD_RTPRIV_IOCTL_IRQ_INIT:
+ /* init IRQ */
+ RTMP_IRQ_INIT(pAd);
+ break;
+
+ case CMD_RTPRIV_IOCTL_IRQ_RELEASE:
+ /* release IRQ */
+ RTMP_OS_IRQ_RELEASE(pAd, pAd->net_dev);
+ break;
+
+
+ case CMD_RTPRIV_IOCTL_NIC_NOT_EXIST:
+ /* set driver state to fRTMP_ADAPTER_NIC_NOT_EXIST */
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
+ break;
+
+ case CMD_RTPRIV_IOCTL_MCU_SLEEP_CLEAR:
+ RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_MCU_SLEEP);
+ break;
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+ case CMD_RTPRIV_IOCTL_MAX_IN_BIT:
+ /* set MAX_IN_BIT for WMM */
+ CW_MAX_IN_BITS = Data;
+ break;
+#endif /* CONFIG_APSTA_MIXED_SUPPORT */
+
+ case CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_SET:
+ /* set driver state to fRTMP_ADAPTER_SUSPEND */
+ RTMP_SET_FLAG(pAd,fRTMP_ADAPTER_SUSPEND);
+ break;
+
+ case CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_CLEAR:
+ /* clear driver state to fRTMP_ADAPTER_SUSPEND */
+ RTMP_CLEAR_FLAG(pAd,fRTMP_ADAPTER_SUSPEND);
+ break;
+
+ case CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_OFF:
+ /* RT28xxUsbAsicRadioOff */
+ //RT28xxUsbAsicRadioOff(pAd);
+ ASIC_RADIO_OFF(pAd, SUSPEND_RADIO_OFF);
+ break;
+
+ case CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_ON:
+ /* RT28xxUsbAsicRadioOn */
+ //RT28xxUsbAsicRadioOn(pAd);
+ ASIC_RADIO_ON(pAd, RESUME_RADIO_ON);
+ break;
+
+ case CMD_RTPRIV_IOCTL_SANITY_CHECK:
+ /* sanity check before IOCTL */
+ if ((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+#ifdef IFUP_IN_PROBE
+ || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))
+ || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
+ || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+#endif /* IFUP_IN_PROBE */
+ )
+ {
+ if(pData == NULL || RT_isLegalCmdBeforeInfUp((PSTRING) pData) == FALSE)
+ return NDIS_STATUS_FAILURE;
+ }
+ break;
+
+ case CMD_RTPRIV_IOCTL_SIOCGIWFREQ:
+ /* get channel number */
+ *(ULONG *)pData = pAd->CommonCfg.Channel;
+ break;
+
+
+
+ case CMD_RTPRIV_IOCTL_BEACON_UPDATE:
+ /* update all beacon contents */
+#ifdef CONFIG_AP_SUPPORT
+ APMakeAllBssBeacon(pAd);
+ APUpdateAllBeaconFrame(pAd);
+#endif /* CONFIG_AP_SUPPORT */
+ break;
+
+ case CMD_RTPRIV_IOCTL_RXPATH_GET:
+ /* get the number of rx path */
+ *(ULONG *)pData = pAd->Antenna.field.RxPath;
+ break;
+
+ case CMD_RTPRIV_IOCTL_CHAN_LIST_NUM_GET:
+ *(ULONG *)pData = pAd->ChannelListNum;
+ break;
+
+ case CMD_RTPRIV_IOCTL_CHAN_LIST_GET:
+ {
+ UINT32 i;
+ UCHAR *pChannel = (UCHAR *)pData;
+
+ for (i = 1; i <= pAd->ChannelListNum; i++)
+ {
+ *pChannel = pAd->ChannelList[i-1].Channel;
+ pChannel ++;
+ }
+ }
+ break;
+
+ case CMD_RTPRIV_IOCTL_FREQ_LIST_GET:
+ {
+ UINT32 i;
+ UINT32 *pFreq = (UINT32 *)pData;
+ UINT32 m;
+
+ for (i = 1; i <= pAd->ChannelListNum; i++)
+ {
+ m = 2412000;
+ MAP_CHANNEL_ID_TO_KHZ(pAd->ChannelList[i-1].Channel, m);
+ (*pFreq) = m;
+ pFreq ++;
+ }
+ }
+ break;
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+ case CMD_RTPRIV_SET_PRECONFIG_VALUE:
+ /* Set some preconfigured value before interface up*/
+ pAd->CommonCfg.DfsType = MAX_RD_REGION;
+ break;
+#endif /* EXT_BUILD_CHANNEL_LIST */
+
+
+#ifdef RTMP_USB_SUPPORT
+ case CMD_RTPRIV_IOCTL_USB_MORE_FLAG_SET:
+ {
+ RT_CMD_USB_MORE_FLAG_CONFIG *pConfig;
+ UINT32 VendorID, ProductID;
+
+
+ pConfig = (RT_CMD_USB_MORE_FLAG_CONFIG *)pData;
+ VendorID = pConfig->VendorID;
+ ProductID = pConfig->ProductID;
+
+ if (VendorID == 0x0DB0)
+ {
+ if ((ProductID == 0x871C) || (ProductID == 0x822C))
+ {
+ RTMP_SET_MORE_FLAG(pAd, (fRTMP_ADAPTER_DISABLE_DOT_11N | fRTMP_ADAPTER_WSC_PBC_PIN0));
+ }
+ if ((ProductID == 0x871A) || (ProductID == 0x822A))
+ {
+ RTMP_SET_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DOT_11N);
+ }
+ if ((ProductID == 0x871B) || (ProductID == 0x822B))
+ {
+ RTMP_SET_MORE_FLAG(pAd, fRTMP_ADAPTER_WSC_PBC_PIN0);
+ }
+ }
+
+ if (VendorID == 0x07D1)
+ {
+ if (ProductID == 0x3C0F)
+ RTMP_SET_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DOT_11N);
+ }
+ }
+ break;
+
+ case CMD_RTPRIV_IOCTL_USB_CONFIG_INIT:
+ {
+ RT_CMD_USB_DEV_CONFIG *pConfig;
+ UINT32 i;
+ pConfig = (RT_CMD_USB_DEV_CONFIG *)pData;
+ pAd->NumberOfPipes = pConfig->NumberOfPipes;
+ pAd->BulkInMaxPacketSize = pConfig->BulkInMaxPacketSize;
+ pAd->BulkOutMaxPacketSize = pConfig->BulkOutMaxPacketSize;
+
+ for (i = 0; i < 6; i++)
+ pAd->BulkOutEpAddr[i] = pConfig->BulkOutEpAddr[i];
+
+ for (i = 0; i < 6; i++) {
+ DBGPRINT(RT_DEBUG_OFF, ("%s():pAd->BulkOutEpAddr=0x%x\n", __FUNCTION__, pAd->BulkOutEpAddr[i]));
+ }
+
+
+ for (i = 0; i < 2; i++)
+ pAd->BulkInEpAddr[i] = pConfig->BulkInEpAddr[i];
+
+ pAd->config = pConfig->pConfig;
+ }
+ break;
+
+ case CMD_RTPRIV_IOCTL_USB_SUSPEND:
+ pAd->PM_FlgSuspend = 1;
+ if (Data)
+ {
+ RTUSBCancelPendingBulkInIRP(pAd);
+ RTUSBCancelPendingBulkOutIRP(pAd);
+ }
+ break;
+
+ case CMD_RTPRIV_IOCTL_USB_RESUME:
+ pAd->PM_FlgSuspend = 0;
+ break;
+#endif /* RTMP_USB_SUPPORT */
+
+
+#ifdef RT_CFG80211_SUPPORT
+ case CMD_RTPRIV_IOCTL_CFG80211_CFG_START:
+ RT_CFG80211_REINIT(pAd);
+ RT_CFG80211_CRDA_REG_RULE_APPLY(pAd);
+ break;
+#endif /* RT_CFG80211_SUPPORT */
+
+#ifdef INF_PPA_SUPPORT
+ case CMD_RTPRIV_IOCTL_INF_PPA_INIT:
+ os_alloc_mem(NULL, (UCHAR **)&(pAd->pDirectpathCb), sizeof(PPA_DIRECTPATH_CB));
+ break;
+
+ case CMD_RTPRIV_IOCTL_INF_PPA_EXIT:
+ if (ppa_hook_directpath_register_dev_fn && pAd->PPAEnable==TRUE)
+ {
+ UINT status;
+ status=ppa_hook_directpath_register_dev_fn(&pAd->g_if_id, pAd->net_dev, NULL, 0);
+ DBGPRINT(RT_DEBUG_TRACE, ("unregister PPA:g_if_id=%d status=%d\n",pAd->g_if_id,status));
+ }
+ os_free_mem(NULL, pAd->pDirectpathCb);
+ break;
+#endif /* INF_PPA_SUPPORT*/
+
+ case CMD_RTPRIV_IOCTL_VIRTUAL_INF_UP:
+ /* interface up */
+ {
+ RT_CMD_INF_UP_DOWN *pInfConf = (RT_CMD_INF_UP_DOWN *)pData;
+
+ if (VIRTUAL_IF_NUM(pAd) == 0)
+ {
+ if (pInfConf->rt28xx_open(pAd->net_dev) != 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_open return fail!\n"));
+ return NDIS_STATUS_FAILURE;
+ }
+ }
+ else
+ {
+#ifdef CONFIG_AP_SUPPORT
+ extern VOID APMakeAllBssBeacon(IN PRTMP_ADAPTER pAd);
+ extern VOID APUpdateAllBeaconFrame(IN PRTMP_ADAPTER pAd);
+ APMakeAllBssBeacon(pAd);
+ APUpdateAllBeaconFrame(pAd);
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ VIRTUAL_IF_INC(pAd);
+ }
+ break;
+
+ case CMD_RTPRIV_IOCTL_VIRTUAL_INF_DOWN:
+ /* interface down */
+ {
+ RT_CMD_INF_UP_DOWN *pInfConf = (RT_CMD_INF_UP_DOWN *)pData;
+
+ VIRTUAL_IF_DEC(pAd);
+ if (VIRTUAL_IF_NUM(pAd) == 0)
+ pInfConf->rt28xx_close(pAd->net_dev);
+ }
+ break;
+
+ case CMD_RTPRIV_IOCTL_VIRTUAL_INF_GET:
+ /* get virtual interface number */
+ *(ULONG *)pData = VIRTUAL_IF_NUM(pAd);
+ break;
+
+ case CMD_RTPRIV_IOCTL_INF_TYPE_GET:
+ /* get current interface type */
+ *(ULONG *)pData = pAd->infType;
+ break;
+
+ case CMD_RTPRIV_IOCTL_INF_STATS_GET:
+ /* get statistics */
+ {
+ RT_CMD_STATS *pStats = (RT_CMD_STATS *)pData;
+ pStats->pStats = pAd->stats;
+ if(pAd->OpMode == OPMODE_STA)
+ {
+ pStats->rx_packets = pAd->WlanCounters.ReceivedFragmentCount.QuadPart;
+ pStats->tx_packets = pAd->WlanCounters.TransmittedFragmentCount.QuadPart;
+ pStats->rx_bytes = pAd->RalinkCounters.ReceivedByteCount;
+ pStats->tx_bytes = pAd->RalinkCounters.TransmittedByteCount;
+ pStats->rx_errors = pAd->Counters8023.RxErrors;
+ pStats->tx_errors = pAd->Counters8023.TxErrors;
+ pStats->multicast = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart; /* multicast packets received*/
+ pStats->collisions = pAd->Counters8023.OneCollision + pAd->Counters8023.MoreCollisions; /* Collision packets*/
+ pStats->rx_over_errors = pAd->Counters8023.RxNoBuffer; /* receiver ring buff overflow*/
+ pStats->rx_crc_errors = 0;/*pAd->WlanCounters.FCSErrorCount; recved pkt with crc error*/
+ pStats->rx_frame_errors = pAd->Counters8023.RcvAlignmentErrors; /* recv'd frame alignment error*/
+ pStats->rx_fifo_errors = pAd->Counters8023.RxNoBuffer; /* recv'r fifo overrun*/
+ }
+#ifdef CONFIG_AP_SUPPORT
+ else if(pAd->OpMode == OPMODE_AP)
+ {
+ INT index;
+ for(index = 0; index < MAX_MBSSID_NUM(pAd); index++)
+ {
+ if (pAd->ApCfg.MBSSID[index].MSSIDDev == (PNET_DEV)(pStats->pNetDev))
+ {
+ break;
+ }
+ }
+
+ if(index >= MAX_MBSSID_NUM(pAd))
+ {
+ //reset counters
+ pStats->rx_packets = 0;
+ pStats->tx_packets = 0;
+ pStats->rx_bytes = 0;
+ pStats->tx_bytes = 0;
+ pStats->rx_errors = 0;
+ pStats->tx_errors = 0;
+ pStats->multicast = 0; /* multicast packets received*/
+ pStats->collisions = 0; /* Collision packets*/
+ pStats->rx_over_errors = 0; /* receiver ring buff overflow*/
+ pStats->rx_crc_errors = 0; /* recved pkt with crc error*/
+ pStats->rx_frame_errors = 0; /* recv'd frame alignment error*/
+ pStats->rx_fifo_errors = 0; /* recv'r fifo overrun*/
+
+ DBGPRINT(RT_DEBUG_ERROR, ("CMD_RTPRIV_IOCTL_INF_STATS_GET: can not find mbss I/F\n"));
+ return NDIS_STATUS_FAILURE;
+ }
+
+ pStats->rx_packets = pAd->ApCfg.MBSSID[index].RxCount;
+ pStats->tx_packets = pAd->ApCfg.MBSSID[index].TxCount;
+ pStats->rx_bytes = pAd->ApCfg.MBSSID[index].ReceivedByteCount;
+ pStats->tx_bytes = pAd->ApCfg.MBSSID[index].TransmittedByteCount;
+ pStats->rx_errors = pAd->ApCfg.MBSSID[index].RxErrorCount;
+ pStats->tx_errors = pAd->ApCfg.MBSSID[index].TxErrorCount;
+ pStats->multicast = pAd->ApCfg.MBSSID[index].mcPktsRx; /* multicast packets received */
+ pStats->collisions = 0; /* Collision packets*/
+ pStats->rx_over_errors = 0; /* receiver ring buff overflow*/
+ pStats->rx_crc_errors = 0;/* recved pkt with crc error*/
+ pStats->rx_frame_errors = 0; /* recv'd frame alignment error*/
+ pStats->rx_fifo_errors = 0; /* recv'r fifo overrun*/
+ }
+#endif
+ }
+ break;
+
+ case CMD_RTPRIV_IOCTL_INF_IW_STATUS_GET:
+ /* get wireless statistics */
+ {
+ UCHAR CurOpMode = OPMODE_AP;
+#ifdef CONFIG_AP_SUPPORT
+ PMAC_TABLE_ENTRY pMacEntry = NULL;
+#endif /* CONFIG_AP_SUPPORT */
+ RT_CMD_IW_STATS *pStats = (RT_CMD_IW_STATS *)pData;
+
+ pStats->qual = 0;
+ pStats->level = 0;
+ pStats->noise = 0;
+ pStats->pStats = pAd->iw_stats;
+
+
+ /*check if the interface is down*/
+ if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+ return NDIS_STATUS_FAILURE;
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == OPMODE_AP)
+ {
+#ifdef APCLI_SUPPORT
+ if ((pStats->priv_flags == INT_APCLI)
+ )
+ {
+ INT ApCliIdx = ApCliIfLookUp(pAd, (PUCHAR)pStats->dev_addr);
+ if ((ApCliIdx >= 0) && VALID_WCID(pAd->ApCfg.ApCliTab[ApCliIdx].MacTabWCID))
+ pMacEntry = &pAd->MacTab.Content[pAd->ApCfg.ApCliTab[ApCliIdx].MacTabWCID];
+ }
+ else
+#endif /* APCLI_SUPPORT */
+ {
+ /*
+ only AP client support wireless stats function.
+ return NULL pointer for all other cases.
+ */
+ pMacEntry = NULL;
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == OPMODE_AP)
+ {
+ if (pMacEntry != NULL)
+ pStats->qual = ((pMacEntry->ChannelQuality * 12)/10 + 10);
+ else
+ pStats->qual = ((pAd->Mlme.ChannelQuality * 12)/10 + 10);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pStats->qual > 100)
+ pStats->qual = 100;
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == OPMODE_AP)
+ {
+ if (pMacEntry != NULL)
+ pStats->level =
+ RTMPMaxRssi(pAd, pMacEntry->RssiSample.AvgRssi0,
+ pMacEntry->RssiSample.AvgRssi1,
+ pMacEntry->RssiSample.AvgRssi2);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+ pStats->noise = RTMPMaxRssi(pAd, pAd->ApCfg.RssiSample.AvgRssi0,
+ pAd->ApCfg.RssiSample.AvgRssi1,
+ pAd->ApCfg.RssiSample.AvgRssi2) -
+ RTMPMinSnr(pAd, pAd->ApCfg.RssiSample.AvgSnr0,
+ pAd->ApCfg.RssiSample.AvgSnr1);
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ break;
+
+ case CMD_RTPRIV_IOCTL_INF_MAIN_CREATE:
+ *(VOID **)pData = RtmpPhyNetDevMainCreate(pAd);
+ break;
+
+ case CMD_RTPRIV_IOCTL_INF_MAIN_ID_GET:
+ *(ULONG *)pData = INT_MAIN;
+ break;
+
+ case CMD_RTPRIV_IOCTL_INF_MAIN_CHECK:
+ if (Data != INT_MAIN)
+ return NDIS_STATUS_FAILURE;
+ break;
+
+ case CMD_RTPRIV_IOCTL_INF_P2P_CHECK:
+ if (Data != INT_P2P)
+ return NDIS_STATUS_FAILURE;
+ break;
+
+#ifdef WDS_SUPPORT
+ case CMD_RTPRIV_IOCTL_WDS_INIT:
+ WDS_Init(pAd, pData);
+ break;
+
+ case CMD_RTPRIV_IOCTL_WDS_REMOVE:
+ WDS_Remove(pAd);
+ break;
+
+ case CMD_RTPRIV_IOCTL_WDS_STATS_GET:
+ if (Data == INT_WDS)
+ {
+ if (WDS_StatsGet(pAd, pData) != TRUE)
+ return NDIS_STATUS_FAILURE;
+ }
+ else
+ return NDIS_STATUS_FAILURE;
+ break;
+#endif /* WDS_SUPPORT */
+
+#ifdef RALINK_ATE
+#ifdef RALINK_QA
+ case CMD_RTPRIV_IOCTL_ATE:
+ RtmpDoAte(pAd, wrq, pData);
+ break;
+#endif /* RALINK_QA */
+#endif /* RALINK_ATE */
+
+ case CMD_RTPRIV_IOCTL_MAC_ADDR_GET:
+
+ RT28xx_EEPROM_READ16(pAd, 0x04, Addr01);
+ RT28xx_EEPROM_READ16(pAd, 0x06, Addr23);
+ RT28xx_EEPROM_READ16(pAd, 0x08, Addr45);
+
+ PermanentAddress[0] = (UCHAR)(Addr01 & 0xff);
+ PermanentAddress[1] = (UCHAR)(Addr01 >> 8);
+ PermanentAddress[2] = (UCHAR)(Addr23 & 0xff);
+ PermanentAddress[3] = (UCHAR)(Addr23 >> 8);
+ PermanentAddress[4] = (UCHAR)(Addr45 & 0xff);
+ PermanentAddress[5] = (UCHAR)(Addr45 >> 8);
+
+ for(i=0; i<6; i++)
+ *(UCHAR *)(pData+i) = PermanentAddress[i];
+ break;
+#ifdef CONFIG_AP_SUPPORT
+ case CMD_RTPRIV_IOCTL_AP_SIOCGIWRATEQ:
+ /* handle for SIOCGIWRATEQ */
+ {
+ RT_CMD_IOCTL_RATE *pRate = (RT_CMD_IOCTL_RATE *)pData;
+ HTTRANSMIT_SETTING HtPhyMode;
+
+#ifdef APCLI_SUPPORT
+ if (pRate->priv_flags == INT_APCLI)
+ HtPhyMode = pAd->ApCfg.ApCliTab[pObj->ioctl_if].HTPhyMode;
+ else
+#endif /* APCLI_SUPPORT */
+#ifdef WDS_SUPPORT
+ if (pRate->priv_flags == INT_WDS)
+ HtPhyMode = pAd->WdsTab.WdsEntry[pObj->ioctl_if].HTPhyMode;
+ else
+#endif /* WDS_SUPPORT */
+ {
+ HtPhyMode = pAd->ApCfg.MBSSID[pObj->ioctl_if].HTPhyMode;
+#ifdef MBSS_SUPPORT
+ /* reset phy mode for MBSS */
+ MBSS_PHY_MODE_RESET(pObj->ioctl_if, HtPhyMode);
+#endif /* MBSS_SUPPORT */
+ }
+ RtmpDrvMaxRateGet(pAd, HtPhyMode.field.MODE, HtPhyMode.field.ShortGI,
+ HtPhyMode.field.BW, HtPhyMode.field.MCS,
+ (UINT32 *)&pRate->BitRate);
+ }
+ break;
+#endif /* CONFIG_AP_SUPPORT */
+
+ case CMD_RTPRIV_IOCTL_SIOCGIWNAME:
+ RtmpIoctl_rt_ioctl_giwname(pAd, pData, 0);
+ break;
+
+#if defined(CONFIG_CSO_SUPPORT) || defined(CONFIG_RX_CSO_SUPPORT)
+ case CMD_RTPRIV_IOCTL_ADAPTER_CSO_SUPPORT_TEST:
+ *(UCHAR *)pData = (pAd->MoreFlags & fASIC_CAP_CSO) ? 1:0;
+ break;
+#endif /* defined(CONFIG_CSO_SUPPORT) || defined(CONFIG_RX_CSO_SUPPORT) */
+
+ }
+
+#ifdef RT_CFG80211_SUPPORT
+ if ((CMD_RTPRIV_IOCTL_80211_START <= cmd) &&
+ (cmd <= CMD_RTPRIV_IOCTL_80211_END))
+ {
+ CFG80211DRV_IoctlHandle(pAd, wrq, cmd, subcmd, pData, Data);
+ }
+#endif /* RT_CFG80211_SUPPORT */
+
+ if (cmd >= CMD_RTPRIV_IOCTL_80211_COM_LATEST_ONE)
+ return NDIS_STATUS_FAILURE;
+
+ return Status;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Issue a site survey command to driver
+ Arguments:
+ pAdapter Pointer to our adapter
+ wrq Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ Usage:
+ 1.) iwpriv ra0 set site_survey
+ ==========================================================================
+*/
+INT Set_SiteSurvey_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ NDIS_802_11_SSID Ssid;
+ POS_COOKIE pObj;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ //check if the interface is down
+ if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("INFO::Network is down!\n"));
+ return -ENETDOWN;
+ }
+
+
+ NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID));
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef AP_SCAN_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if ((strlen(arg) != 0) && (strlen(arg) <= MAX_LEN_OF_SSID))
+ {
+ NdisMoveMemory(Ssid.Ssid, arg, strlen(arg));
+ Ssid.SsidLength = strlen(arg);
+ }
+
+ if (Ssid.SsidLength == 0)
+ ApSiteSurvey(pAd, &Ssid, SCAN_PASSIVE, FALSE);
+ else
+ ApSiteSurvey(pAd, &Ssid, SCAN_ACTIVE, FALSE);
+
+ return TRUE;
+ }
+#endif /* AP_SCAN_SUPPORT */
+#endif // CONFIG_AP_SUPPORT //
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_SiteSurvey_Proc\n"));
+
+ return TRUE;
+}
+
+INT Set_Antenna_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ANT_DIVERSITY_TYPE UsedAnt;
+ int i;
+ DBGPRINT(RT_DEBUG_OFF, ("==> Set_Antenna_Proc *******************\n"));
+
+ for (i = 0; i < strlen(arg); i++)
+ if (!isdigit(arg[i]))
+ return -EINVAL;
+
+ UsedAnt = simple_strtol(arg, 0, 10);
+
+ switch (UsedAnt)
+ {
+ /* 2: Fix in the PHY Antenna CON1*/
+ case ANT_FIX_ANT0:
+ AsicSetRxAnt(pAd, 0);
+ DBGPRINT(RT_DEBUG_OFF, ("<== Set_Antenna_Proc(Fix in Ant CON1), (%d,%d)\n",
+ pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
+ break;
+ /* 3: Fix in the PHY Antenna CON2*/
+ case ANT_FIX_ANT1:
+ AsicSetRxAnt(pAd, 1);
+ DBGPRINT(RT_DEBUG_OFF, ("<== %s(Fix in Ant CON2), (%d,%d)\n",
+ __FUNCTION__, pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
+ break;
+ default:
+ DBGPRINT(RT_DEBUG_ERROR, ("<== %s(N/A cmd: %d), (%d,%d)\n", __FUNCTION__, UsedAnt,
+ pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
+ break;
+ }
+
+ return TRUE;
+}
+
+
+
+#ifdef MICROWAVE_OVEN_SUPPORT
+INT Set_MO_FalseCCATh_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG th;
+
+ th = simple_strtol(arg, 0, 10);
+
+ if (th > 65535)
+ th = 65535;
+
+ pAd->CommonCfg.MO_Cfg.nFalseCCATh = th;
+
+ DBGPRINT(RT_DEBUG_OFF, ("%s: set falseCCA threshold %lu for microwave oven application!!\n", __FUNCTION__, th));
+
+ return TRUE;
+}
+#endif /* MICROWAVE_OVEN_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_cmd.c b/cleopatre/devkit/mt7601udrv/common/cmm_cmd.c
new file mode 100644
index 0000000000..6fddedee5c
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_cmd.c
@@ -0,0 +1,169 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2006, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ cmm_cmd.c
+
+ Abstract:
+ All command related API.
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+ Paul Lin 06-25-2004 created
+*/
+
+#include "rt_config.h"
+
+
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTInitializeCmdQ(
+ IN PCmdQ cmdq)
+{
+ cmdq->head = NULL;
+ cmdq->tail = NULL;
+ cmdq->size = 0;
+ cmdq->CmdQState = RTMP_TASK_STAT_INITED;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTThreadDequeueCmd(
+ IN PCmdQ cmdq,
+ OUT PCmdQElmt *pcmdqelmt)
+{
+ *pcmdqelmt = cmdq->head;
+
+ if (*pcmdqelmt != NULL)
+ {
+ cmdq->head = cmdq->head->next;
+ cmdq->size--;
+ if (cmdq->size == 0)
+ cmdq->tail = NULL;
+ }
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS RTEnqueueInternalCmd(
+ IN PRTMP_ADAPTER pAd,
+ IN NDIS_OID Oid,
+ IN PVOID pInformationBuffer,
+ IN UINT32 InformationBufferLength)
+{
+ NDIS_STATUS status;
+ PCmdQElmt cmdqelmt = NULL;
+
+
+ status = os_alloc_mem(pAd, (PUCHAR *)&cmdqelmt, sizeof(CmdQElmt));
+ if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt == NULL))
+ return (NDIS_STATUS_RESOURCES);
+ NdisZeroMemory(cmdqelmt, sizeof(CmdQElmt));
+
+ if(InformationBufferLength > 0)
+ {
+ status = os_alloc_mem(pAd, (PUCHAR *)&cmdqelmt->buffer, InformationBufferLength);
+ if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt->buffer == NULL))
+ {
+ os_free_mem(pAd, cmdqelmt);
+ return (NDIS_STATUS_RESOURCES);
+ }
+ else
+ {
+ NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength);
+ cmdqelmt->bufferlength = InformationBufferLength;
+ }
+ }
+ else
+ {
+ cmdqelmt->buffer = NULL;
+ cmdqelmt->bufferlength = 0;
+ }
+
+ cmdqelmt->command = Oid;
+ cmdqelmt->CmdFromNdis = FALSE;
+
+ if (cmdqelmt != NULL)
+ {
+ NdisAcquireSpinLock(&pAd->CmdQLock);
+ if (pAd->CmdQ.CmdQState & RTMP_TASK_CAN_DO_INSERT)
+ {
+ EnqueueCmd((&pAd->CmdQ), cmdqelmt);
+ status = NDIS_STATUS_SUCCESS;
+ }
+ else
+ {
+ status = NDIS_STATUS_FAILURE;
+ }
+ NdisReleaseSpinLock(&pAd->CmdQLock);
+
+ if (status == NDIS_STATUS_FAILURE)
+ {
+ if (cmdqelmt->buffer)
+ os_free_mem(pAd, cmdqelmt->buffer);
+ os_free_mem(pAd, cmdqelmt);
+ }
+ else
+ RTCMDUp(&pAd->cmdQTask);
+ }
+ return(NDIS_STATUS_SUCCESS);
+}
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_cs.c b/cleopatre/devkit/mt7601udrv/common/cmm_cs.c
new file mode 100644
index 0000000000..d736385fee
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_cs.c
@@ -0,0 +1,763 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ cmm_cs.c
+
+ Abstract:
+ Carrier Sensing related functions
+
+ Revision History:
+ Who When What
+ ---------------------------------------------------------------------
+*/
+#include "rt_config.h"
+
+#ifdef CARRIER_DETECTION_SUPPORT
+static ULONG time[20];
+static ULONG idle[20];
+static ULONG busy[20];
+static ULONG cd_idx=0;
+
+static void ToneRadarProgram(PRTMP_ADAPTER pAd);
+
+#ifdef CONFIG_AP_SUPPORT
+/*
+ ==========================================================================
+ Description:
+ Check current CS state, indicating Silient state (carrier exist) or not
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ TRUE if the current state is SILENT state, FALSE other wise
+ Note:
+ ==========================================================================
+*/
+INT isCarrierDetectExist(
+ IN PRTMP_ADAPTER pAd)
+{
+ if (pAd->CommonCfg.CarrierDetect.CD_State == CD_SILENCE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Enable or Disable Carrier Detection feature (AP ioctl).
+ Arguments:
+ pAd Pointer to our adapter
+ arg Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ Usage:
+ 1.) iwpriv ra0 set CarrierDetect=[1/0]
+ ==========================================================================
+*/
+INT Set_CarrierDetect_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+ UCHAR apidx = pObj->ioctl_if;
+ UINT Enable;
+
+ if (apidx != MAIN_MBSSID)
+ return FALSE;
+
+ Enable = (UINT) simple_strtol(arg, 0, 10);
+
+ pAd->CommonCfg.CarrierDetect.Enable = (BOOLEAN)(Enable == 0 ? FALSE : TRUE);
+
+ RTMP_CHIP_RADAR_GLRT_COMPENSATE(pAd);
+ RTMP_CHIP_CCK_MRC_STATUS_CTRL(pAd);
+
+ if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+ CarrierDetectionStart(pAd);
+ else
+ CarrierDetectionStop(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: %s\n", __FUNCTION__,
+ pAd->CommonCfg.CarrierDetect.Enable == TRUE ? "Enable Carrier Detection":"Disable Carrier Detection"));
+
+ return TRUE;
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT
+/*
+ ==========================================================================
+ Description:
+ When h/w interrupt is not available for CS, f/w take care of the operation, this function monitor necessary
+ parameters that determine the CS state periodically. (every 100ms)
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+VOID CarrierDetectionPeriodicStateCtrl(
+ IN PRTMP_ADAPTER pAd)
+{
+ CD_STATE *pCD_State = &pAd->CommonCfg.CarrierDetect.CD_State;
+ ULONG *pOneSecIntCount = &pAd->CommonCfg.CarrierDetect.OneSecIntCount;
+ CARRIER_DETECT_PARAM CarrDetectParam;
+
+
+#ifdef RALINK_ATE
+ /* Nothing to do in ATE mode */
+ if (ATE_ON(pAd))
+ return;
+#endif /* RALINK_ATE */
+
+ /* tell firmware to prepare Recheck and RadarToneCount */
+ AsicSendCommandToMcu(pAd, CD_CHECKOUT_MCU_CMD, 0xff, 0x00, 0x00, FALSE);
+ /* Debug */
+ if (pAd->CommonCfg.CarrierDetect.Debug == RT_DEBUG_TRACE)
+ {
+ CARRIER_DETECT_DEBUG CarrDetectDebug;
+ RTUSBMultiRead(pAd, 0x4CB0, (PUCHAR) &CarrDetectDebug, sizeof(CarrDetectDebug));
+ printk("delta_div = 0x%02X, rRadarToneCount = %u, Recheck = %u, Criteria = %u, Threshold = 0x%08X, VGA_Mask = 0x%04X\n",
+ CarrDetectDebug.delta_div,
+ CarrDetectDebug.RadarToneCount,
+ CarrDetectDebug.ReCheck,
+ CarrDetectDebug.Criteria << 6, /* ms -> 16us*/
+ CarrDetectDebug.Threshold,
+ CarrDetectDebug.VGA_Mask);
+ }
+
+ RTUSBMultiRead(pAd, RADAR_TONE_COUNT, (PUCHAR) &CarrDetectParam, sizeof(CarrDetectParam));
+ switch(*pCD_State)
+ {
+ case CD_NORMAL:
+ if (CarrDetectParam.ReCheck == 0)
+ {
+ *pCD_State = CD_SILENCE;
+ if (pAd->CommonCfg.CarrierDetect.Debug != RT_DEBUG_TRACE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Carrier Detected\n"));
+
+ /* stop all TX actions including Beacon sending.*/
+ AsicDisableSync(pAd);
+ }
+ else
+ printk("Carrier Detected\n");
+ }
+ break;
+
+ case CD_SILENCE:
+ *pOneSecIntCount += CarrDetectParam.RadarToneCount;
+ break;
+
+ default:
+ break;
+ }
+}
+#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */
+
+/*
+ ==========================================================================
+ Description:
+ When there is no f/w taking care of CS operation, this function depends on h/w interrupts for every possible carrier
+ tone to judge the CS state
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+VOID RTMPHandleRadarInterrupt(PRTMP_ADAPTER pAd)
+{
+ UINT32 value, delta;
+ UCHAR bbp=0;
+ PCARRIER_DETECTION_STRUCT pCarrierDetect = &pAd->CommonCfg.CarrierDetect;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandleRadarInterrupt()\n"));
+ RTMP_IO_READ32(pAd, PBF_LIFE_TIMER, &value);
+ RTMP_IO_READ32(pAd, CH_IDLE_STA, &pCarrierDetect->idle_time);
+ RTMP_IO_READ32(pAd, CH_BUSY_STA, &pCarrierDetect->busy_time);
+ delta = (value >> 4) - pCarrierDetect->TimeStamp;
+ pCarrierDetect->TimeStamp = value >> 4;
+ pCarrierDetect->OneSecIntCount++;
+
+ if(pAd->chipCap.carrier_func==TONE_RADAR_V2)
+ {
+ RTMP_CARRIER_IO_READ8(pAd, 1, &bbp);
+ if (!(bbp & 0x1))
+ return;
+ else
+ {
+ /* Disable carrier detection and clear the status bit*/
+ RTMP_CARRIER_IO_WRITE8(pAd, 0, 0);
+ RTMP_CARRIER_IO_WRITE8(pAd, 1, 1);
+ /* Clear interrupt */
+ RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR ,(1<<20));
+ }
+ }
+
+ if (pCarrierDetect->Debug)
+ {
+ if (cd_idx < 20)
+ {
+ time[cd_idx] = delta;
+ idle[cd_idx] = pCarrierDetect->idle_time;
+ busy[cd_idx] = pCarrierDetect->busy_time;
+ cd_idx++;
+ }
+ else
+ {
+ int i;
+ pCarrierDetect->Debug = 0;
+ for (i = 0; i < 20; i++)
+ {
+ printk("%3d %4ld %ld %ld\n", i, time[i], idle[i], busy[i]);
+ }
+ cd_idx = 0;
+
+ }
+ }
+
+ if (pCarrierDetect->CD_State == CD_NORMAL)
+ {
+ if ((delta < pCarrierDetect->criteria) && (pCarrierDetect->recheck))
+ pCarrierDetect->recheck --;
+ else
+ pCarrierDetect->recheck = pCarrierDetect->recheck1;
+
+ if (pCarrierDetect->recheck == 0)
+ {
+ /* declare carrier sense*/
+ pCarrierDetect->CD_State = CD_SILENCE;
+
+ if (pCarrierDetect->Debug != RT_DEBUG_TRACE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Carrier Detected\n"));
+
+ /* stop all TX actions including Beacon sending.*/
+ AsicDisableSync(pAd);
+ }
+ else
+ {
+ printk("Carrier Detected\n");
+ }
+ }
+ }
+
+ if(pAd->chipCap.carrier_func == TONE_RADAR_V2)
+ {
+ /* Clear Status bit */
+ //RTMP_CARRIER_IO_WRITE8(pAd, 1, bbp);
+ RTMP_CARRIER_IO_READ8(pAd, 1, &bbp);
+ if (bbp & 0x1)
+ DBGPRINT(RT_DEBUG_ERROR, ("CS bit not cleared!!!\n"));
+ /* re-enable carrier detection */
+ RTMP_CARRIER_IO_WRITE8(pAd, 0, 1);
+ }
+ else if(pAd->chipCap.carrier_func == TONE_RADAR_V1 &&
+ pCarrierDetect->Enable)
+ {
+ ToneRadarProgram(pAd);
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ Reset CS state to NORMAL state.
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+INT CarrierDetectReset(
+ IN PRTMP_ADAPTER pAd)
+{
+ pAd->CommonCfg.CarrierDetect.CD_State = CD_NORMAL;
+ return 0;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Criteria in CS is a timing difference threshold for a pair of carrier tones. This function is a ioctl uesed to adjust the
+ Criteria. (unit: 16us)
+
+ Arguments:
+ pAd Pointer to our adapter
+ arg Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+INT Set_CarrierCriteria_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UINT32 Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ pAd->CommonCfg.CarrierDetect.criteria = Value;
+#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT
+ {
+ USHORT sVal = (USHORT) (Value >> 6); /* convert unit from 16us to ms:(2^4 /2^10) */
+ RTUSBMultiWrite(pAd, CD_CRITERIA, (PUCHAR) &sVal, 2, FALSE);
+ /* send enable cmd to mcu to take effect */
+ AsicSendCommandToMcu(pAd, CD_ONOFF_MCU_CMD, 0xff, 0x01, 0x00, FALSE);
+ }
+#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ ReCheck in CS is a value indicating how many continuous incoming carrier tones is enough us to announce that there
+ is carrier tone (and hence enter SILENT state). This function is a ioctl uesed to adjust the ReCheck value.
+
+ Arguments:
+ pAd Pointer to our adapter
+ arg Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+INT Set_CarrierReCheck_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.CarrierDetect.recheck1 = simple_strtol(arg, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("Set Recheck = %u\n", pAd->CommonCfg.CarrierDetect.recheck1));
+#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT
+ RTMP_IO_WRITE8(pAd, CD_CHECK_COUNT, pAd->CommonCfg.CarrierDetect.recheck1);
+ /* send enable cmd to mcu to take effect */
+ AsicSendCommandToMcu(pAd, CD_ONOFF_MCU_CMD, 0xff, 0x01, 0x00, FALSE);
+#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ CarrierGoneThreshold is used to determine whether we should leave SILENT state. When the number of carrier
+ tones in a certain period of time is less than CarrierGoneThreshold, we should return to NORMAL state. This function
+ is a ioctl uesed to adjust the CarrierGoneThreshold.
+
+ Arguments:
+ pAd Pointer to our adapter
+ arg Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+INT Set_CarrierGoneThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.CarrierDetect.CarrierGoneThreshold = simple_strtol(arg, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("Set CarrierGoneThreshold = %u\n", pAd->CommonCfg.CarrierDetect.CarrierGoneThreshold));
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Setting up the carrier debug level. set 0 means to turning off the carrier debug
+
+ Arguments:
+ pAd Pointer to our adapter
+ arg Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+INT Set_CarrierDebug_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.CarrierDetect.Debug = simple_strtol(arg, 0, 10);
+ printk("pAd->CommonCfg.CarrierDetect.Debug = %ld\n", pAd->CommonCfg.CarrierDetect.Debug);
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Delta control the delay line characteristic of the cross correlation energy calculation.
+ This function is a ioctl uesed to adjust the Delta value.
+
+ Arguments:
+ pAd Pointer to our adapter
+ arg Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+INT Set_CarrierDelta_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.CarrierDetect.delta = simple_strtol(arg, 0, 10);
+ printk("Delta = %d\n", pAd->CommonCfg.CarrierDetect.delta);
+ CarrierDetectionStart(pAd);
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ To set ON/OFF of the "Not Divide Flag"
+
+ Arguments:
+ pAd Pointer to our adapter
+ arg Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+INT Set_CarrierDivFlag_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.CarrierDetect.div_flag = simple_strtol(arg, 0, 10);
+ printk("DivFlag = %d\n", pAd->CommonCfg.CarrierDetect.div_flag);
+ CarrierDetectionStart(pAd);
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Carrier Threshold is the energy threshold for h/w to determine a carrier tone or not.
+ This function is a ioctl uesed to adjust the Threshold value.
+
+ Arguments:
+ pAd Pointer to our adapter
+ arg Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+INT Set_CarrierThrd_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.CarrierDetect.threshold = simple_strtol(arg, 0, 10);
+ printk("CarrThrd = %d(0x%x)\n", pAd->CommonCfg.CarrierDetect.threshold, pAd->CommonCfg.CarrierDetect.threshold);
+ CarrierDetectionStart(pAd);
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Carrier SymRund is the number of round bits in Radar Symmetric Round Bits Option.
+ This function is a ioctl uesed to adjust the SymRund. (unit: bit)
+
+ Arguments:
+ pAd Pointer to our adapter
+ arg Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+INT Set_CarrierSymRund_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.CarrierDetect.SymRund= simple_strtol(arg, 0, 10);
+ printk("SymRund = %d\n", pAd->CommonCfg.CarrierDetect.SymRund);
+ CarrierDetectionStart(pAd);
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Carrier Masks are used to prevent false trigger while doing Rx_PE, Packet_End, and AGC tuning.
+ This function is a ioctl uesed to adjust these three mask. (unit: 100ns)
+
+ Arguments:
+ pAd Pointer to our adapter
+ arg Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+INT Set_CarrierMask_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.CarrierDetect.VGA_Mask = simple_strtol(arg, 0, 10);
+ pAd->CommonCfg.CarrierDetect.Packet_End_Mask = simple_strtol(arg, 0, 10);
+ pAd->CommonCfg.CarrierDetect.Rx_PE_Mask = simple_strtol(arg, 0, 10);
+ printk("CarrMask = %u(%x)\n", pAd->CommonCfg.CarrierDetect.VGA_Mask, pAd->CommonCfg.CarrierDetect.VGA_Mask);
+ CarrierDetectionStart(pAd);
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Initialize CS parameters.
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+VOID CSInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ PCARRIER_DETECTION_STRUCT pCarrierDetect = &pAd->CommonCfg.CarrierDetect;
+
+ pCarrierDetect->TimeStamp = 0;
+ pCarrierDetect->recheck = pCarrierDetect->recheck1;
+ pCarrierDetect->OneSecIntCount = 0;
+}
+
+/*
+ ==========================================================================
+ Description:
+ To trigger CS start
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+VOID CarrierDetectionStart(PRTMP_ADAPTER pAd)
+{
+ /*ULONG Value;*/
+ /* Enable Bandwidth usage monitor*/
+ DBGPRINT(RT_DEBUG_TRACE, ("CarrierDetectionStart\n"));
+ /*RTMP_IO_READ32(pAd, CH_TIME_CFG, &Value);*/
+ /*RTMP_IO_WRITE32(pAd, CH_TIME_CFG, Value | 0x1f); */
+
+ /* Init Carrier Detect*/
+ if (pAd->CommonCfg.CarrierDetect.Enable)
+ {
+ CSInit(pAd);
+ ToneRadarProgram(pAd);
+#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT
+ {
+ USHORT criteria = (USHORT) (pAd->CommonCfg.CarrierDetect.criteria >> 6); /* convert unit from 16us to 1ms:(2^4 /2^10) */
+ RTUSBMultiWrite(pAd, CD_CRITERIA, (PUCHAR) &criteria, 2, FALSE);
+ RTMP_IO_WRITE8(pAd, CD_CHECK_COUNT, pAd->CommonCfg.CarrierDetect.recheck1);
+ AsicSendCommandToMcu(pAd, CD_ONOFF_MCU_CMD, 0xff, 0x01, 0x00, FALSE);
+ }
+#else
+ /* trun on interrupt polling for pcie device */
+ if (pAd->infType == RTMP_DEV_INF_PCIE)
+ AsicSendCommandToMcu(pAd, CD_INT_POLLING_CMD, 0xff, 0x01, 0x00, FALSE);
+#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ To stop CS
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+VOID CarrierDetectionStop(IN PRTMP_ADAPTER pAd)
+{
+ CarrierDetectReset(pAd);
+#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT
+ /* Stop firmware CS action */
+ AsicSendCommandToMcu(pAd, CD_ONOFF_MCU_CMD, 0xff, 0x00, 0x00, FALSE);
+#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ To program CS related BBP registers (CS initialization)
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+static VOID ToneRadarProgram(PRTMP_ADAPTER pAd)
+{
+ ULONG threshold;
+ /* if wireless mode is 20Mhz mode, then the threshold should div by 2 */
+ if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_20)
+ threshold = pAd->CommonCfg.CarrierDetect.threshold >> 1;
+ else
+ threshold = pAd->CommonCfg.CarrierDetect.threshold;
+ /* Call ToneRadarProgram_v1/ToneRadarProgram_v2*/
+ RTMP_CHIP_CARRIER_PROGRAM(pAd, threshold);
+}
+
+/*
+ ==========================================================================
+ Description:
+ To program CS v1 related BBP registers (CS initialization)
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+VOID ToneRadarProgram_v1(PRTMP_ADAPTER pAd, ULONG threshold)
+{
+ UCHAR bbp;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ToneRadarProgram v1\n"));
+ /* programe delta delay & division bit*/
+ BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R184, 0xf0);
+ bbp = pAd->CommonCfg.CarrierDetect.delta << 4;
+ bbp |= (pAd->CommonCfg.CarrierDetect.div_flag & 0x1) << 3;
+ BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R185, bbp);
+
+ /* program threshold*/
+ BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R184, 0x34);
+ BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R185, (threshold & 0xff000000) >> 24);
+
+ BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R184, 0x24);
+ BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R185, (threshold & 0xff0000) >> 16);
+
+ BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R184, 0x14);
+ BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R185, (threshold & 0xff00) >> 8);
+
+ BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R184, 0x04);
+ BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R185, threshold & 0xff);
+
+ /* ToneRadarEnable v1 */
+ BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R184, 0x05);
+}
+
+/*
+ ==========================================================================
+ Description:
+ To program CS v2 related BBP registers (CS initialization)
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+VOID ToneRadarProgram_v2(PRTMP_ADAPTER pAd, ULONG threshold)
+{
+ UCHAR bbp;
+
+ /* programe delta delay & division bit*/
+ DBGPRINT(RT_DEBUG_TRACE, ("ToneRadarProgram v2\n"));
+ bbp = pAd->CommonCfg.CarrierDetect.delta | \
+ ((pAd->CommonCfg.CarrierDetect.SymRund & 0x3) << 4) | \
+ ((pAd->CommonCfg.CarrierDetect.div_flag & 0x1) << 6) | \
+ 0x80; /* Full 40MHz Detection Mode */
+ RTMP_CARRIER_IO_WRITE8(pAd, 5, bbp);
+
+ /* program *_mask*/
+ RTMP_CARRIER_IO_WRITE8(pAd, 2, pAd->CommonCfg.CarrierDetect.VGA_Mask);
+ RTMP_CARRIER_IO_WRITE8(pAd, 3, pAd->CommonCfg.CarrierDetect.Packet_End_Mask);
+ RTMP_CARRIER_IO_WRITE8(pAd, 4, pAd->CommonCfg.CarrierDetect.Rx_PE_Mask);
+
+ /* program threshold*/
+ RTMP_CARRIER_IO_WRITE8(pAd, 6, threshold & 0xff);
+ RTMP_CARRIER_IO_WRITE8(pAd, 7, (threshold & 0xff00) >> 8);
+ RTMP_CARRIER_IO_WRITE8(pAd, 8, (threshold & 0xff0000) >> 16);
+ RTMP_CARRIER_IO_WRITE8(pAd, 9, (threshold & 0xff000000) >> 24);
+
+ /* ToneRadarEnable v2 */
+ RTMP_CARRIER_IO_WRITE8(pAd, 0, 1);
+}
+
+#endif /* CARRIER_DETECTION_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_data.c b/cleopatre/devkit/mt7601udrv/common/cmm_data.c
new file mode 100644
index 0000000000..ce6b48947b
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_data.c
@@ -0,0 +1,3569 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ****************************************************************************
+
+ Module Name:
+ cmm_data.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ --------- ---------- ----------------------------------------------
+ */
+
+
+#include "rt_config.h"
+
+
+UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
+UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
+UCHAR EAPOL[] = {0x88, 0x8e};
+UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */
+
+UCHAR IPX[] = {0x81, 0x37};
+UCHAR APPLE_TALK[] = {0x80, 0xf3};
+
+
+UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO};
+
+
+
+VOID dump_rxinfo(RTMP_ADAPTER *pAd, RXINFO_STRUC *pRxInfo)
+{
+ hex_dump("RxInfo Raw Data", (UCHAR *)pRxInfo, sizeof(RXINFO_STRUC));
+
+ DBGPRINT(RT_DEBUG_OFF, ("RxInfo Fields:\n"));
+
+#ifdef RLT_MAC
+ DBGPRINT(RT_DEBUG_OFF, ("\tBA=%d\n", pRxInfo->BA));
+ DBGPRINT(RT_DEBUG_OFF, ("\tDATA=%d\n", pRxInfo->DATA));
+ DBGPRINT(RT_DEBUG_OFF, ("\tNULLDATA=%d\n", pRxInfo->NULLDATA));
+ DBGPRINT(RT_DEBUG_OFF, ("\tFRAG=%d\n", pRxInfo->FRAG));
+ DBGPRINT(RT_DEBUG_OFF, ("\tU2M=%d\n", pRxInfo->U2M));
+ DBGPRINT(RT_DEBUG_OFF, ("\tMcast=%d\n", pRxInfo->Mcast));
+ DBGPRINT(RT_DEBUG_OFF, ("\tBcast=%d\n", pRxInfo->Bcast));
+ DBGPRINT(RT_DEBUG_OFF, ("\tMyBss=%d\n", pRxInfo->MyBss));
+ DBGPRINT(RT_DEBUG_OFF, ("\tCrc=%d\n", pRxInfo->Crc));
+ DBGPRINT(RT_DEBUG_OFF, ("\tCipherErr=%d\n", pRxInfo->CipherErr));
+ DBGPRINT(RT_DEBUG_OFF, ("\tAMSDU=%d\n", pRxInfo->AMSDU));
+ DBGPRINT(RT_DEBUG_OFF, ("\tHTC=%d\n", pRxInfo->HTC));
+ DBGPRINT(RT_DEBUG_OFF, ("\tRSSI=%d\n", pRxInfo->RSSI));
+ DBGPRINT(RT_DEBUG_OFF, ("\tL2PAD=%d\n", pRxInfo->L2PAD));
+ DBGPRINT(RT_DEBUG_OFF, ("\tAMPDU=%d\n", pRxInfo->AMPDU));
+ DBGPRINT(RT_DEBUG_OFF, ("\tDecrypted=%d\n", pRxInfo->Decrypted));
+ DBGPRINT(RT_DEBUG_OFF, ("\tBssIdx3=%d\n", pRxInfo->BssIdx3));
+ DBGPRINT(RT_DEBUG_OFF, ("\twapi_kidx=%d\n", pRxInfo->wapi_kidx));
+ DBGPRINT(RT_DEBUG_OFF, ("\tpn_len=%d\n", pRxInfo->pn_len));
+ DBGPRINT(RT_DEBUG_OFF, ("\ttcp_sum_bypass=%d\n", pRxInfo->tcp_sum_bypass));
+ DBGPRINT(RT_DEBUG_OFF, ("\tip_sum_bypass=%d\n", pRxInfo->ip_sum_bypass));
+#endif /* RLT_MAC */
+
+#ifdef RTMP_MAC
+ DBGPRINT(RT_DEBUG_OFF, ("\t" ));
+#endif /* RTMP_MAC */
+}
+
+
+#ifdef RLT_MAC
+VOID dumpRxFCEInfo(RTMP_ADAPTER *pAd, RXFCE_INFO *pRxFceInfo)
+{
+ hex_dump("RxFCEInfo Raw Data", (UCHAR *)pRxFceInfo, sizeof(RXFCE_INFO));
+
+ DBGPRINT(RT_DEBUG_OFF, ("RxFCEInfo Fields:\n"));
+
+ DBGPRINT(RT_DEBUG_OFF, ("\tinfo_type=%d\n", pRxFceInfo->info_type));
+ DBGPRINT(RT_DEBUG_OFF, ("\ts_port=%d\n", pRxFceInfo->s_port));
+ DBGPRINT(RT_DEBUG_OFF, ("\tqsel=%d\n", pRxFceInfo->qsel));
+ DBGPRINT(RT_DEBUG_OFF, ("\tpcie_intr=%d\n", pRxFceInfo->pcie_intr));
+ DBGPRINT(RT_DEBUG_OFF, ("\tmac_len=%d\n", pRxFceInfo->mac_len));
+ DBGPRINT(RT_DEBUG_OFF, ("\tl3l4_done=%d\n", pRxFceInfo->l3l4_done));
+ DBGPRINT(RT_DEBUG_OFF, ("\tpkt_80211=%d\n", pRxFceInfo->pkt_80211));
+ DBGPRINT(RT_DEBUG_OFF, ("\tip_err=%d\n", pRxFceInfo->ip_err));
+ DBGPRINT(RT_DEBUG_OFF, ("\ttcp_err=%d\n", pRxFceInfo->tcp_err));
+ DBGPRINT(RT_DEBUG_OFF, ("\tudp_err=%d\n", pRxFceInfo->udp_err));
+ DBGPRINT(RT_DEBUG_OFF, ("\tpkt_len=%d\n", pRxFceInfo->pkt_len));
+}
+#endif /* RLT_MAC */
+
+
+static UCHAR *txwi_txop_str[]={"HT_TXOP", "PIFS", "SIFS", "BACKOFF", "Invalid"};
+#define TXWI_TXOP_STR(_x) ((_x) <= 3 ? txwi_txop_str[(_x)]: txwi_txop_str[4])
+
+VOID dumpTxWI(RTMP_ADAPTER *pAd, TXWI_STRUC *pTxWI)
+{
+ hex_dump("TxWI Raw Data: ", (UCHAR *)pTxWI, sizeof(TXWI_STRUC));
+
+ DBGPRINT(RT_DEBUG_OFF, ("TxWI Fields:\n"));
+ DBGPRINT(RT_DEBUG_OFF, ("\tPHYMODE=%d(%s)\n", pTxWI->TxWIPHYMODE, get_phymode_str(pTxWI->TxWIPHYMODE)));
+ DBGPRINT(RT_DEBUG_OFF, ("\tSTBC=%d\n", pTxWI->TxWISTBC));
+ DBGPRINT(RT_DEBUG_OFF, ("\tShortGI=%d\n", pTxWI->TxWIShortGI));
+ DBGPRINT(RT_DEBUG_OFF, ("\tBW=%d(%sMHz)\n", pTxWI->TxWIBW, get_bw_str(pTxWI->TxWIBW)));
+ DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d\n", pTxWI->TxWIMCS));
+ DBGPRINT(RT_DEBUG_OFF, ("\tTxOP=%d(%s)\n", pTxWI->TxWITXOP, TXWI_TXOP_STR(pTxWI->TxWITXOP)));
+ DBGPRINT(RT_DEBUG_OFF, ("\tMpduDensity=%d\n", pTxWI->TxWIMpduDensity));
+ DBGPRINT(RT_DEBUG_OFF, ("\tAMPDU=%d\n", pTxWI->TxWIAMPDU));
+ DBGPRINT(RT_DEBUG_OFF, ("\tTS=%d\n", pTxWI->TxWITS));
+ DBGPRINT(RT_DEBUG_OFF, ("\tCF-ACK=%d\n", pTxWI->TxWICFACK));
+ DBGPRINT(RT_DEBUG_OFF, ("\tMIMO-PS=%d\n", pTxWI->TxWIMIMOps));
+ DBGPRINT(RT_DEBUG_OFF, ("\tNSEQ=%d\n", pTxWI->TxWINSEQ));
+ DBGPRINT(RT_DEBUG_OFF, ("\tACK=%d\n", pTxWI->TxWIACK));
+ DBGPRINT(RT_DEBUG_OFF, ("\tFRAG=%d\n", pTxWI->TxWIFRAG));
+ DBGPRINT(RT_DEBUG_OFF, ("\tWCID=%d\n", pTxWI->TxWIWirelessCliID));
+ DBGPRINT(RT_DEBUG_OFF, ("\tBAWinSize=%d\n", pTxWI->TxWIBAWinSize));
+ DBGPRINT(RT_DEBUG_OFF, ("\tMPDUtotalByteCnt=%d\n", pTxWI->TxWIMPDUByteCnt));
+#ifdef RLT_MAC
+ DBGPRINT(RT_DEBUG_OFF, ("\tPID=%d\n", pTxWI->TxWIPacketId));
+#endif /* RLT_MAC */
+}
+
+
+VOID dump_rxwi(RTMP_ADAPTER *pAd, RXWI_STRUC *pRxWI)
+{
+ hex_dump("RxWI Raw Data", (UCHAR *)pRxWI, sizeof(RXWI_STRUC));
+
+ DBGPRINT(RT_DEBUG_OFF, ("RxWI Fields:\n"));
+ DBGPRINT(RT_DEBUG_OFF, ("\tWCID=%d\n", pRxWI->RxWIWirelessCliID));
+ DBGPRINT(RT_DEBUG_OFF, ("\tPhyMode=%d(%s)\n", pRxWI->RxWIPhyMode, get_phymode_str(pRxWI->RxWIPhyMode)));
+#ifdef RT65xx
+ if (IS_RT65XX(pAd) && (pRxWI->RxWIPhyMode == MODE_VHT))
+ DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d(Nss:%d, MCS:%d)\n", pRxWI->RxWIMCS, (pRxWI->RxWIMCS >> 4), (pRxWI->RxWIMCS & 0xf)));
+ else
+#endif /* RT65xx */
+ DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d\n", pRxWI->RxWIMCS));
+ DBGPRINT(RT_DEBUG_OFF, ("\tBW=%d\n", pRxWI->RxWIBW));
+ DBGPRINT(RT_DEBUG_OFF, ("\tSGI=%d\n", pRxWI->RxWISGI));
+ DBGPRINT(RT_DEBUG_OFF, ("\tMPDUtotalByteCnt=%d\n", pRxWI->RxWIMPDUByteCnt));
+ DBGPRINT(RT_DEBUG_OFF, ("\tTID=%d\n", pRxWI->RxWITID));
+ DBGPRINT(RT_DEBUG_OFF, ("\tSTBC=%d\n", pRxWI->RxWISTBC));
+ DBGPRINT(RT_DEBUG_OFF, ("\tkey_idx=%d\n", pRxWI->RxWIKeyIndex));
+ DBGPRINT(RT_DEBUG_OFF, ("\tBSS_IDX=%d\n", pRxWI->RxWIBSSID));
+}
+
+
+static UCHAR *txinfo_type_str[]={"PKT", "", "CMD", "RSV", "Invalid"};
+static UCHAR *txinfo_d_port_str[]={"WLAN", "CPU_RX", "CPU_TX", "HOST", "VIRT_RX", "VIRT_TX", "DROP", "Invalid"};
+static UCHAR *txinfo_que_str[]={"MGMT", "HCCA", "EDCA_1", "EDCA_2", "Invalid"};
+
+#define TXINFO_TYPE_STR(_x) ((_x)<=3 ? txinfo_type_str[_x] : txinfo_type_str[4])
+#define TXINFO_DPORT_STR(_x) ((_x) <= 6 ? txinfo_d_port_str[_x]: txinfo_d_port_str[7])
+#define TXINFO_QUE_STR(_x) ((_x) <= 3 ? txinfo_que_str[_x]: txinfo_que_str[4])
+
+VOID dump_txinfo(RTMP_ADAPTER *pAd, TXINFO_STRUC *pTxInfo)
+{
+ hex_dump("TxInfo Raw Data: ", (UCHAR *)pTxInfo, sizeof(TXINFO_STRUC));
+
+ DBGPRINT(RT_DEBUG_OFF, ("TxInfo Fields:\n"));
+
+#ifdef RLT_MAC
+{
+ struct _TXINFO_NMAC_PKT *pkt_txinfo = (struct _TXINFO_NMAC_PKT *)pTxInfo;
+
+ DBGPRINT(RT_DEBUG_OFF, ("\tInfo_Type=%d(%s)\n", pkt_txinfo->info_type, TXINFO_TYPE_STR(pkt_txinfo->info_type)));
+ DBGPRINT(RT_DEBUG_OFF, ("\td_port=%d(%s)\n", pkt_txinfo->d_port, TXINFO_DPORT_STR(pkt_txinfo->d_port)));
+ DBGPRINT(RT_DEBUG_OFF, ("\tQSEL=%d(%s)\n", pkt_txinfo->QSEL, TXINFO_QUE_STR(pkt_txinfo->QSEL)));
+ DBGPRINT(RT_DEBUG_OFF, ("\tWIV=%d\n", pkt_txinfo->wiv));
+ DBGPRINT(RT_DEBUG_OFF, ("\t802.11=%d\n", pkt_txinfo->pkt_80211));
+ DBGPRINT(RT_DEBUG_OFF, ("\tcso=%d\n", pkt_txinfo->cso));
+ DBGPRINT(RT_DEBUG_OFF, ("\ttso=%d\n", pkt_txinfo->tso));
+ DBGPRINT(RT_DEBUG_OFF, ("\tpkt_len=0x%x\n", pkt_txinfo->pkt_len));
+}
+#endif /* RLT_MAC */
+
+#ifdef RTMP_MAC
+ DBGPRINT(RT_DEBUG_OFF, ("\n"));
+#endif /* RTMP_MAC */
+}
+
+
+#ifdef DBG_DIAGNOSE
+static VOID dumpTxBlk(TX_BLK *pTxBlk)
+{
+ NDIS_PACKET *pPacket;
+ int i, frameNum;
+ PQUEUE_ENTRY pQEntry;
+
+ DBGPRINT(RT_DEBUG_TRACE,("Dump TX_BLK Structure:\n"));
+ DBGPRINT(RT_DEBUG_TRACE,("\tTxFrameType=%d!\n", pTxBlk->TxFrameType));
+ DBGPRINT(RT_DEBUG_TRACE,("\tTotalFrameLen=%d\n", pTxBlk->TotalFrameLen));
+ DBGPRINT(RT_DEBUG_TRACE,("\tTotalFrameNum=%ld!\n", pTxBlk->TxPacketList.Number));
+ DBGPRINT(RT_DEBUG_TRACE,("\tTotalFragNum=%d!\n", pTxBlk->TotalFragNum));
+ DBGPRINT(RT_DEBUG_TRACE,("\tpPacketList=\n"));
+
+ frameNum = pTxBlk->TxPacketList.Number;
+
+ for(i=0; i < frameNum; i++)
+ { int j;
+ UCHAR *pBuf;
+
+ pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
+ pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
+ if (pPacket)
+ {
+ pBuf = GET_OS_PKT_DATAPTR(pPacket);
+ DBGPRINT(RT_DEBUG_TRACE,("\t\t[%d]:ptr=0x%x, Len=%d!\n", i, (UINT32)(GET_OS_PKT_DATAPTR(pPacket)), GET_OS_PKT_LEN(pPacket)));
+ DBGPRINT(RT_DEBUG_TRACE,("\t\t"));
+ for (j =0 ; j < GET_OS_PKT_LEN(pPacket); j++)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("%02x ", (pBuf[j] & 0xff)));
+ if (j == 16)
+ break;
+ }
+ InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
+ }
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("\tWcid=%d!\n", pTxBlk->Wcid));
+ DBGPRINT(RT_DEBUG_TRACE,("\tapidx=%d!\n", pTxBlk->apidx));
+ DBGPRINT(RT_DEBUG_TRACE,("----EndOfDump\n"));
+
+}
+#endif
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ API for MLME to transmit management frame to AP (BSS Mode)
+ or station (IBSS Mode)
+
+ Arguments:
+ pAd Pointer to our adapter
+ pData Pointer to the outgoing 802.11 frame
+ Length Size of outgoing management frame
+
+ Return Value:
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_PENDING
+ NDIS_STATUS_SUCCESS
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS MiniportMMRequest(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR QueIdx,
+ IN UCHAR *pData,
+ IN UINT Length)
+{
+ PNDIS_PACKET pPacket;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ ULONG FreeNum;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+ UCHAR rtmpHwHdr[40];
+ BOOLEAN bUseDataQ = FALSE, FlgDataQForce = FALSE, FlgIsLocked = FALSE;
+ int retryCnt = 0, hw_len = TXINFO_SIZE + TXWISize + TSO_SIZE;
+
+
+ ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
+
+ if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG)
+ {
+ bUseDataQ = TRUE;
+ QueIdx &= (~MGMT_USE_QUEUE_FLAG);
+ }
+
+#ifdef FPGA_MODE
+ if (pAd->fpga_on & 0x1) {
+ if (pAd->tx_kick_cnt > 0) {
+ if (pAd->tx_kick_cnt < 0xffff)
+ pAd->tx_kick_cnt--;
+ }
+ else
+ return NDIS_STATUS_FAILURE;
+
+ QueIdx = 0;
+ bUseDataQ = TRUE;
+ }
+#endif /* FPGA_MODE */
+
+
+ do
+ {
+ /* Reset is in progress, stop immediately*/
+ if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
+ fRTMP_ADAPTER_HALT_IN_PROGRESS |
+ fRTMP_ADAPTER_NIC_NOT_EXIST)) ||
+ !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
+ )
+ {
+ Status = NDIS_STATUS_FAILURE;
+ break;
+ }
+
+
+ /* Check Free priority queue*/
+ /* Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.*/
+ {
+ FreeNum = GET_MGMTRING_FREENO(pAd);
+ }
+
+ if ((FreeNum > 0))
+ {
+ /* We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870*/
+ NdisZeroMemory(&rtmpHwHdr, hw_len);
+ Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, hw_len, pData, Length);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
+ break;
+ }
+
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef UAPSD_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ UAPSD_MR_QOS_NULL_HANDLE(pAd, pData, pPacket);
+ }
+#endif /* UAPSD_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ Status = MlmeHardTransmit(pAd, QueIdx, pPacket, FlgDataQForce, FlgIsLocked);
+ if (Status == NDIS_STATUS_SUCCESS)
+ retryCnt = 0;
+ else
+ RELEASE_NDIS_PACKET(pAd, pPacket, Status);
+ }
+ else
+ {
+ pAd->RalinkCounters.MgmtRingFullCount++;
+ DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
+ QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
+ }
+ } while (retryCnt > 0);
+
+
+
+ return Status;
+}
+
+
+#ifdef CONFIG_AP_SUPPORT
+/*
+ ========================================================================
+
+ Routine Description:
+ Copy frame from waiting queue into relative ring buffer and set
+ appropriate ASIC register to kick hardware transmit function
+
+ Arguments:
+ pAd Pointer to our adapter
+ pBuffer Pointer to memory of outgoing frame
+ Length Size of outgoing management frame
+ FlgIsDeltsFrame 1: the frame is a DELTS frame
+
+ Return Value:
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_PENDING
+ NDIS_STATUS_SUCCESS
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+void AP_QueuePsActionPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pMacEntry,
+ IN PNDIS_PACKET pPacket,
+ IN BOOLEAN FlgIsDeltsFrame,
+ IN BOOLEAN FlgIsLocked,
+ IN UCHAR MgmtQid)
+{
+
+#ifdef UAPSD_SUPPORT
+#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY
+ PNDIS_PACKET DuplicatePkt = NULL;
+#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */
+#endif /* UAPSD_SUPPORT */
+
+ /* Note: for original mode of 4 AC are UAPSD, if station want to change
+ the mode of a AC to legacy PS, we dont know where to put the
+ response;
+ 1. send the response;
+ 2. but the station is in ps mode, so queue the response;
+ 3. we should queue the reponse to UAPSD queue because the station
+ is not yet change its mode to legacy ps AC;
+ 4. so AP should change its mode to legacy ps AC only when the station
+ sends a trigger frame and we send out the reponse;
+ 5. the mechanism is too complicate; */
+
+#ifdef UAPSD_SUPPORT
+ /*
+ If the frame is action frame and the VO is UAPSD, we can not send the
+ frame to VO queue, we need to send to legacy PS queue; or the frame
+ maybe not got from QSTA.
+ */
+/* if ((pMacEntry->bAPSDDeliverEnabledPerAC[MgmtQid]) &&*/
+/* (FlgIsDeltsFrame == 0))*/
+ if (pMacEntry->bAPSDDeliverEnabledPerAC[MgmtQid])
+ {
+ /* queue the management frame to VO queue if VO is deliver-enabled */
+ DBGPRINT(RT_DEBUG_TRACE, ("ps> mgmt to UAPSD queue %d ... (IsDelts: %d)\n",
+ MgmtQid, FlgIsDeltsFrame));
+
+#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY
+ if (!pMacEntry->bAPSDAllAC)
+ {
+ /* duplicate one packet to legacy PS queue */
+ RTMP_SET_PACKET_UAPSD(pPacket, 0, MgmtQid);
+ DuplicatePkt = RTMP_DUPLICATE_PACKET(pAd, pPacket, pMacEntry->apidx);
+ }
+ else
+#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */
+ {
+ RTMP_SET_PACKET_UAPSD(pPacket, 1, MgmtQid);
+ }
+
+ UAPSD_PacketEnqueue(pAd, pMacEntry, pPacket, MgmtQid);
+
+ if (pMacEntry->bAPSDAllAC)
+ {
+ /* mark corresponding TIM bit in outgoing BEACON frame*/
+ WLAN_MR_TIM_BIT_SET(pAd, pMacEntry->apidx, pMacEntry->Aid);
+ }
+ else
+ {
+#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY
+ /* duplicate one packet to legacy PS queue */
+
+ /*
+ Sometimes AP will send DELTS frame to STA but STA will not
+ send any trigger frame to get the DELTS frame.
+ We must force to send it so put another one in legacy PS
+ queue.
+ */
+ if (DuplicatePkt != NULL)
+ {
+ pPacket = DuplicatePkt;
+ goto Label_Legacy_PS;
+ }
+#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */
+ }
+ }
+ else
+#endif /* UAPSD_SUPPORT */
+ {
+/* DuplicatePkt = DuplicatePacket(get_netdev_from_bssid(pAd, pMacEntry->apidx), pPacket, pMacEntry->apidx);*/
+
+#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY
+Label_Legacy_PS:
+#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */
+ if (pMacEntry->PsQueue.Number >= MAX_PACKETS_IN_PS_QUEUE)
+ {
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_RESOURCES);
+ return;
+ }
+ else
+ {
+ ULONG IrqFlags=0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ps> mgmt to legacy ps queue... (%d)\n", FlgIsDeltsFrame));
+
+ if (FlgIsLocked == FALSE)
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+ InsertTailQueue(&pMacEntry->PsQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
+ if (FlgIsLocked == FALSE)
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+ }
+
+ /* mark corresponding TIM bit in outgoing BEACON frame*/
+ WLAN_MR_TIM_BIT_SET(pAd, pMacEntry->apidx, pMacEntry->Aid);
+ }
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Copy frame from waiting queue into relative ring buffer and set
+ appropriate ASIC register to kick hardware transmit function
+
+ Arguments:
+ pAd Pointer to our adapter
+ pBuffer Pointer to memory of outgoing frame
+ Length Size of outgoing management frame
+
+ Return Value:
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_PENDING
+ NDIS_STATUS_SUCCESS
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS MlmeHardTransmit(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket,
+ IN BOOLEAN FlgDataQForce,
+ IN BOOLEAN FlgIsLocked)
+{
+#ifdef CONFIG_AP_SUPPORT
+ MAC_TABLE_ENTRY *pEntry = NULL;
+ PHEADER_802_11 pHeader_802_11;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+#endif /* CONFIG_AP_SUPPORT */
+ PACKET_INFO PacketInfo;
+ PUCHAR pSrcBufVA;
+ UINT SrcBufLen;
+
+ if ((pAd->Dot11_H.RDMode != RD_NORMAL_MODE)
+#ifdef CARRIER_DETECTION_SUPPORT
+#ifdef CONFIG_AP_SUPPORT
+ ||(isCarrierDetectExist(pAd) == TRUE)
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* CARRIER_DETECTION_SUPPORT */
+ )
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
+ if (pSrcBufVA == NULL)
+ return NDIS_STATUS_FAILURE;
+
+#ifdef CONFIG_AP_SUPPORT
+ pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWISize + TSO_SIZE);
+
+ /*
+ Section 11.2.1.1 STA Power Management modes of IEEE802.11-2007:
+ The Power Managment bit shall not be set in any management frame,
+ except an Action frame.
+
+ So in the 'baseline' test plan
+ (Wi-Fi 802.11 WPA2, WPA, WEP Interoperability Test Plan),
+ Section 2.2.6, the following Requirement:
+ APs shall ignore the power save bit in any received Authenticate and
+ (Re) Associate, and shall assume that the station is awake for the
+ response.
+ */
+
+ /*
+ IEEE802.11, 11.2.1.4 AP operation during the contention period f)
+ A single buffered MSDU or management frame for a STA in the PS mode shall
+ be forwarded to the STA after a PS-Poll has been received from that STA.
+ The More Data field shall be set to indicate the presence of further
+ buffered MSDUs or "management frames" for the polling STA.
+ */
+
+ /*
+ IEEE802.11e, 11.2.1.4 Power management with APSD,
+ An unscheduled SP ends after the QAP has attempted to transmit at least
+ one MSDU or MMPDU associated with a delivery-enabled AC and destined for
+ the non-AP QSTA, but no more than the number indicated in the Max SP
+ Length field if the field has a nonzero value.
+ */
+
+ if ((pHeader_802_11->FC.Type == BTYPE_DATA) ||
+ (pHeader_802_11->FC.Type == BTYPE_MGMT))
+ {
+ if (pHeader_802_11->FC.SubType != SUBTYPE_QOS_NULL)
+ pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
+ }
+
+
+
+ if ((pEntry != NULL) &&
+ (pEntry->PsMode == PWR_SAVE) &&
+ (((pHeader_802_11->FC.Type == BTYPE_DATA) &&
+ (pHeader_802_11->FC.SubType != SUBTYPE_NULL_FUNC) &&
+ (pHeader_802_11->FC.SubType != SUBTYPE_QOS_NULL)) ||
+ ((pHeader_802_11->FC.Type == BTYPE_MGMT) &&
+ (pHeader_802_11->FC.SubType == SUBTYPE_ACTION)) ||
+ ((pHeader_802_11->FC.Type == BTYPE_MGMT) &&
+ (pHeader_802_11->FC.SubType == SUBTYPE_ACTION_NO_ACK))))
+ {
+ /* the peer is in PS mode, we need to queue the management frame */
+ UINT8 FlgIsDeltsFrame = 0, MgmtQid = QID_AC_VO;
+
+ /*
+ 1. Data & Not QoS Null, or
+ 2. Management & Action, or
+ 3. Management & Action No ACK;
+ */
+ DBGPRINT(RT_DEBUG_TRACE, ("STA in ps mode, queue the mgmt frame\n"));
+ RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
+ RTMP_SET_PACKET_MGMT_PKT(pPacket, 1); /* is management frame */
+ RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(pPacket, 0); /* default to management queue */
+
+
+ if (FlgDataQForce == TRUE)
+ RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(pPacket, 1); /* force to data queue */
+
+ if ((pHeader_802_11->FC.Type == BTYPE_MGMT) &&
+ (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
+ {
+ FRAME_ADDBA_REQ *pFrameBa = (FRAME_ADDBA_REQ *)pHeader_802_11;
+ if (pFrameBa->Category == CATEGORY_BA)
+ MgmtQid = QueIdx;
+ }
+
+
+ AP_QueuePsActionPacket(pAd, pEntry, pPacket, FlgIsDeltsFrame,
+ FlgIsLocked, MgmtQid);
+ return NDIS_STATUS_SUCCESS;
+ }
+ else
+#endif /* CONFIG_AP_SUPPORT */
+ {
+ return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
+ }
+}
+
+
+NDIS_STATUS MlmeHardTransmitMgmtRing(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket)
+{
+ PACKET_INFO PacketInfo;
+ UCHAR *pSrcBufVA;
+ UINT SrcBufLen;
+ HEADER_802_11 *pHeader_802_11;
+ BOOLEAN bAckRequired, bInsertTimestamp;
+ UCHAR MlmeRate;
+ TXWI_STRUC *pFirstTxWI;
+ MAC_TABLE_ENTRY *pMacEntry = NULL;
+ UCHAR PID;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
+
+ /* Make sure MGMT ring resource won't be used by other threads*/
+ RTMP_SEM_LOCK(&pAd->MgmtRingLock);
+ if (pSrcBufVA == NULL)
+ {
+ /* The buffer shouldn't be NULL*/
+ RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
+ return NDIS_STATUS_FAILURE;
+ }
+
+
+ pFirstTxWI = (TXWI_STRUC *)(pSrcBufVA + TXINFO_SIZE);
+ pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TSO_SIZE + TXWISize);
+
+ if (pHeader_802_11->Addr1[0] & 0x01)
+ {
+ MlmeRate = pAd->CommonCfg.BasicMlmeRate;
+ }
+ else
+ {
+ MlmeRate = pAd->CommonCfg.MlmeRate;
+ }
+
+ /* Verify Mlme rate for a / g bands.*/
+ if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band*/
+ MlmeRate = RATE_6;
+
+ if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
+ (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
+ {
+ pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
+ }
+
+
+ /* Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)*/
+ /* Snice it's been set to 0 while on MgtMacHeaderInit*/
+ /* By the way this will cause frame to be send on PWR_SAVE failed.*/
+
+ pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; /* (pAd->StaCfg.Psm == PWR_SAVE);*/
+
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+ pHeader_802_11->FC.MoreData = RTMP_GET_PACKET_MOREDATA(pPacket);
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ bInsertTimestamp = FALSE;
+ if (pHeader_802_11->FC.Type == BTYPE_CNTL) /* must be PS-POLL*/
+ {
+ bAckRequired = FALSE;
+ }
+ else /* BTYPE_MGMT or BTYPE_DATA(must be NULL frame)*/
+ {
+ if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST*/
+ {
+ bAckRequired = FALSE;
+ pHeader_802_11->Duration = 0;
+ }
+ else
+ {
+ bAckRequired = TRUE;
+ pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
+ if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) && (pHeader_802_11->FC.Type == BTYPE_MGMT))
+ {
+ bInsertTimestamp = TRUE;
+ bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Response*/
+ }
+ else if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) && (pHeader_802_11->FC.Type == BTYPE_MGMT))
+ {
+ bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Request*/
+ }
+ }
+ }
+
+ pHeader_802_11->Sequence = pAd->Sequence++;
+ if (pAd->Sequence >0xfff)
+ pAd->Sequence = 0;
+
+ /*
+ Before radar detection done, mgmt frame can not be sent but probe req
+ Because we need to use probe req to trigger driver to send probe req in passive scan
+ */
+ if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
+ && (pAd->CommonCfg.bIEEE80211H == 1)
+ && (pAd->Dot11_H.RDMode != RD_NORMAL_MODE))
+ {
+ RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
+ return NDIS_STATUS_FAILURE;
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
+#endif
+
+
+ /*
+ fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
+ should always has only one physical buffer, and the whole frame size equals
+ to the first scatter buffer size
+ */
+
+
+ /*
+ Initialize TX Descriptor
+ For inter-frame gap, the number is for this frame and next frame
+ For MLME rate, we will fix as 2Mb to match other vendor's implement
+ */
+ /*pAd->CommonCfg.MlmeTransmit.field.MODE = 1;*/
+
+ /*
+ management frame doesn't need encryption.
+ so use RESERVED_WCID no matter u are sending to specific wcid or not
+ */
+ PID = PID_MGMT;
+
+
+ if (pMacEntry == NULL)
+ {
+ RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
+ 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWISize - TSO_SIZE), PID, 0,
+ (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE,
+ &pAd->CommonCfg.MlmeTransmit);
+ }
+ else
+ {
+ /* dont use low rate to send QoS Null data frame */
+ RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
+ bInsertTimestamp, FALSE, bAckRequired, FALSE,
+ 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWISize - TSO_SIZE),
+ pMacEntry->MaxHTPhyMode.field.MCS, 0,
+ (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
+ IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange(pAd, (PUCHAR)pFirstTxWI, TYPE_TXWI);
+#endif
+
+//+++Add by shiang for debug
+if (0) {
+ hex_dump("TxMgmtPkt", (UCHAR *)pHeader_802_11, ((SrcBufLen - TXINFO_SIZE - TXWISize - TSO_SIZE) > 7000 ? 7000 : (SrcBufLen - TXINFO_SIZE - TXWISize - TSO_SIZE)));
+}
+//---Add by shiang for debug
+
+ /* Now do hardware-depened kick out.*/
+ HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
+
+ /* Make sure to release MGMT ring resource*/
+/* if (!IrqState)*/
+ RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/********************************************************************************
+
+ New DeQueue Procedures.
+
+ ********************************************************************************/
+#define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
+ do{ \
+ if (bIntContext == FALSE) \
+ RTMP_IRQ_LOCK((lock), IrqFlags); \
+ }while(0)
+
+#define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
+ do{ \
+ if (bIntContext == FALSE) \
+ RTMP_IRQ_UNLOCK((lock), IrqFlags); \
+ }while(0)
+
+
+/*
+ ========================================================================
+ Tx Path design algorithm:
+ Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
+ Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
+ Classification Rule=>
+ Multicast: (*addr1 & 0x01) == 0x01
+ Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
+ 11N Rate : If peer support HT
+ (1).AMPDU -- If TXBA is negotiated.
+ (2).AMSDU -- If AMSDU is capable for both peer and ourself.
+ *). AMSDU can embedded in a AMPDU, but now we didn't support it.
+ (3).Normal -- Other packets which send as 11n rate.
+
+ B/G Rate : If peer is b/g only.
+ (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
+ (2).Normal -- Other packets which send as b/g rate.
+ Fragment:
+ The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
+
+ Classified Packet Handle Rule=>
+ Multicast:
+ No ACK, pTxBlk->bAckRequired = FALSE;
+ No WMM, pTxBlk->bWMM = FALSE;
+ No piggyback, pTxBlk->bPiggyBack = FALSE;
+ Force LowRate, pTxBlk->bForceLowRate = TRUE;
+ Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
+ the same policy to handle it.
+ Force LowRate, pTxBlk->bForceLowRate = TRUE;
+
+ 11N Rate :
+ No piggyback, pTxBlk->bPiggyBack = FALSE;
+
+ (1).AMSDU
+ pTxBlk->bWMM = TRUE;
+ (2).AMPDU
+ pTxBlk->bWMM = TRUE;
+ (3).Normal
+
+ B/G Rate :
+ (1).ARALINK
+
+ (2).Normal
+ ========================================================================
+*/
+static UCHAR TxPktClassification(
+ IN RTMP_ADAPTER *pAd,
+ IN PNDIS_PACKET pPacket)
+{
+ UCHAR TxFrameType = TX_UNKOWN_FRAME;
+ UCHAR Wcid;
+ MAC_TABLE_ENTRY *pMacEntry = NULL;
+#ifdef DOT11_N_SUPPORT
+ BOOLEAN bHTRate = FALSE;
+#endif /* DOT11_N_SUPPORT */
+
+ Wcid = RTMP_GET_PACKET_WCID(pPacket);
+ if (Wcid == MCAST_WCID)
+ { /* Handle for RA is Broadcast/Multicast Address.*/
+ return TX_MCAST_FRAME;
+ }
+
+ /* Handle for unicast packets*/
+ pMacEntry = &pAd->MacTab.Content[Wcid];
+ if (RTMP_GET_PACKET_LOWRATE(pPacket))
+ { /* It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame*/
+ TxFrameType = TX_LEGACY_FRAME;
+ }
+#ifdef DOT11_N_SUPPORT
+ else if (IS_HT_RATE(pMacEntry))
+ { /* it's a 11n capable packet*/
+
+ /* Depends on HTPhyMode to check if the peer support the HTRate transmission.*/
+ /* Currently didn't support A-MSDU embedded in A-MPDU*/
+ bHTRate = TRUE;
+ if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
+ TxFrameType = TX_LEGACY_FRAME;
+#ifdef UAPSD_SUPPORT
+ else if (RTMP_GET_PACKET_EOSP(pPacket))
+ TxFrameType = TX_LEGACY_FRAME;
+#endif /* UAPSD_SUPPORT */
+ else if(((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
+#ifdef WFA_VHT_PF
+ && (pAd->force_amsdu == FALSE)
+#endif /* WFA_VHT_PF */
+ )
+ return TX_AMPDU_FRAME;
+ else if((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED)
+#ifdef WFA_VHT_PF
+ || (pAd->force_amsdu == TRUE)
+#endif /* WFA_VHT_PF */
+ )
+ )
+ return TX_AMSDU_FRAME;
+ else
+ TxFrameType = TX_LEGACY_FRAME;
+ }
+#endif /* DOT11_N_SUPPORT */
+ else
+ { /* it's a legacy b/g packet.*/
+ if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
+ (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
+ (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)))
+ )
+ { /* if peer support Ralink Aggregation, we use it.*/
+ TxFrameType = TX_RALINK_FRAME;
+ }
+ else
+ {
+ TxFrameType = TX_LEGACY_FRAME;
+ }
+ }
+
+ /* Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.*/
+ if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1)
+ && (TxFrameType == TX_LEGACY_FRAME)
+#ifdef DOT11_N_SUPPORT
+ && ((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) == 0)
+#endif /* DOT11_N_SUPPORT */
+ )
+ TxFrameType = TX_FRAG_FRAME;
+
+ return TxFrameType;
+}
+
+
+BOOLEAN RTMP_FillTxBlkInfo(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk)
+{
+ PACKET_INFO PacketInfo;
+ PNDIS_PACKET pPacket;
+ MAC_TABLE_ENTRY *pMacEntry = NULL;
+
+ pPacket = pTxBlk->pPacket;
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
+#ifdef TX_PKT_SG
+ NdisMoveMemory( &pTxBlk->pkt_info, &PacketInfo, sizeof(PacketInfo));
+#endif /* TX_PKT_SG */
+ pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
+ pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
+ pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
+ pTxBlk->FrameGap = IFS_HTTXOP;
+#ifdef CONFIG_AP_SUPPORT
+ pTxBlk->pMbss = NULL;
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
+ else
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
+
+ /* Default to clear this flag*/
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
+
+#ifdef WAPI_SUPPORT
+ /* Check if this is an WPI data frame*/
+ if ((RTMPIsWapiCipher(pAd, pTxBlk->apidx) == TRUE) &&
+ (RTMP_GET_PACKET_WAI(pTxBlk->pPacket) == FALSE))
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bWPIDataFrame);
+ else
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWPIDataFrame);
+#endif /* WAPI_SUPPORT */
+
+ if (pTxBlk->Wcid == MCAST_WCID)
+ {
+ pTxBlk->pMacEntry = NULL;
+ {
+#ifdef MCAST_RATE_SPECIFIC
+ PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
+ if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
+ pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
+ else
+#endif /* MCAST_RATE_SPECIFIC */
+ pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
+ }
+
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); /* AckRequired = FALSE, when broadcast packet in Adhoc mode.*/
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
+ if (RTMP_GET_PACKET_MOREDATA(pPacket))
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
+ }
+ }
+ else
+ {
+ pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
+ pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
+
+ pMacEntry = pTxBlk->pMacEntry;
+#ifdef CONFIG_AP_SUPPORT
+ pTxBlk->pMbss = pMacEntry->pMbss;
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.*/
+ if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
+ else
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
+
+
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef WDS_SUPPORT
+ if(IS_ENTRY_WDS(pMacEntry))
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bWDSEntry);
+ }
+ else
+#endif /* WDS_SUPPORT */
+#ifdef APCLI_SUPPORT
+ if(IS_ENTRY_APCLI(pMacEntry))
+ {
+ PNDIS_PACKET apCliPkt = NULL;
+
+ /* For each tx packet, update our MAT convert engine databases.*/
+ apCliPkt = (PNDIS_PACKET)MATEngineTxHandle(pAd, pPacket, pMacEntry->MatchAPCLITabIdx, pTxBlk->OpMode);
+ if(apCliPkt)
+ {
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ pPacket = apCliPkt;
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
+ pTxBlk->pPacket = apCliPkt;
+ }
+ pTxBlk->pApCliEntry = &pAd->ApCfg.ApCliTab[pMacEntry->MatchAPCLITabIdx];
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bApCliPacket);
+
+ }
+ else
+#endif /* APCLI_SUPPORT */
+#ifdef CLIENT_WDS
+ if (IS_ENTRY_CLIWDS(pMacEntry))
+ {
+ PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
+ PUCHAR pSA = GET_OS_PKT_DATAPTR(pPacket) + MAC_ADDR_LEN;
+ if (((pMacEntry->apidx < MAX_MBSSID_NUM(pAd))
+ && !MAC_ADDR_EQUAL(pSA, pAd->ApCfg.MBSSID[pMacEntry->apidx].Bssid))
+ || !MAC_ADDR_EQUAL(pDA, pMacEntry->Addr)
+ )
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bClientWDSFrame);
+ }
+ }
+ else
+#endif /* CLIENT_WDS */
+ if (IS_ENTRY_CLIENT(pMacEntry))
+ { }
+ else
+ return FALSE;
+
+ /* If both of peer and us support WMM, enable it.*/
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+
+ if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
+ {
+ if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
+ ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1))
+ )
+ { /* Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.*/
+ pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
+
+#ifdef WAPI_SUPPORT
+ /* According to WAPIA certification description, WAI packets can not
+ include QoS header */
+ if (RTMP_GET_PACKET_WAI(pTxBlk->pPacket))
+ {
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
+ }
+#endif /* WAPI_SUPPORT */
+#ifdef DOT11_N_SUPPORT
+ /* Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it? */
+ if (IS_HT_STA(pTxBlk->pMacEntry) &&
+ (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
+ ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
+ {
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
+ }
+#endif /* DOT11_N_SUPPORT */
+ }
+
+#ifdef DOT11_N_SUPPORT
+ if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
+ (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
+ { /* Currently piggy-back only support when peer is operate in b/g mode.*/
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
+ }
+#endif /* DOT11_N_SUPPORT */
+
+ if (RTMP_GET_PACKET_MOREDATA(pPacket))
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
+ }
+#ifdef UAPSD_SUPPORT
+ if (RTMP_GET_PACKET_EOSP(pPacket))
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
+ }
+#endif /* UAPSD_SUPPORT */
+ }
+ else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
+ }
+
+ pMacEntry->DebugTxCount++;
+ }
+
+
+ pAd->LastTxRate = (USHORT)pTxBlk->pTransmit->word;
+
+ return TRUE;
+}
+
+
+BOOLEAN CanDoAggregateTransmit(
+ IN RTMP_ADAPTER *pAd,
+ IN NDIS_PACKET *pPacket,
+ IN TX_BLK *pTxBlk)
+{
+ int minLen = LENGTH_802_3;
+
+ /*DBGPRINT(RT_DEBUG_TRACE, ("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType));*/
+
+ if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
+ return FALSE;
+
+ if (RTMP_GET_PACKET_DHCP(pPacket) ||
+ RTMP_GET_PACKET_EAPOL(pPacket) ||
+ RTMP_GET_PACKET_WAI(pPacket)
+ )
+ return FALSE;
+
+ /* Make sure the first packet has non-zero-length data payload */
+ if (RTMP_GET_PACKET_VLAN(pPacket))
+ minLen += LENGTH_802_1Q; /* VLAN tag */
+ else if (RTMP_GET_PACKET_LLCSNAP(pPacket))
+ minLen += 8; /* SNAP hdr Len*/
+ if (minLen >= GET_OS_PKT_LEN(pPacket))
+ return FALSE;
+
+ if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
+ ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
+ { /* For AMSDU, allow the packets with total length < max-amsdu size*/
+ return FALSE;
+ }
+
+ if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
+ (pTxBlk->TxPacketList.Number == 2))
+ { /* For RALINK-Aggregation, allow two frames in one batch.*/
+ return FALSE;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ if ((MAC_ADDR_EQUAL(GET_OS_PKT_DATAPTR(pTxBlk->pPacket), GET_OS_PKT_DATAPTR(pPacket))) && (pAd->OpMode == OPMODE_AP)) /* unicast to same STA*/
+ return TRUE;
+ else
+#endif /* CONFIG_AP_SUPPORT */
+ return FALSE;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ To do the enqueue operation and extract the first item of waiting
+ list. If a number of available shared memory segments could meet
+ the request of extracted item, the extracted item will be fragmented
+ into shared memory segments.
+
+ Arguments:
+ pAd Pointer to our adapter
+ pQueue Pointer to Waiting Queue
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPDeQueuePacket(
+ IN RTMP_ADAPTER *pAd,
+ IN BOOLEAN bIntContext,
+ IN UCHAR QIdx,
+ IN INT Max_Tx_Packets)
+{
+ PQUEUE_ENTRY pEntry = NULL;
+ PNDIS_PACKET pPacket;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ UCHAR Count=0;
+ PQUEUE_HEADER pQueue;
+ ULONG FreeNumber[NUM_OF_TX_RING];
+ UCHAR QueIdx, sQIdx, eQIdx;
+ unsigned long IrqFlags = 0;
+ BOOLEAN hasTxDesc = FALSE;
+ TX_BLK TxBlk, *pTxBlk;
+
+#ifdef DBG_DIAGNOSE
+ BOOLEAN firstRound;
+ RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
+#endif
+
+
+ if (QIdx == NUM_OF_TX_RING)
+ {
+ sQIdx = 0;
+#ifdef CONFIG_MULTI_CHANNEL
+ eQIdx = QID_HCCA; /* 5 ACs, start from 0.*/
+#else
+ eQIdx = QID_AC_VO; /* 4 ACs, start from 0.*/
+#endif /* CONFIG_MULTI_CHANNEL */
+
+ }
+ else
+ {
+ sQIdx = eQIdx = QIdx;
+ }
+
+ for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
+ {
+ Count=0;
+
+ RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags);
+
+#ifdef DBG_DIAGNOSE
+ firstRound = ((QueIdx == 0) ? TRUE : FALSE);
+#endif /* DBG_DIAGNOSE */
+
+ while (1)
+ {
+ if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
+ fRTMP_ADAPTER_RADIO_OFF |
+ fRTMP_ADAPTER_RESET_IN_PROGRESS |
+ fRTMP_ADAPTER_HALT_IN_PROGRESS |
+#ifdef CONFIG_MULTI_CHANNEL
+ fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET |
+#endif /* CONFIG_MULTI_CHANNEL */
+ fRTMP_ADAPTER_NIC_NOT_EXIST
+ )))
+
+ )
+ {
+ RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
+ return;
+ }
+#ifdef CONFIG_MULTI_CHANNEL
+ if ((pAd->MultiChannelFlowCtl & (1 << QueIdx)) == (1 << QueIdx))
+ {
+ break;
+ }
+#endif /* CONFIG_MULTI_CHANNEL */
+
+
+ if (Count >= Max_Tx_Packets)
+ break;
+
+ DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ if (&pAd->TxSwQueue[QueIdx] == NULL)
+ {
+#ifdef DBG_DIAGNOSE
+ if (firstRound == TRUE)
+ pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
+#endif /* DBG_DIAGNOSE */
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ break;
+ }
+
+
+ /* probe the Queue Head*/
+ pQueue = &pAd->TxSwQueue[QueIdx];
+ if ((pEntry = pQueue->Head) == NULL)
+ {
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ break;
+ }
+
+ pTxBlk = &TxBlk;
+ NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
+
+ pTxBlk->QueIdx = QueIdx;
+
+#ifdef VENDOR_FEATURE1_SUPPORT
+ pTxBlk->HeaderBuf = (UCHAR *)pTxBlk->HeaderBuffer;
+#endif /* VENDOR_FEATURE1_SUPPORT */
+
+ pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
+
+#ifdef CONFIG_AP_SUPPORT
+ if (RTMP_GET_PACKET_MGMT_PKT(pPacket) == 1)
+ {
+ /* this is a management frame */
+ NDIS_STATUS status;
+
+ pEntry = RemoveHeadQueue(pQueue);
+
+ status = MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("Transmit queued management frame error!\n"));
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ }
+
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ Count++;
+ continue;
+ }
+ else
+ {
+ /*when WDS Jam happen, drop following 1min to HW TxRing Pkts*/
+ MAC_TABLE_ENTRY *pMacEntry = NULL;
+ UCHAR RAWcid;
+ RAWcid = RTMP_GET_PACKET_WCID(pPacket);
+ pMacEntry = &pAd->MacTab.Content[RAWcid];
+
+#ifdef WDS_SUPPORT
+ /*
+ It WDS life checking.
+ WDS need to check the peer is come back or not
+ by sending few (2 ~3) WDS Packet out to peer.
+ It must be checked first.
+ */
+ if(IS_ENTRY_WDS(pMacEntry))
+ {
+ ULONG Now32;
+ NdisGetSystemUpTime(&Now32);
+ if(pMacEntry->LockEntryTx && RTMP_TIME_BEFORE(Now32, pMacEntry->TimeStamp_toTxRing + WDS_ENTRY_RETRY_INTERVAL))
+ {
+ pEntry = RemoveHeadQueue(pQueue);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ continue;
+ }
+ else
+ NdisGetSystemUpTime(&pMacEntry->TimeStamp_toTxRing);
+ }
+ else
+#endif /* WDS_SUPPORT */
+ if (!IS_ENTRY_NONE(pMacEntry)
+ && (pMacEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck))
+ {
+ /*
+ Sample Lin, 20100412
+
+ For non-WDS interface, we need to send packet to detect
+ the link periodically; Or when
+ pMacEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck,
+ no any chance to clear pMacEntry->ContinueTxFailCnt.
+
+ EX: When pMacEntry->ContinueTxFailCnt >=
+ pAd->ApCfg.EntryLifeCheck, the condition will not be
+ removed and we will drop all packets for the pEntry.
+ But maybe the signal becomes better.
+ So we try to send a packet periodically and we will
+ get the tx status in tx done interrupt.
+ If the tx status is success, pMacEntry->ContinueTxFailCnt
+ will be cleared to 0.
+ */
+#define ENTRY_RETRY_INTERVAL (100 * OS_HZ / 1000)
+ ULONG Now32;
+ NdisGetSystemUpTime(&Now32);
+ if(RTMP_TIME_BEFORE(Now32, pMacEntry->TimeStamp_toTxRing + ENTRY_RETRY_INTERVAL))
+ {
+ pEntry = RemoveHeadQueue(pQueue);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ continue;
+ }
+ else
+ NdisGetSystemUpTime(&pMacEntry->TimeStamp_toTxRing);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Early check to make sure we have enoguh Tx Resource.*/
+ hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
+ if (!hasTxDesc)
+ {
+ pAd->PrivateInfo.TxRingFullCnt++;
+
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+
+ break;
+ }
+
+ pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
+ pEntry = RemoveHeadQueue(pQueue);
+ pTxBlk->TotalFrameNum++;
+ pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary*/
+ pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
+ pTxBlk->pPacket = pPacket;
+ InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
+
+ if (pTxBlk->TxFrameType & (TX_RALINK_FRAME | TX_AMSDU_FRAME))
+ {
+ // Enhance SW Aggregation Mechanism
+ if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
+ {
+ InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ break;
+ }
+ }
+
+
+ if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
+ {
+ // Enhance SW Aggregation Mechanism
+ if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
+ {
+ InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ break;
+ }
+
+ do{
+ if((pEntry = pQueue->Head) == NULL)
+ break;
+
+ /* For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.*/
+ pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
+ FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
+ hasTxDesc = RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
+ if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
+ break;
+
+ /*Remove the packet from the TxSwQueue and insert into pTxBlk*/
+ pEntry = RemoveHeadQueue(pQueue);
+ ASSERT(pEntry);
+ pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
+
+
+ pTxBlk->TotalFrameNum++;
+ pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); /* The real fragment number maybe vary*/
+ pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
+ InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
+ }while(1);
+
+ if (pTxBlk->TxPacketList.Number == 1)
+ pTxBlk->TxFrameType = TX_LEGACY_FRAME;
+ }
+
+#ifdef RTMP_MAC_USB
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+#endif /* RTMP_MAC_USB */
+
+ Count += pTxBlk->TxPacketList.Number;
+
+ /* Do HardTransmit now.*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ Status = APHardTransmit(pAd, pTxBlk, QueIdx);
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ }
+
+ RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
+
+#ifdef RTMP_MAC_USB
+ if (!hasTxDesc)
+#ifdef CONFIG_MULTI_CHANNEL
+ if ((pAd->MultiChannelFlowCtl & (1 << QueIdx)) != (1 << QueIdx))
+#endif /* CONFIG_MULTI_CHANNEL */
+ RTUSBKickBulkOut(pAd);
+#endif /* RTMP_MAC_USB */
+
+#ifdef BLOCK_NET_IF
+ if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE)
+ && (pAd->TxSwQueue[QueIdx].Number < 1))
+ {
+ releaseNetIf(&pAd->blockQueueTab[QueIdx]);
+ }
+#endif /* BLOCK_NET_IF */
+
+ }
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculates the duration which is required to transmit out frames
+ with given size and specified rate.
+
+ Arguments:
+ pAd Pointer to our adapter
+ Rate Transmit rate
+ Size Frame size in units of byte
+
+ Return Value:
+ Duration number in units of usec
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+USHORT RTMPCalcDuration(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Rate,
+ IN ULONG Size)
+{
+ ULONG Duration = 0;
+
+ if (Rate < RATE_FIRST_OFDM_RATE) /* CCK*/
+ {
+ if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
+ Duration = 96; /* 72+24 preamble+plcp*/
+ else
+ Duration = 192; /* 144+48 preamble+plcp*/
+
+ Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
+ if ((Size << 4) % RateIdTo500Kbps[Rate])
+ Duration ++;
+ }
+ else if (Rate <= RATE_LAST_OFDM_RATE)/* OFDM rates*/
+ {
+ Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension*/
+ Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
+ if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
+ Duration += 4;
+ }
+ else /*mimo rate*/
+ {
+ Duration = 20 + 6; /* 16+4 preamble+plcp + Signal Extension*/
+ }
+
+ return (USHORT)Duration;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Suspend MSDU transmission
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPSuspendMsduTransmission(
+ IN PRTMP_ADAPTER pAd)
+{
+ DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier */
+ /* no carrier detection when scanning */
+ if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+ {
+ CarrierDetectionStop(pAd);
+ }
+#endif
+#endif /* CONFIG_AP_SUPPORT */
+
+ /*
+ Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
+ use Lowbound as R66 value on ScanNextChannel(...)
+ */
+ rtmp_bbp_get_agc(pAd, &pAd->BbpTuning.R66CurrentValue, RX_CHAIN_0);
+
+ pAd->hw_cfg.bbp_bw = pAd->CommonCfg.BBPCurrentBW;
+
+ RTMPSetAGCInitValue(pAd, BW_20);
+
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+ /* abort all TX rings */
+ /*RTMP_IO_WRITE32(pAd, TX_CNTL_CSR, 0x000f0000); */
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Resume MSDU transmission
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPResumeMsduTransmission(
+ IN PRTMP_ADAPTER pAd)
+{
+ DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef CARRIER_DETECTION_SUPPORT
+ /* no carrier detection when scanning*/
+ if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+ CarrierDetectionStart(pAd);
+#endif /* CARRIER_DETECTION_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ /*
+ After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value
+ R66 should not be 0
+ */
+ if (pAd->BbpTuning.R66CurrentValue == 0)
+ {
+ pAd->BbpTuning.R66CurrentValue = 0x38;
+ DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n"));
+ }
+ rtmp_bbp_set_agc(pAd, pAd->BbpTuning.R66CurrentValue, RX_CHAIN_ALL);
+
+ pAd->CommonCfg.BBPCurrentBW = pAd->hw_cfg.bbp_bw;
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+/* sample, for IRQ LOCK to SEM LOCK */
+/*
+ IrqState = pAd->irq_disabled;
+ if (IrqState)
+ RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+ else
+*/
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+}
+
+
+#ifdef DOT11_N_SUPPORT
+UINT deaggregate_AMSDU_announce(
+ IN PRTMP_ADAPTER pAd,
+ PNDIS_PACKET pPacket,
+ IN PUCHAR pData,
+ IN ULONG DataSize,
+ IN UCHAR OpMode)
+{
+ USHORT PayloadSize;
+ USHORT SubFrameSize;
+ PHEADER_802_3 pAMSDUsubheader;
+ UINT nMSDU;
+ UCHAR Header802_3[14];
+
+ PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
+ PNDIS_PACKET pClonePacket;
+
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR FromWhichBSSID = RTMP_GET_PACKET_IF(pPacket);
+ UCHAR VLAN_Size;
+ USHORT VLAN_VID = 0, VLAN_Priority = 0;
+
+
+ if ((FromWhichBSSID < pAd->ApCfg.BssidNum)
+ )
+ VLAN_Size = (pAd->ApCfg.MBSSID[FromWhichBSSID].VLAN_VID != 0) ? LENGTH_802_1Q : 0;
+#ifdef WDS_VLAN_SUPPORT
+ else if ((FromWhichBSSID >= MIN_NET_DEVICE_FOR_WDS) &&
+ (FromWhichBSSID < (MIN_NET_DEVICE_FOR_WDS + MAX_WDS_ENTRY)))
+ {
+ VLAN_Size = (pAd->WdsTab.\
+ WdsEntry[FromWhichBSSID - MIN_NET_DEVICE_FOR_WDS].\
+ VLAN_VID != 0) ? LENGTH_802_1Q : 0;
+ }
+#endif /* WDS_VLAN_SUPPORT */
+ else /* only MBssid support VLAN.*/
+ VLAN_Size = 0;
+#endif /* CONFIG_AP_SUPPORT */
+
+ nMSDU = 0;
+
+ while (DataSize > LENGTH_802_3)
+ {
+
+ nMSDU++;
+
+ /*hex_dump("subheader", pData, 64);*/
+ pAMSDUsubheader = (PHEADER_802_3)pData;
+ /*pData += LENGTH_802_3;*/
+ PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
+ SubFrameSize = PayloadSize + LENGTH_802_3;
+
+
+ if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
+ {
+ break;
+ }
+
+ /*DBGPRINT(RT_DEBUG_TRACE,("%d subframe: Size = %d\n", nMSDU, PayloadSize));*/
+
+ pPayload = pData + LENGTH_802_3;
+ pDA = pData;
+ pSA = pData + MAC_ADDR_LEN;
+
+ /* convert to 802.3 header*/
+ CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ UCHAR WhichBSSID = FromWhichBSSID;
+ if (pRemovedLLCSNAP)
+ {
+ pPayload -= (LENGTH_802_3 + VLAN_Size);
+ PayloadSize += (LENGTH_802_3 + VLAN_Size);
+ /*NdisMoveMemory(pPayload, &Header802_3, LENGTH_802_3);*/
+ }
+ else
+ {
+ pPayload -= VLAN_Size;
+ PayloadSize += VLAN_Size;
+ }
+
+ MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, WhichBSSID);
+
+#ifdef WDS_VLAN_SUPPORT
+ if (VLAN_VID == 0) /* maybe WDS packet */
+ WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+#endif /* WDS_VLAN_SUPPORT */
+
+ RT_VLAN_8023_HEADER_COPY(pAd, VLAN_VID, VLAN_Priority,
+ Header802_3, LENGTH_802_3, pPayload,
+ FromWhichBSSID, TPID);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
+ if (pClonePacket)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+
+ /* A-MSDU has padding to multiple of 4 including subframe header.*/
+ /* align SubFrameSize up to multiple of 4*/
+ SubFrameSize = (SubFrameSize+3)&(~0x3);
+
+
+ if (SubFrameSize > 1528 || SubFrameSize < 32)
+ {
+ break;
+ }
+
+ if (DataSize > SubFrameSize)
+ {
+ pData += SubFrameSize;
+ DataSize -= SubFrameSize;
+ }
+ else
+ {
+ /* end of A-MSDU*/
+ DataSize = 0;
+ }
+ }
+
+ /* finally release original rx packet*/
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+
+ return nMSDU;
+}
+
+
+UINT BA_Reorder_AMSDU_Annnounce(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN UCHAR OpMode)
+{
+ PUCHAR pData;
+ USHORT DataSize;
+ UINT nMSDU = 0;
+
+ pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
+ DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
+
+ nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize, OpMode);
+
+ return nMSDU;
+}
+
+VOID Indicate_AMSDU_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ UINT nMSDU;
+
+ RTMP_UPDATE_OS_PACKET_INFO(pAd, pRxBlk, FromWhichBSSID);
+ RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
+ nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize, pRxBlk->OpMode);
+}
+#endif /* DOT11_N_SUPPORT */
+
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID AssocParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
+ IN PUCHAR pAddr,
+ IN USHORT CapabilityInfo,
+ IN ULONG Timeout,
+ IN USHORT ListenIntv)
+{
+ COPY_MAC_ADDR(AssocReq->Addr, pAddr);
+ /* Add mask to support 802.11b mode only */
+ AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; /* not cf-pollable, not cf-poll-request*/
+ AssocReq->Timeout = Timeout;
+ AssocReq->ListenIntv = ListenIntv;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID DisassocParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
+ IN PUCHAR pAddr,
+ IN USHORT Reason)
+{
+ COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
+ DisassocReq->Reason = Reason;
+}
+
+
+BOOLEAN RTMPCheckEtherType(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN PMAC_TABLE_ENTRY pMacEntry,
+ IN UCHAR OpMode,
+ OUT PUCHAR pUserPriority,
+ OUT PUCHAR pQueIdx)
+{
+ USHORT TypeLen;
+ UCHAR Byte0, Byte1;
+ PUCHAR pSrcBuf;
+ UINT32 pktLen;
+ UINT16 srcPort, dstPort;
+#ifdef CONFIG_AP_SUPPORT
+ MULTISSID_STRUCT *pMbss;
+#endif /* CONFIG_AP_SUPPORT */
+ BOOLEAN bWmmReq;
+
+#ifdef CONFIG_AP_SUPPORT
+/* if (IS_ENTRY_CLIENT(pMacEntry))*/
+/* pMbss = pMacEntry->pMbss;*/
+/* else*/
+/* pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID];*/
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* for APClient, WDS, Mesh, they use MAIN BSS */
+ UCHAR apidx;
+ apidx = RTMP_GET_PACKET_NET_DEVICE(pPacket);
+ if (apidx >= MAX_MBSSID_NUM(pAd))
+ apidx = MAIN_MBSSID;
+ pMbss = &pAd->ApCfg.MBSSID[apidx];
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /*
+ for bc/mc packets, if it has VLAN tag or DSCP field, we also need
+ to get UP for IGMP use.
+ */
+ bWmmReq = (
+#ifdef CONFIG_AP_SUPPORT
+ (
+ (pMbss->bWmmCapable)) ||
+#endif /* CONFIG_AP_SUPPORT */
+ OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
+ && ((pMacEntry) &&
+ ((VALID_WCID(pMacEntry->Aid) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
+ || (pMacEntry->Aid == MCAST_WCID)));
+
+ pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
+ pktLen = GET_OS_PKT_LEN(pPacket);
+
+ ASSERT(pSrcBuf);
+
+ RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
+
+ /* get Ethernet protocol field*/
+ TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13];
+
+ pSrcBuf += LENGTH_802_3; /* Skip the Ethernet Header.*/
+
+ if (TypeLen <= 1500)
+ { /* 802.3, 802.3 LLC*/
+ /*
+ DestMAC(6) + SrcMAC(6) + Lenght(2) +
+ DSAP(1) + SSAP(1) + Control(1) +
+ if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
+ => + SNAP (5, OriginationID(3) + etherType(2))
+ */
+ if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
+ {
+ Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 6, &Byte0, &Byte1);
+ RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
+ TypeLen = (USHORT)((Byte0 << 8) + Byte1);
+ pSrcBuf += 8; /* Skip this LLC/SNAP header*/
+ }
+ else
+ {
+ /*It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.*/
+ }
+ }
+
+ /* If it's a VLAN packet, get the real Type/Length field.*/
+ if (TypeLen == 0x8100)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ USHORT VLAN_VID = 0;
+
+ /* 0x8100 means VLAN packets */
+
+ /* Dest. MAC Address (6-bytes) +
+ Source MAC Address (6-bytes) +
+ Length/Type = 802.1Q Tag Type (2-byte) +
+ Tag Control Information (2-bytes) +
+ Length / Type (2-bytes) +
+ data payload (0-n bytes) +
+ Pad (0-p bytes) +
+ Frame Check Sequence (4-bytes) */
+
+ /* No matter unicast or multicast */
+ /*if (IS_ENTRY_CLIENT(pMacEntry))*/
+#ifdef WDS_VLAN_SUPPORT
+ if (IS_ENTRY_WDS(pMacEntry))
+ {
+ UINT32 WdsId;
+
+ WdsId = RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_WDS;
+ if (WdsId < MAX_WDS_ENTRY)
+ VLAN_VID = pAd->WdsTab.WdsEntry[WdsId].VLAN_VID;
+ }
+ else
+#endif /* WDS_VLAN_SUPPORT */
+ {
+ VLAN_VID = pMbss->VLAN_VID;
+ }
+
+ if (VLAN_VID != 0)
+ {
+ /* check if the packet is my VLAN */
+ /* VLAN tag: 3-bit UP + 1-bit CFI + 12-bit VLAN ID */
+ USHORT vlan_id = *(USHORT *)pSrcBuf;
+
+ vlan_id = cpu2be16(vlan_id);
+ vlan_id = vlan_id & 0x0FFF; /* 12 bit */
+ if (vlan_id != VLAN_VID)
+ {
+ /* not my VLAN packet, discard it */
+ return FALSE;
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ RTMP_SET_PACKET_VLAN(pPacket, 1);
+ Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 2, &Byte0, &Byte1);
+ TypeLen = (USHORT)((Byte0 << 8) + Byte1);
+
+ /* only use VLAN tag */
+ if (bWmmReq)
+ {
+ *pUserPriority = (*pSrcBuf & 0xe0) >> 5;
+ *pQueIdx = MapUserPriorityToAccessCategory[*pUserPriority];
+ }
+
+ pSrcBuf += 4; /* Skip the VLAN Header.*/
+ }
+ else if (TypeLen == 0x0800)
+ {
+ if (bWmmReq)
+ {
+ if ((*pSrcBuf & 0xf0) == 0x40) /* IPv4 */
+ {
+ /*
+ Version - 4-bit Internet Protocol version number.
+ Length - 4-bit IP header length.
+ Traffic Class - 8-bit TOS field.
+ */
+ *pUserPriority = (*(pSrcBuf + 1) & 0xe0) >> 5;
+ }
+
+ *pQueIdx = MapUserPriorityToAccessCategory[*pUserPriority];
+ }
+ }
+ else if (TypeLen == 0x86dd)
+ {
+ if (bWmmReq)
+ {
+ if ((*pSrcBuf & 0xf0) == 0x60) /* IPv6 */
+ {
+ /*
+ Version - 4-bit Internet Protocol version number.
+ Traffic Class - 8-bit traffic class field.
+ */
+ *pUserPriority = ((*pSrcBuf) & 0x0e) >> 1;
+ }
+
+ *pQueIdx = MapUserPriorityToAccessCategory[*pUserPriority];
+ }
+ }
+
+ switch (TypeLen)
+ {
+ case 0x0800:
+ {
+ /* return AC_BE if packet is not IPv4*/
+ if (bWmmReq && (*pSrcBuf & 0xf0) != 0x40)
+ {
+ *pUserPriority = 0;
+ *pQueIdx = QID_AC_BE;
+ }
+ else
+ RTMP_SET_PACKET_IPV4(pPacket, 1);
+
+ ASSERT((pktLen > 34));
+ if (*(pSrcBuf + 9) == 0x11)
+ { /* udp packet*/
+ ASSERT((pktLen > 34)); /* 14 for ethernet header, 20 for IP header*/
+
+ pSrcBuf += 20; /* Skip the IP header*/
+ srcPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf)));
+ dstPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf+2)));
+
+ if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
+ { /*It's a BOOTP/DHCP packet*/
+ RTMP_SET_PACKET_DHCP(pPacket, 1);
+ }
+ }
+ }
+ break;
+ case 0x86dd:
+ {
+ /* return AC_BE if packet is not IPv6 */
+ if (bWmmReq &&
+ ((*pSrcBuf & 0xf0) != 0x60))
+ {
+ *pUserPriority = 0;
+ *pQueIdx = QID_AC_BE;
+ }
+ }
+ break;
+ case 0x0806:
+ {
+ /*ARP Packet.*/
+ RTMP_SET_PACKET_DHCP(pPacket, 1);
+ }
+ break;
+ case 0x888e:
+ {
+ /* EAPOL Packet.*/
+ RTMP_SET_PACKET_EAPOL(pPacket, 1);
+ }
+ break;
+#ifdef WAPI_SUPPORT
+ case 0x88b4:
+ {
+ /* WAI Packet.*/
+ /*hex_dump("WAI Packet", pSrcBuf, pktLen);*/
+ RTMP_SET_PACKET_WAI(pPacket, 1);
+ }
+ break;
+#endif /* WAPI_SUPPORT */
+
+
+ default:
+ break;
+ }
+
+#ifdef VENDOR_FEATURE1_SUPPORT
+ RTMP_SET_PACKET_PROTOCOL(pPacket, TypeLen);
+#endif /* VENDOR_FEATURE1_SUPPORT */
+
+ /* have to check ACM bit. downgrade UP & QueIdx before passing ACM*/
+ /* NOTE: AP doesn't have to negotiate TSPEC. ACM is controlled purely via user setup, not protocol handshaking*/
+ /*
+ Under WMM ACM control, we dont need to check the bit;
+ Or when a TSPEC is built for VO but we will change priority to
+ BE here and when we issue a BA session, the BA session will
+ be BE session, not VO session.
+ */
+ if (pAd->CommonCfg.APEdcaParm.bACM[*pQueIdx])
+ {
+ *pUserPriority = 0;
+ *pQueIdx = QID_AC_BE;
+ }
+
+
+ return TRUE;
+
+}
+
+
+VOID Update_Rssi_Sample(
+ IN RTMP_ADAPTER *pAd,
+ IN RSSI_SAMPLE *pRssi,
+ IN RXWI_STRUC *pRxWI)
+{
+ CHAR rssi[3];
+ UCHAR snr[3];
+ BOOLEAN bInitial = FALSE;
+ CHAR Phymode = get_pkt_phymode_by_rxwi(pRxWI);
+
+
+ if (!(pRssi->AvgRssi0 | pRssi->AvgRssi0X8 | pRssi->LastRssi0))
+ {
+ bInitial = TRUE;
+ }
+
+ get_pkt_rssi_by_rxwi(pAd, pRxWI, 3, &rssi[0]);
+ get_pkt_snr_by_rxwi(pAd, pRxWI, 3, &snr[0]);
+ if (rssi[0] != 0)
+ {
+ pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi[0], RSSI_0, pRxWI->RxWISNR1, pRxWI->RxWIBW);
+ if (bInitial)
+ {
+ pRssi->AvgRssi0X8 = pRssi->LastRssi0 << 3;
+ pRssi->AvgRssi0 = pRssi->LastRssi0;
+ }
+ else
+ pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
+
+ pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
+ }
+
+ if (snr[0] != 0 && Phymode != MODE_CCK)
+ {
+ pRssi->LastSnr0 = ConvertToSnr(pAd, (UCHAR)snr[0]);
+ if (bInitial)
+ {
+ pRssi->AvgSnr0X8 = pRssi->LastSnr0 << 3;
+ pRssi->AvgSnr0 = pRssi->LastSnr0;
+ }
+ else
+ pRssi->AvgSnr0X8 = (pRssi->AvgSnr0X8 - pRssi->AvgSnr0) + pRssi->LastSnr0;
+
+ pRssi->AvgSnr0 = pRssi->AvgSnr0X8 >> 3;
+ }
+
+ if (rssi[1] != 0)
+ {
+ pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi[1], RSSI_1, pRxWI->RxWISNR1, pRxWI->RxWIBW);
+ if (bInitial)
+ {
+ pRssi->AvgRssi1X8 = pRssi->LastRssi1 << 3;
+ pRssi->AvgRssi1 = pRssi->LastRssi1;
+ }
+ else
+ pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
+
+ pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
+ }
+
+ if (snr[1] != 0 && Phymode != MODE_CCK)
+ {
+ pRssi->LastSnr1 = ConvertToSnr(pAd, (UCHAR)snr[1]);
+ if (bInitial)
+ {
+ pRssi->AvgSnr1X8 = pRssi->LastSnr1 << 3;
+ pRssi->AvgSnr1 = pRssi->LastSnr1;
+ }
+ else
+ pRssi->AvgSnr1X8 = (pRssi->AvgSnr1X8 - pRssi->AvgSnr1) + pRssi->LastSnr1;
+
+ pRssi->AvgSnr1 = pRssi->AvgSnr1X8 >> 3;
+ }
+
+ if (rssi[2] != 0)
+ {
+ pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi[2], RSSI_2, pRxWI->RxWISNR1, pRxWI->RxWIBW);
+
+ if (bInitial)
+ {
+ pRssi->AvgRssi2X8 = pRssi->LastRssi2 << 3;
+ pRssi->AvgRssi2 = pRssi->LastRssi2;
+ }
+ else
+ pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
+
+ pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
+ }
+}
+
+
+
+/* Normal legacy Rx packet indication*/
+VOID Indicate_Legacy_Packet(
+ IN RTMP_ADAPTER *pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
+ UCHAR Header802_3[LENGTH_802_3];
+ USHORT VLAN_VID = 0, VLAN_Priority = 0;
+
+
+//+++Add by shiang for debug
+if (0) {
+ hex_dump("Indicate_Legacy_Packet", pRxBlk->pData, pRxBlk->DataSize);
+ hex_dump("802_11_hdr", (UCHAR *)pRxBlk->pHeader, LENGTH_802_11);
+}
+//---Add by shiang for debug
+
+ /*
+ 1. get 802.3 Header
+ 2. remove LLC
+ a. pointer pRxBlk->pData to payload
+ b. modify pRxBlk->DataSize
+ */
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
+ {
+
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
+
+#ifdef RTMP_MAC_USB
+#ifdef DOT11_N_SUPPORT
+ if (pAd->CommonCfg.bDisableReordering == 0)
+ {
+ PBA_REC_ENTRY pBAEntry;
+ ULONG Now32;
+ UCHAR Wcid = pRxBlk->pRxWI->RxWIWirelessCliID;
+ UCHAR TID = pRxBlk->pRxWI->RxWITID;
+ USHORT Idx;
+
+#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms*/
+
+ if (Wcid < MAX_LEN_OF_MAC_TABLE)
+ {
+ Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+ if (Idx != 0)
+ {
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ /* update last rx time*/
+ NdisGetSystemUpTime(&Now32);
+ if ((pBAEntry->list.qlen > 0) &&
+ RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
+ )
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n",
+ pRxBlk->Flags, pRxBlk->pRxWI->RxWITID, pRxBlk->pRxInfo->AMPDU));
+ hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
+ ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
+ }
+ }
+ }
+ }
+#endif /* DOT11_N_SUPPORT */
+#endif /* RTMP_MAC_USB */
+
+#ifdef CONFIG_AP_SUPPORT
+ MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+
+#ifdef WDS_VLAN_SUPPORT
+ if (VLAN_VID == 0) /* maybe WDS packet */
+ WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+#endif /* WDS_VLAN_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+//+++Add by shiang for debug
+if (0) {
+ hex_dump("Before80211_2_8023", pRxBlk->pData, pRxBlk->DataSize);
+ hex_dump("header802_3", &Header802_3[0], LENGTH_802_3);
+}
+//---Add by shiang for debug
+ RT_80211_TO_8023_PACKET(pAd, VLAN_VID, VLAN_Priority,
+ pRxBlk, Header802_3, FromWhichBSSID, TPID);
+//+++Add by shiang for debug
+if (0) {
+ hex_dump("After80211_2_8023", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), GET_OS_PKT_LEN(pRxBlk->pRxPacket));
+}
+//---Add by shiang for debug
+
+
+ /* pass this 802.3 packet to upper layer or forward this packet to WM directly*/
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
+#endif /* CONFIG_AP_SUPPORT */
+
+}
+
+
+#ifdef HDR_TRANS_SUPPORT
+/* Normal legacy Rx packet indication*/
+VOID Indicate_Legacy_Packet_Hdr_Trns(
+ IN RTMP_ADAPTER *pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
+ UCHAR Header802_3[LENGTH_802_3];
+ USHORT VLAN_VID = 0, VLAN_Priority = 0;
+
+ struct sk_buff *pOSPkt;
+
+//+++Add by shiang for debug
+if (0) {
+ hex_dump("Indicate_Legacy_Packet", pRxBlk->pTransData, pRxBlk->TransDataSize);
+ hex_dump("802_11_hdr", pRxBlk->pHeader, LENGTH_802_11);
+}
+//---Add by shiang for debug
+
+ /*
+ 1. get 802.3 Header
+ 2. remove LLC
+ a. pointer pRxBlk->pData to payload
+ b. modify pRxBlk->DataSize
+ */
+
+ if (pRxBlk->TransDataSize > 1514 )
+ {
+
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+
+ STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
+
+#ifdef RTMP_MAC_USB
+#ifdef DOT11_N_SUPPORT
+ if (pAd->CommonCfg.bDisableReordering == 0)
+ {
+ PBA_REC_ENTRY pBAEntry;
+ ULONG Now32;
+ UCHAR Wcid = pRxBlk->pRxWI->RxWIWirelessCliID;
+ UCHAR TID = pRxBlk->pRxWI->RxWITID;
+ USHORT Idx;
+
+#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms*/
+
+ if (Wcid < MAX_LEN_OF_MAC_TABLE)
+ {
+ Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+ if (Idx != 0)
+ {
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ /* update last rx time*/
+ NdisGetSystemUpTime(&Now32);
+ if ((pBAEntry->list.qlen > 0) &&
+ RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
+ )
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("Indicate_Legacy_Packet():flush reordering_timeout_mpdus! RxWI->Flags=%d, pRxWI.TID=%d, RxD->AMPDU=%d!\n",
+ pRxBlk->Flags, pRxBlk->pRxWI->RxWITID, pRxBlk->pRxInfo->AMPDU));
+ hex_dump("Dump the legacy Packet:", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), 64);
+ ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
+ }
+ }
+ }
+ }
+#endif /* DOT11_N_SUPPORT */
+#endif /* RTMP_MAC_USB */
+
+#ifdef CONFIG_AP_SUPPORT
+ MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+
+#ifdef WDS_VLAN_SUPPORT
+ if (VLAN_VID == 0) /* maybe WDS packet */
+ WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+#endif /* WDS_VLAN_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+//+++Add by shiang for debug
+if (0) {
+ hex_dump("Before80211_2_8023", pRxBlk->pData, pRxBlk->TransDataSize);
+ hex_dump("header802_3", &Header802_3[0], LENGTH_802_3);
+}
+//---Add by shiang for debug
+
+
+
+
+
+ RtmpOsSetPacket(get_netdev_from_bssid(pAd, FromWhichBSSID), pRxPacket, pRxBlk->pTransData, pRxBlk->TransDataSize);
+
+
+//+++Add by shiang for debug
+if (0) {
+ hex_dump("After80211_2_8023", GET_OS_PKT_DATAPTR(pRxBlk->pRxPacket), GET_OS_PKT_LEN(pRxBlk->pRxPacket));
+}
+//---Add by shiang for debug
+
+
+ /* pass this 802.3 packet to upper layer or forward this packet to WM directly*/
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
+#endif /* CONFIG_AP_SUPPORT */
+
+}
+#endif /* HDR_TRANS_SUPPORT */
+
+
+/* Normal, AMPDU or AMSDU*/
+VOID CmmRxnonRalinkFrameIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+#ifdef DOT11_N_SUPPORT
+ if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
+ {
+ Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
+ }
+ else
+#endif /* DOT11_N_SUPPORT */
+ {
+#ifdef DOT11_N_SUPPORT
+ if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
+ {
+ /* handle A-MSDU*/
+ Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
+ }
+ else
+#endif /* DOT11_N_SUPPORT */
+ {
+ Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
+ }
+ }
+}
+
+
+#ifdef HDR_TRANS_SUPPORT
+VOID CmmRxnonRalinkFrameIndicate_Hdr_Trns(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+#ifdef DOT11_N_SUPPORT
+ if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
+ {
+ Indicate_AMPDU_Packet_Hdr_Trns(pAd, pRxBlk, FromWhichBSSID);
+ }
+ else
+#endif /* DOT11_N_SUPPORT */
+ {
+#ifdef DOT11_N_SUPPORT
+ if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
+ {
+ /* handle A-MSDU*/
+ Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
+ }
+ else
+#endif /* DOT11_N_SUPPORT */
+ {
+ Indicate_Legacy_Packet_Hdr_Trns(pAd, pRxBlk, FromWhichBSSID);
+ }
+ }
+}
+#endif /* HDR_TRANS_SUPPORT */
+
+
+VOID CmmRxRalinkFrameIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ UCHAR Header802_3[LENGTH_802_3];
+ UINT16 Msdu2Size;
+ UINT16 Payload1Size, Payload2Size;
+ PUCHAR pData2;
+ PNDIS_PACKET pPacket2 = NULL;
+ USHORT VLAN_VID = 0, VLAN_Priority = 0;
+
+
+ Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
+
+ if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
+ {
+ /* skip two byte MSDU2 len */
+ pRxBlk->pData += 2;
+ pRxBlk->DataSize -= 2;
+ }
+ else
+ {
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ /* get 802.3 Header and remove LLC*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ RTMP_AP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ ASSERT(pRxBlk->pRxPacket);
+
+ /* Ralink Aggregation frame*/
+ pAd->RalinkCounters.OneSecRxAggregationCount ++;
+ Payload1Size = pRxBlk->DataSize - Msdu2Size;
+ Payload2Size = Msdu2Size - LENGTH_802_3;
+
+ pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ USHORT VLAN_VID = 0, VLAN_Priority = 0;
+
+ MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+#ifdef WDS_VLAN_SUPPORT
+ if (VLAN_VID == 0) /* maybe WDS packet */
+ WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+#endif /* WDS_VLAN_SUPPORT */
+
+ RT_VLAN_PKT_DUPLICATE(pPacket2, pAd, VLAN_VID, VLAN_Priority,
+ (pData2-LENGTH_802_3), LENGTH_802_3, pData2,
+ Payload2Size, FromWhichBSSID, TPID);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (!pPacket2)
+ {
+ /* release packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ /* update payload size of 1st packet*/
+ pRxBlk->DataSize = Payload1Size;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ MBSS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+
+#ifdef WDS_VLAN_SUPPORT
+ if (VLAN_VID == 0) /* maybe WDS packet */
+ WDS_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, FromWhichBSSID);
+#endif /* WDS_VLAN_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ RT_80211_TO_8023_PACKET(pAd, VLAN_VID, VLAN_Priority,
+ pRxBlk, Header802_3, FromWhichBSSID, TPID);
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pPacket2)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ AP_ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
+#endif /* CONFIG_AP_SUPPORT */
+ }
+}
+
+
+#define RESET_FRAGFRAME(_fragFrame) \
+ { \
+ _fragFrame.RxSize = 0; \
+ _fragFrame.Sequence = 0; \
+ _fragFrame.LastFrag = 0; \
+ _fragFrame.Flags = 0; \
+ }
+
+
+PNDIS_PACKET RTMPDeFragmentDataFrame(
+ IN RTMP_ADAPTER *pAd,
+ IN RX_BLK *pRxBlk)
+{
+ HEADER_802_11 *pHeader = pRxBlk->pHeader;
+ PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
+ UCHAR *pData = pRxBlk->pData;
+ USHORT DataSize = pRxBlk->DataSize;
+ PNDIS_PACKET pRetPacket = NULL;
+ UCHAR *pFragBuffer = NULL;
+ BOOLEAN bReassDone = FALSE;
+ UCHAR HeaderRoom = 0;
+
+
+ ASSERT(pHeader);
+
+ HeaderRoom = pData - (UCHAR *)pHeader;
+
+ /* Re-assemble the fragmented packets*/
+ if (pHeader->Frag == 0) /* Frag. Number is 0 : First frag or only one pkt*/
+ {
+ /* the first pkt of fragment, record it.*/
+ if (pHeader->FC.MoreFrag)
+ {
+ ASSERT(pAd->FragFrame.pFragPacket);
+ pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
+ pAd->FragFrame.RxSize = DataSize + HeaderRoom;
+ NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
+ pAd->FragFrame.Sequence = pHeader->Sequence;
+ pAd->FragFrame.LastFrag = pHeader->Frag; /* Should be 0*/
+ ASSERT(pAd->FragFrame.LastFrag == 0);
+ goto done; /* end of processing this frame*/
+ }
+ }
+ else /*Middle & End of fragment*/
+ {
+ if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
+ (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
+ {
+ /* Fragment is not the same sequence or out of fragment number order*/
+ /* Reset Fragment control blk*/
+ RESET_FRAGFRAME(pAd->FragFrame);
+ DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
+ goto done; /* give up this frame*/
+ }
+ else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
+ {
+ /* Fragment frame is too large, it exeeds the maximum frame size.*/
+ /* Reset Fragment control blk*/
+ RESET_FRAGFRAME(pAd->FragFrame);
+ DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
+ goto done; /* give up this frame*/
+ }
+
+
+ /* Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.*/
+ /* In this case, we will dropt it.*/
+
+ if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
+ goto done; /* give up this frame*/
+ }
+
+ pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
+
+ /* concatenate this fragment into the re-assembly buffer*/
+ NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
+ pAd->FragFrame.RxSize += DataSize;
+ pAd->FragFrame.LastFrag = pHeader->Frag; /* Update fragment number*/
+
+ /* Last fragment*/
+ if (pHeader->FC.MoreFrag == FALSE)
+ {
+ bReassDone = TRUE;
+ }
+ }
+
+done:
+ /* always release rx fragmented packet*/
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+
+ /* return defragmented packet if packet is reassembled completely*/
+ /* otherwise return NULL*/
+ if (bReassDone)
+ {
+ PNDIS_PACKET pNewFragPacket;
+
+ /* allocate a new packet buffer for fragment*/
+ pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
+ if (pNewFragPacket)
+ {
+ /* update RxBlk*/
+ pRetPacket = pAd->FragFrame.pFragPacket;
+ pAd->FragFrame.pFragPacket = pNewFragPacket;
+ pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
+ pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
+ pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
+ pRxBlk->pRxPacket = pRetPacket;
+ }
+ else
+ {
+ RESET_FRAGFRAME(pAd->FragFrame);
+ }
+ }
+
+ return pRetPacket;
+}
+
+
+VOID Indicate_EAPOL_Packet(
+ IN RTMP_ADAPTER *pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ MAC_TABLE_ENTRY *pEntry = NULL;
+
+ if (pRxBlk->pRxWI->RxWIWirelessCliID >= MAX_LEN_OF_MAC_TABLE)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: invalid wcid.\n"));
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ pEntry = &pAd->MacTab.Content[pRxBlk->pRxWI->RxWIWirelessCliID];
+ if (pEntry == NULL)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ APRxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
+ return;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+}
+
+
+#define BCN_TBTT_OFFSET 64 /*defer 64 us*/
+VOID ReSyncBeaconTime(
+ IN RTMP_ADAPTER *pAd)
+{
+ UINT32 Offset;
+
+
+ Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
+ pAd->TbttTickCount++;
+
+ /*
+ The updated BeaconInterval Value will affect Beacon Interval after two TBTT
+ beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
+ */
+ if (Offset == (BCN_TBTT_OFFSET-2))
+ {
+ BCN_TIME_CFG_STRUC csr;
+ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+ csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; /* ASIC register in units of 1/16 TU = 64us*/
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+ }
+ else
+ {
+ if (Offset == (BCN_TBTT_OFFSET-1))
+ {
+ BCN_TIME_CFG_STRUC csr;
+
+ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+ csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; /* ASIC register in units of 1/16 TU*/
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+ }
+ }
+}
+
+#ifdef SOFT_ENCRYPT
+BOOLEAN RTMPExpandPacketForSwEncrypt(
+ IN PRTMP_ADAPTER pAd,
+ IN PTX_BLK pTxBlk)
+{
+ PACKET_INFO PacketInfo;
+ UINT32 ex_head = 0, ex_tail = 0;
+ UCHAR NumberOfFrag = RTMP_GET_PACKET_FRAGMENTS(pTxBlk->pPacket);
+
+#ifdef WAPI_SUPPORT
+ if (pTxBlk->CipherAlg == CIPHER_SMS4)
+ ex_tail = LEN_WPI_MIC;
+ else
+#endif /* WAPI_SUPPORT */
+ if (pTxBlk->CipherAlg == CIPHER_AES)
+ ex_tail = LEN_CCMP_MIC;
+
+ ex_tail = (NumberOfFrag * ex_tail);
+
+ pTxBlk->pPacket = ExpandPacket(pAd, pTxBlk->pPacket, ex_head, ex_tail);
+ if (pTxBlk->pPacket == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: out of resource.\n", __FUNCTION__));
+ return FALSE;
+ }
+ RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
+
+ return TRUE;
+}
+
+VOID RTMPUpdateSwCacheCipherInfo(
+ IN PRTMP_ADAPTER pAd,
+ IN PTX_BLK pTxBlk,
+ IN PUCHAR pHdr)
+{
+ PHEADER_802_11 pHeader_802_11;
+ PMAC_TABLE_ENTRY pMacEntry;
+
+ pHeader_802_11 = (HEADER_802_11 *) pHdr;
+ pMacEntry = pTxBlk->pMacEntry;
+
+ if (pMacEntry && pHeader_802_11->FC.Wep &&
+ CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT))
+ {
+ PCIPHER_KEY pKey = &pMacEntry->PairwiseKey;
+
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt);
+
+ pTxBlk->CipherAlg = pKey->CipherAlg;
+ pTxBlk->pKey = pKey;
+#ifdef WAPI_SUPPORT
+ pTxBlk->KeyIdx = pMacEntry->usk_id;
+
+ /* TSC increment pre encryption transmittion */
+ if (pKey->CipherAlg == CIPHER_SMS4)
+ inc_iv_byte(pKey->TxTsc, LEN_WAPI_TSC, 2);
+ else
+#endif /* WAPI_SUPPORT */
+ if ((pKey->CipherAlg == CIPHER_WEP64) || (pKey->CipherAlg == CIPHER_WEP128))
+ inc_iv_byte(pKey->TxTsc, LEN_WEP_TSC, 1);
+ else if ((pKey->CipherAlg == CIPHER_TKIP) || (pKey->CipherAlg == CIPHER_AES))
+ inc_iv_byte(pKey->TxTsc, LEN_WPA_TSC, 1);
+
+ }
+
+}
+
+#endif /* SOFT_ENCRYPT */
+
+/*
+ ==========================================================================
+ Description:
+ Send out a NULL frame to a specified STA at a higher TX rate. The
+ purpose is to ensure the designated client is okay to received at this
+ rate.
+ ==========================================================================
+ */
+VOID RtmpEnqueueNullFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UCHAR TxRate,
+ IN UCHAR PID,
+ IN UCHAR apidx,
+ IN BOOLEAN bQosNull,
+ IN BOOLEAN bEOSP,
+ IN UCHAR OldUP)
+{
+ NDIS_STATUS NState;
+ PHEADER_802_11 pNullFr;
+ PUCHAR pFrame;
+ ULONG Length;
+
+ /* since TxRate may change, we have to change Duration each time */
+ NState = MlmeAllocateMemory(pAd, (PUCHAR *)&pFrame);
+ pNullFr = (PHEADER_802_11) pFrame;
+ Length = sizeof(HEADER_802_11);
+
+ if (NState == NDIS_STATUS_SUCCESS)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ MgtMacHeaderInit(pAd, pNullFr, SUBTYPE_NULL_FUNC, 0, pAddr,
+ pAd->ApCfg.MBSSID[apidx].Bssid);
+#endif /* CONFIG_AP_SUPPORT */
+
+ pNullFr->FC.Type = BTYPE_DATA;
+ pNullFr->FC.FrDs = 1;
+ pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, 14);
+
+
+#ifdef UAPSD_SUPPORT
+ if (bQosNull)
+ {
+ UCHAR *qos_p = ((UCHAR *)pNullFr) + Length;
+
+ pNullFr->FC.SubType = SUBTYPE_QOS_NULL;
+
+ /* copy QOS control bytes */
+ qos_p[0] = ((bEOSP) ? (1 << 4) : 0) | OldUP;
+ qos_p[1] = 0;
+ Length += 2;
+ } /* End of if */
+#endif /* UAPSD_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_INFO, ("send NULL Frame @%d Mbps to AID#%d...\n", RateIdToMbps[TxRate], PID & 0x3f));
+ MiniportMMRequest(pAd, MapUserPriorityToAccessCategory[7], (PUCHAR)pNullFr, Length);
+ MlmeFreeMemory(pAd, pFrame);
+ }
+}
+
+
+
+#ifdef RLT_MAC
+BOOLEAN CmdRspEventCallbackHandle(PRTMP_ADAPTER pAd, PUCHAR pRspBuffer)
+{
+
+ INT32 Ret;
+ struct MCU_CTRL *MCtrl = &pAd->MCUCtrl;
+ struct CMD_RSP_EVENT *CmdRspEvent, *CmdRspEventTmp;
+ RXFCE_INFO_CMD *pFceInfo = (RXFCE_INFO_CMD *)pRspBuffer;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pFceInfo, TYPE_RXINFO);
+#endif
+
+
+ if ((pFceInfo->info_type != CMD_PACKET))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Packet is not command response/event\n"));
+ return NDIS_STATUS_FAILURE;
+ }
+
+ if (pFceInfo->self_gen)
+ {
+ /* if have callback function */
+ RTEnqueueInternalCmd(pAd, CMDTHREAD_RESPONSE_EVENT_CALLBACK,
+ pRspBuffer,
+ sizeof(*pFceInfo) + pFceInfo->pkt_len);
+ }
+ else
+ {
+ unsigned long IrqFlags;
+ RTMP_IRQ_LOCK(&MCtrl->CmdRspEventListLock, IrqFlags);
+ DlListForEachSafe(CmdRspEvent, CmdRspEventTmp, &MCtrl->CmdRspEventList, struct CMD_RSP_EVENT, List)
+ {
+ if (CmdRspEvent->CmdSeq == pFceInfo->cmd_seq)
+ {
+
+ if ((*CmdRspEvent->RspPayloadLen == pFceInfo->pkt_len) && (*CmdRspEvent->RspPayloadLen != 0))
+ {
+ NdisMoveMemory(*CmdRspEvent->RspPayload, pRspBuffer + sizeof(*pFceInfo),
+ pFceInfo->pkt_len);
+ }
+ else if ((*CmdRspEvent->RspPayloadLen == 0) && (pFceInfo->pkt_len == 8))
+ {
+ DBGPRINT(RT_DEBUG_INFO, ("Command response(ack) success\n"));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Expect response len(%d), Command response len(%d) invalid\n", *CmdRspEvent->RspPayloadLen, pFceInfo->pkt_len));
+ *CmdRspEvent->RspPayloadLen = pFceInfo->pkt_len;
+ }
+
+ if (CmdRspEvent->NeedWait)
+ {
+ RtmpComplete(CmdRspEvent->AckDone);
+ }
+ else
+ {
+ DlListDel(&CmdRspEvent->List);
+ os_free_mem(NULL, CmdRspEvent);
+ }
+
+ break;
+ }
+ }
+ RTMP_IRQ_UNLOCK(&MCtrl->CmdRspEventListLock, IrqFlags);
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+#ifdef RTMP_USB_SUPPORT
+BOOLEAN CmdRspEventHandle(RTMP_ADAPTER *pAd)
+{
+ PCMD_RSP_CONTEXT pCmdRspEventContext = &pAd->CmdRspEventContext;
+
+ CmdRspEventCallbackHandle(pAd, pCmdRspEventContext->CmdRspBuffer);
+
+ return TRUE;
+
+}
+#endif /* RTMP_USB_SUPPORT */
+#endif /* RLT_MAC */
+
+
+#ifdef CONFIG_AP_SUPPORT
+MAC_TABLE_ENTRY *MulTestTableLookup(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN BOOLEAN bResetIdelCount)
+{
+ USHORT HashIdx;
+ PMAC_TABLE_ENTRY pEntry = NULL;
+
+ NdisAcquireSpinLock(&pAd->MacTabLock);
+
+ HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
+ pEntry = pAd->MacTab.Hash[HashIdx];
+
+ while (pEntry)
+ {
+ if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
+ {
+ if(bResetIdelCount)
+ pEntry->NoDataIdleCount = 0;
+ break;
+ }
+ else
+ pEntry = pEntry->pNext;
+ }
+
+ NdisReleaseSpinLock(&pAd->MacTabLock);
+
+ return pEntry;
+}
+
+
+MAC_TABLE_ENTRY *MacTableInsertMulTestEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ UINT WdsTabIdx)
+{
+ PMAC_TABLE_ENTRY pEntry = NULL;
+ HTTRANSMIT_SETTING HTPhyMode;
+
+ /* if FULL, return */
+ if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
+ return NULL;
+
+ if((pEntry = MulTestTableLookup(pAd, pAddr, TRUE)) != NULL)
+ return pEntry;
+
+ /* allocate one WDS entry */
+ do
+ {
+ /* allocate one MAC entry */
+ pEntry = MacTableInsertEntry(pAd, pAddr, BSS0, OPMODE_AP, TRUE);
+ if (pEntry)
+ {
+ pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
+
+ /* specific Max Tx Rate for Wds link. */
+ NdisZeroMemory(&HTPhyMode, sizeof(HTTRANSMIT_SETTING));
+ switch (pAd->MulTestTab.WdsEntry[WdsTabIdx].PhyMode)
+ {
+ case 0xff: /* user doesn't specific a Mode for WDS link. */
+ case MODE_OFDM: /* specific OFDM mode. */
+ HTPhyMode.field.MODE = MODE_OFDM;
+ HTPhyMode.field.MCS = 7;
+ pEntry->RateLen = 8;
+ break;
+
+ case MODE_CCK:
+ HTPhyMode.field.MODE = MODE_CCK;
+ HTPhyMode.field.MCS = 3;
+ pEntry->RateLen = 4;
+ break;
+
+#ifdef DOT11_N_SUPPORT
+ case MODE_HTMIX:
+ HTPhyMode.field.MCS = 7;
+ HTPhyMode.field.ShortGI = pAd->MulTestTab.WdsEntry[WdsTabIdx].HTPhyMode.field.ShortGI;
+ HTPhyMode.field.BW = pAd->MulTestTab.WdsEntry[WdsTabIdx].HTPhyMode.field.BW;
+ HTPhyMode.field.STBC = pAd->MulTestTab.WdsEntry[WdsTabIdx].HTPhyMode.field.STBC;
+ HTPhyMode.field.MODE = MODE_HTMIX;
+ pEntry->RateLen = 12;
+ break;
+
+ case MODE_HTGREENFIELD:
+ HTPhyMode.field.MCS = 7;
+ HTPhyMode.field.ShortGI = pAd->MulTestTab.WdsEntry[WdsTabIdx].HTPhyMode.field.ShortGI;
+ HTPhyMode.field.BW = pAd->MulTestTab.WdsEntry[WdsTabIdx].HTPhyMode.field.BW;
+ HTPhyMode.field.STBC = pAd->MulTestTab.WdsEntry[WdsTabIdx].HTPhyMode.field.STBC;
+ HTPhyMode.field.MODE = MODE_HTGREENFIELD;
+ pEntry->RateLen = 12;
+ break;
+#endif /* DOT11_N_SUPPORT */
+
+ default:
+ break;
+ }
+
+ {
+ pEntry->Sst = SST_ASSOC;
+
+ pEntry->MaxSupportedRate = RATE_54;
+
+ 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];
+ }
+
+ // Set WMM capability
+ if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) || (pAd->CommonCfg.bWmmCapable))
+ {
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
+ }
+ else
+ {
+ CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
+ }
+
+ if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+ {
+ UCHAR j, bitmask; /*k,bitmask; */
+ CHAR i;
+
+ if ((pAd->CommonCfg.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 ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
+ {
+ pEntry->MaxHTPhyMode.field.BW= BW_40;
+ pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40));
+ }
+ else
+ {
+ pEntry->MaxHTPhyMode.field.BW = BW_20;
+ pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20));
+ pAd->MacTab.fAnyStation20Only = TRUE;
+ }
+
+ /* find max fixed rate */
+ for (i=23; i>=0; i--) /* 3*3 */
+ {
+ j = i/8;
+ bitmask = (1<<(i-(j*8)));
+ if ((pAd->ApCfg.MBSSID[pEntry->apidx].DesiredHtPhyInfo.MCSSet[j] & bitmask) && (pAd->CommonCfg.HtCapability.MCSSet[j] & bitmask))
+ {
+ pEntry->MaxHTPhyMode.field.MCS = i;
+ break;
+ }
+ if (i==0)
+ break;
+ }
+
+
+ if (pAd->ApCfg.MBSSID[pEntry->apidx].DesiredTransmitSetting.field.MCS != MCS_AUTO)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("@@@ IF-ra%d DesiredTransmitSetting.field.MCS = %d\n", pEntry->apidx,
+ pAd->ApCfg.MBSSID[pEntry->apidx].DesiredTransmitSetting.field.MCS));
+
+ if (pAd->ApCfg.MBSSID[pEntry->apidx].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->ApCfg.MBSSID[pEntry->apidx].HTPhyMode.field.MCS)
+ {
+ /* STA supports fixed MCS */
+ pEntry->MaxHTPhyMode.field.MCS = pAd->ApCfg.MBSSID[pEntry->apidx].HTPhyMode.field.MCS;
+ }
+ }
+
+ pEntry->MaxHTPhyMode.field.STBC = (pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
+ if (pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity < 5)
+ pEntry->MpduDensity = 5;
+ else
+ pEntry->MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
+ pEntry->MaxRAmpduFactor = pAd->CommonCfg.HtCapability.HtCapParm.MaxRAmpduFactor;
+ pEntry->MmpsMode = (UCHAR)pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs;
+ pEntry->AMsduSize = (UCHAR)pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize;
+ pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+
+ if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE))
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED);
+ if (pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
+ if (pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
+ if (pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
+ if (pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
+ if (pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
+ if (pAd->CommonCfg.bRdg && pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
+ if (pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
+
+ /* Record the received capability from association request */
+ NdisMoveMemory(&pEntry->HTCapability, &pAd->CommonCfg.HtCapability, sizeof(HT_CAPABILITY_IE));
+ }
+ else
+ {
+ pAd->MacTab.fAnyStationIsLegacy = TRUE;
+ NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE));
+ }
+
+ pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+ pEntry->CurrTxRate = pEntry->MaxSupportedRate;
+ }
+
+ //pEntry->MaxHTPhyMode.word = pEntry->MaxHTPhyMode.word;
+ //pEntry->MinHTPhyMode.word = pAd->MulTestTab.WdsEntry[WdsTabIdx].MinHTPhyMode.word;
+ //pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+
+
+ /*if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */
+ if (pAd->MulTestTab.WdsEntry[WdsTabIdx].bAutoTxRateSwitch == FALSE)
+ {
+ pEntry->HTPhyMode.field.MCS = pAd->MulTestTab.WdsEntry[WdsTabIdx].DesiredTransmitSetting.field.MCS;
+ pEntry->bAutoTxRateSwitch = FALSE;
+ /* If the legacy mode is set, overwrite the transmit setting of this entry. */
+ RTMPUpdateLegacyTxSetting((UCHAR)pAd->MulTestTab.WdsEntry[WdsTabIdx].DesiredTransmitSetting.field.FixedTxMode, pEntry);
+ }
+ else
+ {
+ pEntry->bAutoTxRateSwitch = TRUE;
+ }
+
+ pAd->MulTestTab.WdsEntry[WdsTabIdx].MacTabMatchWCID = (UCHAR)pEntry->Aid;
+ pEntry->MatchWDSTabIdx = WdsTabIdx;
+
+ AsicUpdateMulTestEncryption(pAd, pEntry->Aid);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertWDSEntry - allocate entry #%d, Total= %d\n",WdsTabIdx, pAd->MacTab.Size));
+ break;
+ }
+ }while(FALSE);
+
+ return pEntry;
+}
+
+
+VOID AsicUpdateMulTestRxWCIDTable(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT index;
+
+ for(index = 0; index < MAX_WDS_ENTRY; index++)
+ {
+ if (pAd->MulTestTab.WdsEntry[index].Valid != TRUE)
+ continue;
+
+ MacTableInsertMulTestEntry(pAd, pAd->MulTestTab.WdsEntry[index].PeerWdsAddr, index);
+ }
+
+ return;
+}
+
+VOID AsicUpdateMulTestEncryption(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR wcid)
+{
+ UINT WdsIdex;
+ PMAC_TABLE_ENTRY pEntry = NULL;
+
+ do
+ {
+ if (wcid >= MAX_LEN_OF_MAC_TABLE)
+ break;
+
+ pEntry = &pAd->MacTab.Content[wcid];
+ if (pAd->MulTestTab.WdsEntry[pEntry->MatchWDSTabIdx].Valid != TRUE)
+ break;
+
+ WdsIdex = pEntry->MatchWDSTabIdx;
+
+ if (((pAd->MulTestTab.WdsEntry[WdsIdex].WepStatus == Ndis802_11Encryption1Enabled) ||
+ (pAd->MulTestTab.WdsEntry[WdsIdex].WepStatus == Ndis802_11Encryption2Enabled) ||
+ (pAd->MulTestTab.WdsEntry[WdsIdex].WepStatus == Ndis802_11Encryption3Enabled)
+#ifdef WAPI_SUPPORT
+ || (pAd->MulTestTab.WdsEntry[WdsIdex].WepStatus == Ndis802_11EncryptionSMS4Enabled)
+#endif /* WAPI_SUPPORT */
+ ) && (pAd->MulTestTab.WdsEntry[WdsIdex].WdsKey.KeyLen > 0))
+ {
+
+ INT DefaultKeyId = 0;
+
+ if (pAd->MulTestTab.WdsEntry[WdsIdex].WepStatus == Ndis802_11Encryption1Enabled)
+ DefaultKeyId = pAd->MulTestTab.WdsEntry[pEntry->MatchWDSTabIdx].KeyIdx;
+
+ NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY));
+
+ /* Assign key material and its length */
+ NdisMoveMemory((PUCHAR)(&pEntry->PairwiseKey), (PUCHAR)(&pAd->MulTestTab.WdsEntry[WdsIdex].WdsKey), sizeof(CIPHER_KEY));
+
+ DBGPRINT(RT_DEBUG_ERROR, ("pEntry->PairwiseKey.CipherAlg = (%d)\n", pEntry->PairwiseKey.CipherAlg));
+
+ pEntry->WepStatus = pAd->MulTestTab.WdsEntry[WdsIdex].WepStatus;
+
+ /* Assign the pairwise cipher algorithm */
+ if (pEntry->WepStatus == Ndis802_11Encryption1Enabled)
+ {
+ if (pAd->MulTestTab.WdsEntry[WdsIdex].WdsKey.CipherAlg == CIPHER_WEP64)
+ pEntry->PairwiseKey.CipherAlg = CIPHER_WEP64;
+ else if (pAd->MulTestTab.WdsEntry[WdsIdex].WdsKey.CipherAlg == CIPHER_WEP128)
+ pEntry->PairwiseKey.CipherAlg = CIPHER_WEP128;
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (wcid-%d)\n",
+ __FUNCTION__, pEntry->Aid));
+ return;
+
+ }
+ }
+ else if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
+ pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP;
+ else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled)
+ pEntry->PairwiseKey.CipherAlg = CIPHER_AES;
+#ifdef WAPI_SUPPORT
+ else if (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled)
+ pEntry->PairwiseKey.CipherAlg = CIPHER_SMS4;
+#endif /* WAPI_SUPPORT */
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (wcid-%d)\n",
+ __FUNCTION__, pEntry->Aid));
+ return;
+ }
+
+#ifdef SOFT_ENCRYPT
+ if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("===> SW_ENC ON(wcid=%d) \n", pEntry->Aid));
+ NdisZeroMemory(pEntry->PairwiseKey.TxTsc, LEN_WPA_TSC);
+ NdisZeroMemory(pEntry->PairwiseKey.RxTsc, LEN_WPA_TSC);
+ }
+ else
+#endif /* SOFT_ENCRYPT */
+ {
+ /* Update key into Asic Pairwise key table */
+ RTMP_ASIC_PAIRWISE_KEY_TABLE(
+ pAd,
+ pEntry->Aid,
+ &pAd->MulTestTab.WdsEntry[pEntry->MatchWDSTabIdx].WdsKey);
+
+ /* update WCID attribute table and IVEIV table for this entry */
+ RTMP_SET_WCID_SEC_INFO(
+ pAd,
+ BSS0,
+ DefaultKeyId,
+ pAd->MulTestTab.WdsEntry[pEntry->MatchWDSTabIdx].WdsKey.CipherAlg,
+ pEntry->Aid,
+ PAIRWISEKEY);
+ }
+
+
+
+
+ }
+ } while (FALSE);
+
+ return;
+}
+#endif
+
+
+NTSTATUS StopDmaRx(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR Level)
+{
+ PNDIS_PACKET pRxPacket;
+ RX_BLK RxBlk, *pRxBlk;
+ UINT32 RxPending = 0, MacReg = 0, MTxCycle = 0;
+ BOOLEAN bReschedule = FALSE;
+ UINT32 MaxRetry;
+
+ //DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__));
+
+ if ( Level == DOT11POWERSAVE )
+ MaxRetry = 20;
+ else
+ MaxRetry = 2000;
+
+ /*
+ process whole rx ring
+ */
+ while (1)
+ {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return STATUS_UNSUCCESSFUL;
+ pRxBlk = &RxBlk;
+ pRxPacket = GetPacketFromRxRing(pAd, pRxBlk, &bReschedule, &RxPending);
+ if ((RxPending == 0) && (bReschedule == FALSE))
+ break;
+ else
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
+ }
+
+ /*
+ Check DMA Rx idle
+ */
+ for (MTxCycle = 0; MTxCycle < MaxRetry ; MTxCycle++)
+ {
+
+#ifdef RTMP_MAC_USB
+ RTMP_IO_READ32(pAd, USB_DMA_CFG, &MacReg);
+
+ if (MacReg & 0x40000000)
+ {
+ RTMPusecDelay(50);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_INFO, ("==> DMA Rx Idle, MacReg=0x%x\n", MacReg));
+ break;
+ }
+#endif /* RTMP_MAC_USB */
+
+ if (MacReg == 0xFFFFFFFF)
+ {
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ if (MTxCycle >= MaxRetry)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:RX DMA busy!! DMA_CFG = 0x%08x\n", __FUNCTION__, MacReg));
+
+ if ( Level == GUIRADIO_OFF )
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (Level == RTMP_HALT)
+ {
+ /*
+ Disable DMA RX
+ */
+
+ }
+
+ //DBGPRINT(RT_DEBUG_TRACE, ("<==== %s\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS StopDmaTx(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR Level)
+{
+ UINT32 MacReg = 0, MTxCycle = 0;
+#ifdef RTMP_MAC_USB
+ USB_DMA_CFG_STRUC UsbCfg;
+#endif /* RTMP_MAC_USB */
+ UINT8 IdleNums = 0;
+ UINT32 MaxRetry;
+
+ //DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__));
+
+ if ( Level == DOT11POWERSAVE )
+ MaxRetry = 20;
+ else
+ MaxRetry = 2000;
+
+ for (MTxCycle = 0; MTxCycle < MaxRetry; MTxCycle++)
+ {
+
+#ifdef RTMP_MAC_USB
+ RTMP_IO_READ32(pAd, USB_DMA_CFG, &MacReg);
+
+ if (MacReg & 0x80000000 )
+ {
+ RTMPusecDelay(50);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_INFO, ("==> DMA Tx Idle, MacReg=0x%x\n", MacReg));
+ break;
+ }
+#endif /* RTMP_MAC_USB */
+
+ if (MacReg == 0xFFFFFFFF)
+ {
+ //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ if (MTxCycle >= MaxRetry)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("TX DMA busy!! DMA_CFG(%x)\n", MacReg));
+
+ if ( Level == GUIRADIO_OFF )
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (Level == RTMP_HALT)
+ {
+ }
+
+ //DBGPRINT(RT_DEBUG_TRACE, ("<==== %s\n", __FUNCTION__));
+ return STATUS_SUCCESS;
+}
+
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_data_usb.c b/cleopatre/devkit/mt7601udrv/common/cmm_data_usb.c
new file mode 100644
index 0000000000..46865c2b6c
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_data_usb.c
@@ -0,0 +1,1312 @@
+/*
+ All functions in this file must be USB-depended, or you should out your function
+ in other files.
+
+*/
+
+#ifdef RTMP_MAC_USB
+
+#include "rt_config.h"
+
+
+NDIS_STATUS RTUSBFreeDescriptorRelease(RTMP_ADAPTER *pAd, UCHAR BulkOutPipeId)
+{
+ HT_TX_CONTEXT *pHTTXContext;
+ unsigned long IrqFlags;
+
+
+ pHTTXContext = &pAd->TxContext[BulkOutPipeId];
+ RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+ pHTTXContext->bCurWriting = FALSE;
+ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ This subroutine will scan through releative ring descriptor to find
+ out avaliable free ring descriptor and compare with request size.
+
+ Arguments:
+ pAd Pointer to our adapter
+ RingType Selected Ring
+
+ Return Value:
+ NDIS_STATUS_FAILURE Not enough free descriptor
+ NDIS_STATUS_SUCCESS Enough free descriptor
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS RTUSBFreeDescRequest(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR BulkOutPipeId,
+ IN UINT32 req_cnt)
+{
+ NDIS_STATUS Status = NDIS_STATUS_FAILURE;
+ unsigned long IrqFlags;
+ HT_TX_CONTEXT *pHTTXContext;
+
+
+ pHTTXContext = &pAd->TxContext[BulkOutPipeId];
+ RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+#ifdef USB_BULK_BUF_ALIGMENT
+ if( ((pHTTXContext->CurWriteIdx< pHTTXContext->NextBulkIdx ) && (pHTTXContext->NextBulkIdx - pHTTXContext->CurWriteIdx == 1))
+ || ((pHTTXContext->CurWriteIdx ==(BUF_ALIGMENT_RINGSIZE -1) ) && (pHTTXContext->NextBulkIdx == 0 )))
+ {
+ RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+
+ }
+ else if (pHTTXContext->bCurWriting == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("BUF_ALIGMENT RTUSBFreeD c3 --> QueIdx=%d, CWPos=%ld, NBOutPos=%ld!\n", BulkOutPipeId, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition));
+ RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+ }
+
+#else
+ if ((pHTTXContext->CurWritePosition < pHTTXContext->NextBulkOutPosition) && ((pHTTXContext->CurWritePosition + req_cnt + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition))
+ {
+
+ RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+ }
+ else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < (req_cnt + LOCAL_TXBUF_SIZE)))
+ {
+ RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+ }
+ else if (pHTTXContext->bCurWriting == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("RTUSBFreeD c3 --> QueIdx=%d, CWPos=%ld, NBOutPos=%ld!\n", BulkOutPipeId, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition));
+ RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+ }
+#endif /* USB_BULK_BUF_ALIGMENT */
+ else
+ {
+ Status = NDIS_STATUS_SUCCESS;
+ }
+ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+
+
+ return Status;
+}
+
+
+BOOLEAN RTUSBNeedQueueBackForAgg(RTMP_ADAPTER *pAd, UCHAR BulkOutPipeId)
+{
+ HT_TX_CONTEXT *pHTTXContext;
+ BOOLEAN needQueBack = FALSE;
+ unsigned long IrqFlags;
+
+
+ pHTTXContext = &pAd->TxContext[BulkOutPipeId];
+
+ RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+ if ((pHTTXContext->IRPPending == TRUE) /*&& (pAd->TxSwQueue[BulkOutPipeId].Number == 0) */)
+ {
+ if ((pHTTXContext->CurWritePosition < pHTTXContext->ENextBulkOutPosition) &&
+ (((pHTTXContext->ENextBulkOutPosition+MAX_AGGREGATION_SIZE) < MAX_TXBULK_LIMIT) || (pHTTXContext->CurWritePosition > MAX_AGGREGATION_SIZE)))
+ {
+ needQueBack = TRUE;
+ }
+ else if ((pHTTXContext->CurWritePosition > pHTTXContext->ENextBulkOutPosition) &&
+ ((pHTTXContext->ENextBulkOutPosition + MAX_AGGREGATION_SIZE) < pHTTXContext->CurWritePosition))
+ {
+ needQueBack = TRUE;
+ }
+ }
+ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
+
+ return needQueBack;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculates the duration which is required to transmit out frames
+ with given size and specified rate.
+
+ Arguments:
+ pTxD Pointer to transmit descriptor
+ Ack Setting for Ack requirement bit
+ Fragment Setting for Fragment bit
+ RetryMode Setting for retry mode
+ Ifs Setting for IFS gap
+ Rate Setting for transmit rate
+ Service Setting for service
+ Length Frame length
+ TxPreamble Short or Long preamble when using CCK rates
+ QueIdx - 0-3, according to 802.11e/d4.4 June/2003
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+static VOID rlt_usb_write_txinfo(
+ IN RTMP_ADAPTER *pAd,
+ IN TXINFO_STRUC *pTxInfo,
+ IN USHORT USBDMApktLen,
+ IN BOOLEAN bWiv,
+ IN UCHAR QueueSel,
+ IN UCHAR NextValid,
+ IN UCHAR TxBurst,
+ IN UCHAR pkt_80211 )
+{
+#ifdef RLT_MAC
+ struct _TXINFO_NMAC_PKT *nmac_info;
+
+ nmac_info = (struct _TXINFO_NMAC_PKT *)pTxInfo;
+#ifdef HDR_TRANS_SUPPORT
+ nmac_info->pkt_80211 = pkt_80211;
+#else
+ nmac_info->pkt_80211 = 1;
+#endif /* HDR_TRANS_SUPPORT */
+ nmac_info->info_type = 0;
+ nmac_info->d_port = 0;
+ nmac_info->cso = 0;
+ nmac_info->tso = 0;
+#endif /* RLT_MAC */
+
+#ifdef RTMP_MAC
+
+#endif /* RTMP_MAC */
+
+ pTxInfo->TxInfoPktLen = USBDMApktLen;
+ pTxInfo->TxInfoQSEL = QueueSel;
+#ifndef CONFIG_MULTI_CHANNEL
+ if (QueueSel != FIFO_EDCA)
+ DBGPRINT(RT_DEBUG_TRACE, ("====> QueueSel != FIFO_EDCA <====\n"));
+#endif /* !CONFIG_MULTI_CHANNEL */
+ pTxInfo->TxInfoUDMANextVld = FALSE; /*NextValid; Need to check with Jan about this.*/
+ pTxInfo->TxInfoUDMATxburst = TxBurst;
+ pTxInfo->TxInfoWIV = bWiv;
+#ifndef USB_BULK_BUF_ALIGMENT
+ pTxInfo->TxInfoSwLstRnd = 0;
+#else
+ pTxInfo->bFragLasAlignmentsectiontRound = 0;
+#endif /* USB_BULK_BUF_ALIGMENT */
+}
+
+
+static VOID rlt_usb_update_txinfo(
+ IN RTMP_ADAPTER *pAd,
+ IN TXINFO_STRUC *pTxInfo,
+ IN TX_BLK *pTxBlk)
+{
+#ifdef RLT_MAC
+#endif /* RLT_MAC */
+}
+
+
+
+
+/* IRQL = DISPATCH_LEVEL */
+VOID ComposeNullFrame(RTMP_ADAPTER *pAd)
+{
+ TXINFO_STRUC *pTxInfo;
+ TXWI_STRUC *pTxWI;
+ UCHAR *buf;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+ USHORT data_len = sizeof(pAd->NullFrame);;
+
+ PTX_CONTEXT pNullContext = &pAd->NullContext[0];
+
+ NdisZeroMemory(&pAd->NullFrame, data_len);
+ pAd->NullFrame.FC.Type = BTYPE_DATA;
+ pAd->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC;
+ pAd->NullFrame.FC.ToDs = 1;
+ COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid);
+ COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress);
+ COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid);
+ buf = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0];
+
+ RTMPZeroMemory(buf, 100);
+ pTxInfo = (TXINFO_STRUC *)buf;
+ pTxWI = (TXWI_STRUC *)&buf[TXINFO_SIZE];
+ rlt_usb_write_txinfo(pAd, pTxInfo,
+ (USHORT)(data_len + TXWISize + TSO_SIZE), TRUE,
+ EpToQueue[MGMTPIPEIDX], FALSE, FALSE, 1);
+ RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0,
+ BSSID_WCID, data_len, 0, 0,
+ (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS,
+ IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
+ RTMPMoveMemory((VOID *)&buf[TXWISize + TXINFO_SIZE], (VOID *)&pAd->NullFrame, data_len);
+ pNullContext->BulkOutSize = TXINFO_SIZE + TXWISize + TSO_SIZE + data_len + 4;
+
+}
+
+
+/*
+ We can do copy the frame into pTxContext when match following conditions.
+ =>
+ =>
+ =>
+*/
+static inline NDIS_STATUS RtmpUSBCanDoWrite(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR QueIdx,
+ IN HT_TX_CONTEXT *pHTTXContext)
+{
+ NDIS_STATUS canWrite = NDIS_STATUS_RESOURCES;
+
+#ifdef USB_BULK_BUF_ALIGMENT
+ if( ((pHTTXContext->CurWriteIdx< pHTTXContext->NextBulkIdx ) && (pHTTXContext->NextBulkIdx - pHTTXContext->CurWriteIdx == 1))
+ || ((pHTTXContext->CurWriteIdx ==(BUF_ALIGMENT_RINGSIZE -1) ) && (pHTTXContext->NextBulkIdx == 0 )))
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite USB_BULK_BUF_ALIGMENT c1!\n"));
+ RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
+ }
+ else if (pHTTXContext->bCurWriting == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite USB_BULK_BUF_ALIGMENT c3!!\n"));
+
+ }
+#else
+
+ if (((pHTTXContext->CurWritePosition) < pHTTXContext->NextBulkOutPosition) && (pHTTXContext->CurWritePosition + LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c1!\n"));
+ RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
+ }
+ else if ((pHTTXContext->CurWritePosition == 8) && (pHTTXContext->NextBulkOutPosition < LOCAL_TXBUF_SIZE))
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c2!\n"));
+ RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
+ }
+ else if (pHTTXContext->bCurWriting == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c3!\n"));
+ }
+ else if ((pHTTXContext->ENextBulkOutPosition == 8) && ((pHTTXContext->CurWritePosition + 7912 ) > MAX_TXBULK_LIMIT) )
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("RtmpUSBCanDoWrite c4!\n"));
+ RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
+ }
+
+#endif /* USB_BULK_BUF_ALIGMENT */
+ else
+ {
+ canWrite = NDIS_STATUS_SUCCESS;
+ }
+
+
+ return canWrite;
+}
+
+
+USHORT RtmpUSB_WriteSubTxResource(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_BLK *pTxBlk,
+ IN BOOLEAN bIsLast,
+ OUT USHORT *freeCnt)
+{
+
+ /* Dummy function. Should be removed in the future.*/
+ return 0;
+
+}
+
+USHORT RtmpUSB_WriteFragTxResource(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_BLK *pTxBlk,
+ IN UCHAR fragNum,
+ OUT USHORT *freeCnt)
+{
+ HT_TX_CONTEXT *pHTTXContext;
+ USHORT hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length.*/
+ UINT32 fillOffset;
+ TXINFO_STRUC *pTxInfo;
+ TXWI_STRUC *pTxWI;
+ PUCHAR pWirelessPacket = NULL;
+ UCHAR QueIdx;
+ NDIS_STATUS Status;
+ unsigned long IrqFlags;
+ UINT32 USBDMApktLen = 0, DMAHdrLen, padding;
+#ifdef USB_BULK_BUF_ALIGMENT
+ BOOLEAN bLasAlignmentsectiontRound = FALSE;
+#else
+ BOOLEAN TxQLastRound = FALSE;
+#endif /* USB_BULK_BUF_ALIGMENT */
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+
+ /* get Tx Ring Resource & Dma Buffer address*/
+
+ QueIdx = pTxBlk->QueIdx;
+ pHTTXContext = &pAd->TxContext[QueIdx];
+
+ RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+ pHTTXContext = &pAd->TxContext[QueIdx];
+ fillOffset = pHTTXContext->CurWritePosition;
+
+ if(fragNum == 0)
+ {
+ /* Check if we have enough space for this bulk-out batch.*/
+ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ pHTTXContext->bCurWriting = TRUE;
+
+#ifndef USB_BULK_BUF_ALIGMENT
+ /* Reserve space for 8 bytes padding.*/
+ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
+ {
+ pHTTXContext->ENextBulkOutPosition += 8;
+ pHTTXContext->CurWritePosition += 8;
+ fillOffset += 8;
+ }
+#endif /* USB_BULK_BUF_ALIGMENT */
+ pTxBlk->Priv = 0;
+ pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
+ }
+ else
+ {
+ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+ return(Status);
+ }
+ }
+ else
+ {
+ /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.*/
+ Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ fillOffset += pTxBlk->Priv;
+ }
+ else
+ {
+ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+ return(Status);
+ }
+ }
+
+ NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), TXINFO_SIZE);
+ pTxInfo = (TXINFO_STRUC *)(&pTxBlk->HeaderBuf[0]);
+ pTxWI= (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
+
+ pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
+
+ /* copy TXWI + WLAN Header + LLC into DMA Header Buffer*/
+ /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);*/
+ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
+
+ /* Build our URB for USBD*/
+ DMAHdrLen = TXWISize + hwHdrLen;
+ USBDMApktLen = DMAHdrLen + pTxBlk->SrcBufLen;
+ padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment*/
+ USBDMApktLen += padding;
+
+ pTxBlk->Priv += (TXINFO_SIZE + USBDMApktLen);
+
+ /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + 802.11 header + payload*/
+#ifdef CONFIG_MULTI_CHANNEL
+ if ((QueIdx == QID_HCCA) && (pAd->Multi_Channel_Enable == TRUE))
+ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(USBDMApktLen),
+ FALSE, FIFO_EDCA2, FALSE, FALSE, 1);
+ else
+#endif /* CONFIG_MULTI_CHANNEL */
+ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(USBDMApktLen), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE, 1);
+
+ if (fragNum == pTxBlk->TotalFragNum)
+ {
+ pTxInfo->TxInfoUDMATxburst = 0;
+
+#ifdef USB_BULK_BUF_ALIGMENT
+ /*
+ when CurWritePosition > 0x6000 mean that it is at the max bulk out size,
+ we CurWriteIdx must move to the next alignment section.
+ Otherwirse, CurWriteIdx will be moved to the next section at databulkout.
+
+
+ (((pHTTXContext->CurWritePosition + 3906)& 0x00007fff) & 0xffff6000) == 0x00006000)
+ we must make sure that the last fragNun packet just over the 0x6000
+ otherwise it will error because the last frag packet will at the section but will not bulk out.
+ ex: when secoend packet writeresouce and it > 0x6000
+ And the last packet writesource and it also > 0x6000 at this time CurWriteIdx++
+ but when data bulk out , because at second packet it will > 0x6000 , the last packet will not bulk out.
+
+ */
+
+ if ( ((pHTTXContext->CurWritePosition + 3906) & 0x00006000) == 0x00006000)
+ {
+
+ bLasAlignmentsectiontRound = TRUE;
+ pTxInfo->bFragLasAlignmentsectiontRound = 1;
+ }
+#else
+ if ((pHTTXContext->CurWritePosition + pTxBlk->Priv + 3906)> MAX_TXBULK_LIMIT)
+ {
+ pTxInfo->TxInfoSwLstRnd = 1;
+ TxQLastRound = TRUE;
+ }
+#endif /* USB_BULK_BUF_ALIGMENT */
+ }
+ else
+ {
+ pTxInfo->TxInfoUDMATxburst = 1;
+ }
+
+ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWISize + hwHdrLen);
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWISize), DIR_WRITE, FALSE);
+#endif /* RT_BIG_ENDIAN */
+ pWirelessPacket += (TXINFO_SIZE + TXWISize + hwHdrLen);
+ pHTTXContext->CurWriteRealPos += (TXINFO_SIZE + TXWISize + hwHdrLen);
+
+ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+ NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
+
+ /* Zero the last padding.*/
+ pWirelessPacket += pTxBlk->SrcBufLen;
+ NdisZeroMemory(pWirelessPacket, padding + 8);
+
+ if (fragNum == pTxBlk->TotalFragNum)
+ {
+ RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+ /* Update the pHTTXContext->CurWritePosition. 3906 used to prevent the NextBulkOut is a A-RALINK/A-MSDU Frame.*/
+ pHTTXContext->CurWritePosition += pTxBlk->Priv;
+#ifndef USB_BULK_BUF_ALIGMENT
+ if (TxQLastRound == TRUE)
+ pHTTXContext->CurWritePosition = 8;
+#endif /* USB_BULK_BUF_ALIGMENT */
+#ifdef USB_BULK_BUF_ALIGMENT
+ if(bLasAlignmentsectiontRound == TRUE)
+ {
+ pHTTXContext->CurWritePosition = ((CUR_WRITE_IDX_INC(pHTTXContext->CurWriteIdx, BUF_ALIGMENT_RINGSIZE)) * 0x8000);
+ }
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+ pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
+
+#ifdef UAPSD_SUPPORT
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ UAPSD_TagFrame(pAd, pTxBlk->pPacket, pTxBlk->Wcid, pHTTXContext->CurWritePosition);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* UAPSD_SUPPORT */
+
+ /* Finally, set bCurWriting as FALSE*/
+ pHTTXContext->bCurWriting = FALSE;
+
+ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+ /* succeed and release the skb buffer*/
+ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
+ }
+
+
+ return(Status);
+
+}
+
+
+USHORT RtmpUSB_WriteSingleTxResource(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_BLK *pTxBlk,
+ IN BOOLEAN bIsLast,
+ OUT USHORT *freeCnt)
+{
+ HT_TX_CONTEXT *pHTTXContext;
+ UINT32 fillOffset;
+ TXINFO_STRUC *pTxInfo;
+ TXWI_STRUC *pTxWI;
+ UCHAR *pWirelessPacket, *buf;
+ UCHAR QueIdx;
+ unsigned long IrqFlags;
+ NDIS_STATUS Status;
+ UINT32 hdr_copy_len, hdr_len, dma_len = 0, padding;
+#ifndef USB_BULK_BUF_ALIGMENT
+ BOOLEAN bTxQLastRound = FALSE;
+#endif /* USB_BULK_BUF_ALIGMENT */
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+ /* get Tx Ring Resource & Dma Buffer address*/
+ QueIdx = pTxBlk->QueIdx;
+
+ RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+ pHTTXContext = &pAd->TxContext[QueIdx];
+ fillOffset = pHTTXContext->CurWritePosition;
+
+
+
+ /* Check ring full */
+ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
+ if(Status == NDIS_STATUS_SUCCESS)
+ {
+ pHTTXContext->bCurWriting = TRUE;
+ buf = &pTxBlk->HeaderBuf[0];
+ pTxInfo = (TXINFO_STRUC *)buf;
+ pTxWI= (TXWI_STRUC *)&buf[TXINFO_SIZE];
+
+#ifndef USB_BULK_BUF_ALIGMENT
+ /* Reserve space for 8 bytes padding.*/
+ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
+ {
+ pHTTXContext->ENextBulkOutPosition += 8;
+ pHTTXContext->CurWritePosition += 8;
+ fillOffset += 8;
+ }
+#endif /* USB_BULK_BUF_ALIGMENT */
+ pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
+
+ pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
+
+ /* Build our URB for USBD */
+ hdr_len = TXWISize + TSO_SIZE + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
+ hdr_copy_len = TXINFO_SIZE + hdr_len;
+ dma_len = hdr_len + pTxBlk->SrcBufLen;
+ padding = (4 - (dma_len % 4)) & 0x03; /* round up to 4 byte alignment*/
+ dma_len += padding;
+
+ pTxBlk->Priv = (TXINFO_SIZE + dma_len);
+
+ /* For TxInfo, the length of USBDMApktLen = TXWI_SIZE + TSO_SIZE + 802.11 header + payload */
+#ifdef HDR_TRANS_SUPPORT
+#ifdef CONFIG_MULTI_CHANNEL
+ if ((QueIdx == QID_HCCA) && (pAd->Multi_Channel_Enable == TRUE))
+ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(dma_len), FALSE, FIFO_EDCA2, FALSE /*NextValid*/, FALSE, pTxBlk->NeedTrans?0:1);
+ else
+#endif /* CONFIG_MULTI_CHANNEL */
+ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(dma_len), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE, pTxBlk->NeedTrans?0:1);
+#else
+#ifdef CONFIG_MULTI_CHANNEL
+ if ((QueIdx == QID_HCCA) && (pAd->Multi_Channel_Enable == TRUE))
+ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(dma_len), FALSE, FIFO_EDCA2, FALSE /*NextValid*/, FALSE, 1);
+ else
+#endif /* CONFIG_MULTI_CHANNEL */
+ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(dma_len), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE, 1);
+#endif /* HDR_TRANS_SUPPORT */
+
+
+#ifndef USB_BULK_BUF_ALIGMENT
+ if ((pHTTXContext->CurWritePosition + 3906 + pTxBlk->Priv) > MAX_TXBULK_LIMIT)
+ {
+ pTxInfo->TxInfoSwLstRnd = 1;
+ bTxQLastRound = TRUE;
+ }
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, hdr_copy_len);
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket + TXINFO_SIZE + TXWISize + TSO_SIZE), DIR_WRITE, FALSE);
+#endif /* RT_BIG_ENDIAN */
+ pWirelessPacket += (hdr_copy_len);
+
+ /* We unlock it here to prevent the first 8 bytes maybe over-writed issue.*/
+ /* 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxcontext.*/
+ /* 2. An interrupt break our routine and handle bulk-out complete.*/
+ /* 3. In the bulk-out compllete, it need to do another bulk-out, */
+ /* if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,*/
+ /* but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.*/
+ /* 4. Interrupt complete.*/
+ /* 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.*/
+ /* 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.*/
+ /* and the packet will wrong.*/
+ pHTTXContext->CurWriteRealPos += hdr_copy_len;
+#ifndef USB_BULK_BUF_ALIGMENT
+ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+#ifdef TX_PKT_SG
+ if (pTxBlk->pkt_info.BufferCount > 1) {
+ INT i, len;
+ void *data;
+ PKT_SG_T *sg = &pTxBlk->pkt_info.sg_list[0];
+
+ for (i = 0 ; i < pTxBlk->pkt_info.BufferCount; i++) {
+ data = sg[i].data;
+ len = sg[i].len;
+ if (i == 0) {
+ len -= ((ULONG)pTxBlk->pSrcBufData - (ULONG)sg[i].data);
+ data = pTxBlk->pSrcBufData;
+ }
+ //DBGPRINT(RT_DEBUG_TRACE, ("%s:sg[%d]=0x%x, len=%d\n", __FUNCTION__, i, data, len));
+ if (len <= 0) {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s():sg[%d] info error, sg.data=0x%x, sg.len=%d, pTxBlk->pSrcBufData=0x%x, pTxBlk->SrcBufLen=%d, data=0x%x, len=%d\n",
+ __FUNCTION__, i, sg[i].data, sg[i].len, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, data, len));
+ break;
+ }
+ NdisMoveMemory(pWirelessPacket, data, len);
+ pWirelessPacket += len;
+ }
+ }
+ else
+#endif /* TX_PKT_SG */
+ {
+ NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
+ pWirelessPacket += pTxBlk->SrcBufLen;
+ }
+
+#ifndef USB_BULK_BUF_ALIGMENT
+ NdisZeroMemory(pWirelessPacket, padding + 8);
+ RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+ pHTTXContext->CurWritePosition += pTxBlk->Priv;
+#ifdef UAPSD_SUPPORT
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ UAPSD_TagFrame(pAd, pTxBlk->pPacket, pTxBlk->Wcid, pHTTXContext->CurWritePosition);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* UAPSD_SUPPORT */
+#ifdef USB_BULK_BUF_ALIGMENT
+ /*
+ when CurWritePosition > 0x6000 mean that it is at the max bulk out size,
+ we CurWriteIdx must move to the next alignment section.
+ Otherwirse, CurWriteIdx will be moved to the next section at databulkout.
+
+ Writingflag = TRUE ,mean that when we writing resource ,and databulkout happen,
+ So we bulk out when this packet finish.
+ */
+ if ( (pHTTXContext->CurWritePosition & 0x00006000) == 0x00006000)
+ {
+ pHTTXContext->CurWritePosition = ((CUR_WRITE_IDX_INC(pHTTXContext->CurWriteIdx, BUF_ALIGMENT_RINGSIZE)) * 0x8000);
+ }
+#else
+ if (bTxQLastRound)
+ pHTTXContext->CurWritePosition = 8;
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+ pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
+ pHTTXContext->bCurWriting = FALSE;
+ }
+
+
+ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+
+ /* succeed and release the skb buffer*/
+ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
+
+ return(Status);
+
+}
+
+
+USHORT RtmpUSB_WriteMultiTxResource(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_BLK *pTxBlk,
+ IN UCHAR frmNum,
+ OUT USHORT *freeCnt)
+{
+ HT_TX_CONTEXT *pHTTXContext;
+ USHORT hwHdrLen; /* The hwHdrLen consist of 802.11 header length plus the header padding length.*/
+ UINT32 fillOffset;
+ TXINFO_STRUC *pTxInfo;
+ TXWI_STRUC *pTxWI;
+ UCHAR *pWirelessPacket = NULL;
+ UCHAR QueIdx;
+ NDIS_STATUS Status;
+ unsigned long IrqFlags;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+
+ /* get Tx Ring Resource & Dma Buffer address*/
+ QueIdx = pTxBlk->QueIdx;
+ pHTTXContext = &pAd->TxContext[QueIdx];
+
+ RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+ if(frmNum == 0)
+ {
+ /* Check if we have enough space for this bulk-out batch.*/
+ Status = RtmpUSBCanDoWrite(pAd, QueIdx, pHTTXContext);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ pHTTXContext->bCurWriting = TRUE;
+
+ pTxInfo = (TXINFO_STRUC *)(&pTxBlk->HeaderBuf[0]);
+ pTxWI= (TXWI_STRUC *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]);
+
+#ifndef USB_BULK_BUF_ALIGMENT
+ /* Reserve space for 8 bytes padding.*/
+ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition))
+ {
+
+ pHTTXContext->CurWritePosition += 8;
+ pHTTXContext->ENextBulkOutPosition += 8;
+ }
+#endif /* USB_BULK_BUF_ALIGMENT */
+ fillOffset = pHTTXContext->CurWritePosition;
+ pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
+
+ pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
+
+
+ /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer*/
+
+ if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
+ /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;*/
+ hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
+ else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
+ /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;*/
+ hwHdrLen = pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
+ else
+ /*hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);*/
+ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
+
+ /* Update the pTxBlk->Priv.*/
+ pTxBlk->Priv = TXINFO_SIZE + TXWISize + hwHdrLen;
+
+ /* pTxInfo->USBDMApktLen now just a temp value and will to correct latter.*/
+#ifdef CONFIG_MULTI_CHANNEL
+ if ((QueIdx == QID_HCCA) && (pAd->Multi_Channel_Enable == TRUE))
+ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA2, FALSE /*NextValid*/, FALSE, 1);
+ else
+#endif /* CONFIG_MULTI_CHANNEL */
+
+ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(pTxBlk->Priv), FALSE, FIFO_EDCA, FALSE /*NextValid*/, FALSE, 1);
+
+ /* Copy it.*/
+ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->Priv);
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)(pWirelessPacket+ TXINFO_SIZE + TXWISize), DIR_WRITE, FALSE);
+#endif /* RT_BIG_ENDIAN */
+ pHTTXContext->CurWriteRealPos += pTxBlk->Priv;
+ pWirelessPacket += pTxBlk->Priv;
+ }
+ }
+ else
+ { /* For sub-sequent frames of this bulk-out batch. Just copy it to our bulk-out buffer.*/
+
+ Status = ((pHTTXContext->bCurWriting == TRUE) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE);
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ fillOffset = (pHTTXContext->CurWritePosition + pTxBlk->Priv);
+ pWirelessPacket = &pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset];
+
+ /*hwHdrLen = pTxBlk->MpduHeaderLen;*/
+ NdisMoveMemory(pWirelessPacket, pTxBlk->HeaderBuf, pTxBlk->MpduHeaderLen);
+ pWirelessPacket += (pTxBlk->MpduHeaderLen);
+ pTxBlk->Priv += pTxBlk->MpduHeaderLen;
+ }
+ else
+ { /* It should not happened now unless we are going to shutdown.*/
+ DBGPRINT(RT_DEBUG_ERROR, ("WriteMultiTxResource():bCurWriting is FALSE when handle sub-sequent frames.\n"));
+ Status = NDIS_STATUS_FAILURE;
+ }
+ }
+
+
+ /*
+ We unlock it here to prevent the first 8 bytes maybe over-write issue.
+ 1. First we got CurWritePosition but the first 8 bytes still not write to the pTxContext.
+ 2. An interrupt break our routine and handle bulk-out complete.
+ 3. In the bulk-out compllete, it need to do another bulk-out,
+ if the ENextBulkOutPosition is just the same as CurWritePosition, it will save the first 8 bytes from CurWritePosition,
+ but the payload still not copyed. the pTxContext->SavedPad[] will save as allzero. and set the bCopyPad = TRUE.
+ 4. Interrupt complete.
+ 5. Our interrupted routine go back and fill the first 8 bytes to pTxContext.
+ 6. Next time when do bulk-out, it found the bCopyPad==TRUE and will copy the SavedPad[] to pTxContext->NextBulkOutPosition.
+ and the packet will wrong.
+ */
+ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("WriteMultiTxResource: CWPos = %ld, NBOutPos = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition));
+ goto done;
+ }
+
+ /* Copy the frame content into DMA buffer and update the pTxBlk->Priv*/
+ NdisMoveMemory(pWirelessPacket, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen);
+ pWirelessPacket += pTxBlk->SrcBufLen;
+ pTxBlk->Priv += pTxBlk->SrcBufLen;
+
+done:
+ /* Release the skb buffer here*/
+ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_SUCCESS);
+
+ return(Status);
+
+}
+
+
+VOID RtmpUSB_FinalWriteTxResource(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_BLK *pTxBlk,
+ IN USHORT totalMPDUSize,
+ IN USHORT TxIdx)
+{
+ UCHAR QueIdx;
+ HT_TX_CONTEXT *pHTTXContext;
+ UINT32 fillOffset;
+ TXINFO_STRUC *pTxInfo;
+ TXWI_STRUC *pTxWI;
+ UINT32 USBDMApktLen, padding;
+ unsigned long IrqFlags;
+ PUCHAR pWirelessPacket;
+
+ QueIdx = pTxBlk->QueIdx;
+ pHTTXContext = &pAd->TxContext[QueIdx];
+
+ RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+ if (pHTTXContext->bCurWriting == TRUE)
+ {
+ fillOffset = pHTTXContext->CurWritePosition;
+#ifndef USB_BULK_BUF_ALIGMENT
+ if (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition))
+ && (pHTTXContext->bCopySavePad == TRUE))
+ pWirelessPacket = (PUCHAR)(&pHTTXContext->SavedPad[0]);
+ else
+#endif /* USB_BULK_BUF_ALIGMENT */
+ pWirelessPacket = (PUCHAR)(&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset]);
+
+
+ /* Update TxInfo->USBDMApktLen , */
+ /* the length = TXWI_SIZE + 802.11_hdr + 802.11_hdr_pad + payload_of_all_batch_frames + Bulk-Out-padding*/
+
+ pTxInfo = (TXINFO_STRUC *)(pWirelessPacket);
+
+ /* Calculate the bulk-out padding*/
+ USBDMApktLen = pTxBlk->Priv - TXINFO_SIZE;
+ padding = (4 - (USBDMApktLen % 4)) & 0x03; /* round up to 4 byte alignment*/
+ USBDMApktLen += padding;
+
+ pTxInfo->TxInfoPktLen = USBDMApktLen;
+
+
+ /*
+ Update TXWI->TxWIMPDUByteCnt,
+ the length = 802.11 header + payload_of_all_batch_frames
+ */
+ pTxWI= (TXWI_STRUC *)(pWirelessPacket + TXINFO_SIZE);
+ pTxWI->TxWIMPDUByteCnt = totalMPDUSize;
+
+
+ /* Update the pHTTXContext->CurWritePosition*/
+
+ pHTTXContext->CurWritePosition += (TXINFO_SIZE + USBDMApktLen);
+#ifdef USB_BULK_BUF_ALIGMENT
+ /*
+ when CurWritePosition > 0x6000 mean that it is at the max bulk out size,
+ we CurWriteIdx must move to the next alignment section.
+ Otherwirse, CurWriteIdx will be moved to the next section at databulkout.
+
+ Writingflag = TRUE ,mean that when we writing resource ,and databulkout happen,
+ So we bulk out when this packet finish.
+ */
+
+ if ( (pHTTXContext->CurWritePosition & 0x00006000) == 0x00006000)
+ {
+ pHTTXContext->CurWritePosition = ((CUR_WRITE_IDX_INC(pHTTXContext->CurWriteIdx, BUF_ALIGMENT_RINGSIZE)) * 0x8000);
+ }
+#else
+ if ((pHTTXContext->CurWritePosition + 3906)> MAX_TXBULK_LIMIT)
+ { /* Add 3906 for prevent the NextBulkOut packet size is a A-RALINK/A-MSDU Frame.*/
+ pHTTXContext->CurWritePosition = 8;
+ pTxInfo->TxInfoSwLstRnd = 1;
+ }
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+ pHTTXContext->CurWriteRealPos = pHTTXContext->CurWritePosition;
+
+#ifdef UAPSD_SUPPORT
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ UAPSD_TagFrame(pAd, pTxBlk->pPacket, pTxBlk->Wcid, pHTTXContext->CurWritePosition);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* UAPSD_SUPPORT */
+
+
+ /* Zero the last padding.*/
+ pWirelessPacket = (&pHTTXContext->TransferBuffer->field.WirelessPacket[fillOffset + pTxBlk->Priv]);
+ NdisZeroMemory(pWirelessPacket, padding + 8);
+
+ /* Finally, set bCurWriting as FALSE*/
+ pHTTXContext->bCurWriting = FALSE;
+
+ }
+ else
+ { /* It should not happened now unless we are going to shutdown.*/
+ DBGPRINT(RT_DEBUG_ERROR, ("FinalWriteTxResource():bCurWriting is FALSE when handle last frames.\n"));
+ }
+
+ RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[QueIdx], IrqFlags);
+
+}
+
+
+VOID RtmpUSBDataLastTxIdx(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR QueIdx,
+ IN USHORT TxIdx)
+{
+ /* DO nothing for USB.*/
+}
+
+
+/*
+ When can do bulk-out:
+ 1. TxSwFreeIdx < TX_RING_SIZE;
+ It means has at least one Ring entity is ready for bulk-out, kick it out.
+ 2. If TxSwFreeIdx == TX_RING_SIZE
+ Check if the CurWriting flag is FALSE, if it's FALSE, we can do kick out.
+
+*/
+VOID RtmpUSBDataKickOut(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_BLK *pTxBlk,
+ IN UCHAR QueIdx)
+{
+
+#ifdef CONFIG_MULTI_CHANNEL
+ if ((pAd->MultiChannelFlowCtl & (1 << QueIdx)) == (1 << QueIdx))
+ {
+ return;
+ }
+#endif /* CONFIG_MULTI_CHANNEL */
+ RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx));
+ RTUSBKickBulkOut(pAd);
+
+}
+
+
+/*
+ Must be run in Interrupt context
+ This function handle RT2870 specific TxDesc and cpu index update and kick the packet out.
+ */
+int RtmpUSBMgmtKickOut(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket,
+ IN UCHAR *pSrcBufVA,
+ IN UINT SrcBufLen)
+{
+ TXINFO_STRUC *pTxInfo;
+ ULONG BulkOutSize;
+ UCHAR padLen;
+ PUCHAR pDest;
+ ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
+ TX_CONTEXT *pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[SwIdx].AllocVa;
+ ULONG IrqFlags;
+
+
+ pTxInfo = (TXINFO_STRUC *)(pSrcBufVA);
+
+ /* Build our URB for USBD*/
+ BulkOutSize = (SrcBufLen + 3) & (~3);
+ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(BulkOutSize - TXINFO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE, 1);
+
+ BulkOutSize += 4; /* Always add 4 extra bytes at every packet.*/
+
+//+++Add by shiang for debug
+if (0) {
+ DBGPRINT(RT_DEBUG_OFF, ("-->%s():shiang-6590, QueIdx=%d, SrcBufLen=%d\n", __FUNCTION__, QueIdx, SrcBufLen));
+ dump_txinfo(pAd, pTxInfo);
+ dumpTxWI(pAd, (TXWI_STRUC *)(pSrcBufVA + TXINFO_SIZE));
+}
+//---Add by shiang for debug
+
+/* WY , it cause Tx hang on Amazon_SE , Max said the padding is useless*/
+ /* If BulkOutSize is multiple of BulkOutMaxPacketSize, add extra 4 bytes again.*/
+/* if ((BulkOutSize % pAd->BulkOutMaxPacketSize) == 0)*/
+/* BulkOutSize += 4;*/
+
+ padLen = BulkOutSize - SrcBufLen;
+ ASSERT((padLen <= RTMP_PKT_TAIL_PADDING));
+
+ /* Now memzero all extra padding bytes.*/
+ pDest = (PUCHAR)(pSrcBufVA + SrcBufLen);
+ OS_PKT_TAIL_BUF_EXTEND(pPacket, padLen);
+ NdisZeroMemory(pDest, padLen);
+
+ RTMP_IRQ_LOCK(&pAd->MLMEBulkOutLock, IrqFlags);
+
+ pAd->MgmtRing.Cell[pAd->MgmtRing.TxCpuIdx].pNdisPacket = pPacket;
+ pMLMEContext->TransferBuffer = (PTX_BUFFER)(GET_OS_PKT_DATAPTR(pPacket));
+
+ /* Length in TxInfo should be 8 less than bulkout size.*/
+ pMLMEContext->BulkOutSize = BulkOutSize;
+ pMLMEContext->InUse = TRUE;
+ pMLMEContext->bWaitingBulkOut = TRUE;
+
+#ifdef UAPSD_SUPPORT
+ /*
+ If the packet is QoS Null frame, we mark the packet with its WCID;
+ If not, we mark the packet with bc/mc WCID = 0.
+
+ We will handle it in rtusb_mgmt_dma_done_tasklet().
+
+ Even AP send a QoS Null frame but not EOSP frame in USB mode,
+ then we will call UAPSD_SP_Close() and we will check
+ pEntry->bAPSDFlagSPStart() so do not worry about it.
+ */
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if (RTMP_GET_PACKET_QOS_NULL(pPacket) != 0x00)
+ pMLMEContext->Wcid = RTMP_GET_PACKET_WCID(pPacket);
+ else
+ pMLMEContext->Wcid = MCAST_WCID;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* UAPSD_SUPPORT */
+
+ /*hex_dump("RtmpUSBMgmtKickOut", &pMLMEContext->TransferBuffer->field.WirelessPacket[0], (pMLMEContext->BulkOutSize > 16 ? 16 : pMLMEContext->BulkOutSize));*/
+
+/*
+ pAd->RalinkCounters.KickTxCount++;
+ pAd->RalinkCounters.OneSecTxDoneCount++;
+
+ if (pAd->MgmtRing.TxSwFreeIdx == MGMT_RING_SIZE)
+ needKickOut = TRUE;
+*/
+
+ /* Decrease the TxSwFreeIdx and Increase the TX_CTX_IDX*/
+ pAd->MgmtRing.TxSwFreeIdx--;
+ INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
+
+ RTMP_IRQ_UNLOCK(&pAd->MLMEBulkOutLock, IrqFlags);
+
+ RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
+ /*if (needKickOut)*/
+ RTUSBKickBulkOut(pAd);
+
+ return 0;
+}
+
+
+VOID RtmpUSBNullFrameKickOut(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR QueIdx,
+ IN UCHAR *pNullFrame,
+ IN UINT32 frameLen)
+{
+
+ PTX_CONTEXT pNullContext = &pAd->NullContext[0];
+
+#ifdef CONFIG_MULTI_CHANNEL
+
+
+ if (QueIdx == EDCA_AC0_PIPE)
+ {
+ pNullContext = &pAd->NullContext[0];
+ }
+ else if (QueIdx == HCCA_PIPE)
+ {
+ pNullContext = &pAd->NullContext[1];
+ }
+ else
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow pipe!!\n", __FUNCTION__));
+
+#endif /* CONFIG_MULTI_CHANNEL */
+ if (pNullContext->InUse == FALSE)
+ {
+ PTX_CONTEXT pNullContext;
+ TXINFO_STRUC *pTxInfo;
+ TXWI_STRUC *pTxWI;
+ UCHAR *pWirelessPkt;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+ pNullContext = &(pAd->NullContext[0]);
+
+ /* Set the in use bit*/
+ pNullContext->InUse = TRUE;
+ pWirelessPkt = (PUCHAR)&pNullContext->TransferBuffer->field.WirelessPacket[0];
+
+ RTMPZeroMemory(&pWirelessPkt[0], 100);
+ pTxInfo = (TXINFO_STRUC *)&pWirelessPkt[0];
+ rlt_usb_write_txinfo(pAd, pTxInfo, (USHORT)(frameLen + TXWISize + TSO_SIZE), TRUE, EpToQueue[MGMTPIPEIDX], FALSE, FALSE, 1);
+ pTxInfo->TxInfoQSEL = FIFO_EDCA;
+ pTxWI = (TXWI_STRUC *)&pWirelessPkt[TXINFO_SIZE];
+ RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, BSSID_WCID, frameLen,
+ 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit);
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI);
+#endif /* RT_BIG_ENDIAN */
+ RTMPMoveMemory(&pWirelessPkt[TXWISize + TXINFO_SIZE + TSO_SIZE], pNullFrame, frameLen);
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)&pWirelessPkt[TXINFO_SIZE + TXWISize + TSO_SIZE], DIR_WRITE, FALSE);
+#endif /* RT_BIG_ENDIAN */
+ pNullContext->BulkOutSize = TXINFO_SIZE + TXWISize + TSO_SIZE + frameLen + 4;
+
+
+ /* Fill out frame length information for global Bulk out arbitor*/
+ /*pNullContext->BulkOutSize = TransferBufferLength;*/
+ DBGPRINT(RT_DEBUG_TRACE, ("%s - Send NULL Frame @%d Mbps...\n", __FUNCTION__, RateIdToMbps[pAd->CommonCfg.TxRate]));
+#ifdef CONFIG_MULTI_CHANNEL
+ if ((QueIdx == HCCA_PIPE) && (pAd->Multi_Channel_Enable == TRUE))
+ RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL_HCCA);
+ else
+#endif /* CONFIG_MULTI_CHANNEL */
+ RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL);
+
+ pAd->Sequence = (pAd->Sequence+1) & MAXSEQ;
+
+ /* Kick bulk out */
+ RTUSBKickBulkOut(pAd);
+ }
+
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Get a received packet.
+
+Arguments:
+ pAd device control block
+ pSaveRxD receive descriptor information
+ *pbReschedule need reschedule flag
+ *pRxPending pending received packet flag
+
+Return Value:
+ the recieved packet
+
+Note:
+========================================================================
+*/
+PNDIS_PACKET GetPacketFromRxRing(
+ IN RTMP_ADAPTER *pAd,
+ OUT RX_BLK *pRxBlk,
+ OUT BOOLEAN *pbReschedule,
+ INOUT UINT32 *pRxPending)
+{
+ RX_CONTEXT *pRxContext;
+ PNDIS_PACKET pNetPkt;
+ UCHAR *pData;
+ ULONG ThisFrameLen, RxBufferLength, valid_len;
+ RXWI_STRUC *pRxWI;
+ UINT8 RXWISize = pAd->chipCap.RXWISize;
+ RXINFO_STRUC *pRxInfo;
+#ifdef RLT_MAC
+ RXFCE_INFO *pRxFceInfo;
+#endif /* RLT_MAC */
+
+
+ pRxContext = &pAd->RxContext[pAd->NextRxBulkInReadIndex];
+ if ((pRxContext->Readable == FALSE) || (pRxContext->InUse == TRUE))
+ return NULL;
+
+ RxBufferLength = pRxContext->BulkInOffset - pAd->ReadPosition;
+ valid_len = RXDMA_FIELD_SIZE + RXWISize + sizeof(RXINFO_STRUC);
+#ifdef RLT_MAC
+ valid_len += sizeof(RXFCE_INFO);
+#endif /* RLT_MAC */
+ if (RxBufferLength < valid_len)
+ {
+ goto label_null;
+ }
+
+ pData = &pRxContext->TransferBuffer[pAd->ReadPosition];
+//+++Add by shiang for debug
+if (0) {
+ hex_dump("GetPacketFromRxRing", pData, (RxBufferLength > 7000 ? 7000 : RxBufferLength));
+}
+//---Add by shiang for debug
+
+ /* The RXDMA field is 4 bytes, now just use the first 2 bytes. The Length including the (RXWI + MSDU + Padding) */
+ ThisFrameLen = *pData + (*(pData+1)<<8);
+ if (ThisFrameLen == 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("BIRIdx(%d): RXDMALen is zero.[%ld], BulkInBufLen = %ld)\n",
+ pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset));
+ goto label_null;
+ }
+ if ((ThisFrameLen & 0x3) != 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("BIRIdx(%d): RXDMALen not multiple of 4.[%ld], BulkInBufLen = %ld)\n",
+ pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset));
+ goto label_null;
+ }
+
+ if ((ThisFrameLen + 8) > RxBufferLength) /* 8 for (RXDMA_FIELD_SIZE + sizeof(RXINFO_STRUC))*/
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("BIRIdx(%d):FrameLen(0x%lx) outranges. BulkInLen=0x%lx, remaining RxBufLen=0x%lx, ReadPos=0x%lx\n",
+ pAd->NextRxBulkInReadIndex, ThisFrameLen, pRxContext->BulkInOffset, RxBufferLength, pAd->ReadPosition));
+
+ /* error frame. finish this loop*/
+ goto label_null;
+ }
+
+ /* skip USB frame length field*/
+ pData += RXDMA_FIELD_SIZE;
+#ifdef RLT_MAC
+ pRxInfo = (RXINFO_STRUC *)pData;
+ pRxFceInfo = (RXFCE_INFO *)(pData + ThisFrameLen);
+
+ pData += RXINFO_SIZE;
+#endif /* RLT_MAC */
+#ifdef RTMP_MAC
+ pRxInfo = (RXINFO_STRUC *)(pData + ThisFrameLen);
+#endif /* RTMP_MAC */
+
+ pRxWI = (RXWI_STRUC *)pData;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange(pAd, pData, TYPE_RXWI);
+#endif /* RT_BIG_ENDIAN */
+ if (pRxWI->RxWIMPDUByteCnt > ThisFrameLen)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s():pRxWIMPDUtotalByteCount(%d) large than RxDMALen(%ld)\n",
+ __FUNCTION__, pRxWI->RxWIMPDUByteCnt, ThisFrameLen));
+ goto label_null;
+ }
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange(pAd, pData, TYPE_RXWI);
+#endif /* RT_BIG_ENDIAN */
+
+ /* allocate a rx packet*/
+ pNetPkt = RTMP_AllocateFragPacketBuffer(pAd, ThisFrameLen);
+ if (pNetPkt == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("%s():Cannot Allocate sk buffer for this Bulk-In buffer!\n", __FUNCTION__));
+ goto label_null;
+ }
+
+ /* copy the rx packet*/
+ RTMP_USB_PKT_COPY(get_netdev_from_bssid(pAd, BSS0), pNetPkt, ThisFrameLen, pData);
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pRxInfo, TYPE_RXINFO);
+#endif /* RT_BIG_ENDIAN */
+
+#ifdef RLT_MAC
+ NdisMoveMemory((VOID *)&pRxBlk->hw_rx_info[0], (VOID *)pRxFceInfo, sizeof(RXFCE_INFO));
+ pRxBlk->pRxFceInfo = (RXFCE_INFO *)&pRxBlk->hw_rx_info[0];
+#endif /* RLT_MAC */
+
+ NdisMoveMemory(&pRxBlk->hw_rx_info[RXINFO_OFFSET], pRxInfo, RXINFO_SIZE);
+ pRxBlk->pRxInfo = (RXINFO_STRUC *)&pRxBlk->hw_rx_info[RXINFO_OFFSET];
+
+
+ /* update next packet read position.*/
+ pAd->ReadPosition += (ThisFrameLen + RXDMA_FIELD_SIZE + RXINFO_SIZE); /* 8 for (RXDMA_FIELD_SIZE + sizeof(RXINFO_STRUC))*/
+
+ return pNetPkt;
+
+label_null:
+
+ return NULL;
+}
+
+
+
+#endif /* RTMP_MAC_USB */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_dfs.c b/cleopatre/devkit/mt7601udrv/common/cmm_dfs.c
new file mode 100644
index 0000000000..46c5bcae3a
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_dfs.c
@@ -0,0 +1,3136 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ ap_dfs.c
+
+ Abstract:
+ Support DFS function.
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+*/
+
+#include "rt_config.h"
+
+#ifdef DFS_SUPPORT
+#ifdef CONFIG_AP_SUPPORT
+
+#ifdef DFS_DEBUG
+NewDFSDebugResult TestResult[1000];
+#endif
+
+NewDFSValidRadar NewDFSValidTable[] =
+{
+ /* FCC-1 && (Japan W53 Radar 1 / W56 Radar 2)*/
+ {
+ (NEW_DFS_FCC | NEW_DFS_JAP | NEW_DFS_JAP_W53),
+ 7,
+ 10, 1000,
+ 0,
+ 4,
+ 0, 0,
+ 28570 - 70,
+ 150
+ },
+ /* FCC-2*/
+ {
+ (NEW_DFS_FCC | NEW_DFS_JAP),
+ 7,
+ 13, 1000,
+ 0,
+ 1,
+ 3000, 4600 - 20,
+ 0,
+ 25
+ },
+ /* FCC-3 & FCC-4*/
+ {
+ (NEW_DFS_FCC | NEW_DFS_JAP),
+ 7,
+ /*120, 200, FCC-3 */
+ /*220, 400, FCC-4*/
+ 100, 1500,
+ 0,
+ 1,
+ 4000, 10000 - 40,
+ 0,
+ 60
+ },
+ /* FCC-6*/
+ {
+ (NEW_DFS_FCC | NEW_DFS_JAP),
+ 7,
+ 12, 1000,
+ 0,
+ 1,
+ 0, 0,
+ 6660-10,
+ 35
+ },
+ /* Japan W53 Radar 2*/
+ {
+ NEW_DFS_JAP_W53,
+ 7,
+ 40, 1000,
+ 0,
+ 1,
+ 0, 0,
+ 76923 - 30,
+ 180
+ },
+ /* Japan W56 Radar 1*/
+ {
+ NEW_DFS_JAP,
+ 7,
+ 5, 500,
+ 0,
+ 2,
+ 0, 0,
+ 27777 - 30,
+ 70
+ },
+ /* Japan W56 Radar 3*/
+ {
+ NEW_DFS_JAP,
+ 7,
+ 30, 1000,
+ 0,
+ 1,
+ 0, 0,
+ 80000 - 50,
+ 200
+ },
+
+/* CE Staggered radar*/
+
+ {
+ /* EN-1*/
+ /* width 0.8 - 5 us*/
+ /* PRF 200 - 1000 Hz*/
+ /* PRI 5000 - 1000 us (T: 20000 - 100000)*/
+ /* */
+ NEW_DFS_EU,
+ 0xf,
+ 10, 1000,
+ 0,
+ 1,
+ 20000-15, 100000-70,
+ 0,
+ 120
+ },
+ /* EN-2*/
+ /* width 0.8 - 15 us*/
+ /* PRF 200 - 1600 Hz*/
+ /* PRI 5000 - 625 us (T: 12500 - 100000)*/
+ {
+ NEW_DFS_EU,
+ 0xf,
+ 10, 2000,
+ 0,
+ 1,
+ 12500 - 10, 100000 - 70,
+ 0,
+ 120
+ },
+
+ /* EN-3*/
+ /* width 0.8 - 15 us*/
+ /* PRF 2300 - 4000 Hz*/
+ /* PRI 434 - 250 us (T: 5000 - 8695)*/
+ {
+ NEW_DFS_EU,
+ 0xf,
+ 21, 2000,
+ 0,
+ 1,
+ 5000 - 4, 8695 - 7,
+ 0,
+ 50
+ },
+ /* EN-4*/
+ /* width 20 - 30 us*/
+ /* PRF 2000 - 4000 Hz*/
+ /* PRI 500 - 250 us (T: 5000 - 10000)*/
+ /* Note : with Chirp Modulation +- 2,5Mhz*/
+ {
+ NEW_DFS_EU,
+ 0xf,
+ 380, 3000,
+ 0,
+ 4,
+ 5000 - 4, 10000 - 8,
+ 0,
+ 60
+ },
+ /* EN-5*/
+ /* width 0.8 - 2 us*/
+ /* PRF 300 - 400 Hz*/
+ /* PRI 3333 - 2500 us (T: 50000 - 66666)*/
+ /* Staggered PRF, 20 - 50 pps*/
+ {
+ NEW_DFS_EU,
+ 0xf,
+ 10, 800,
+ 0,
+ 1,
+ 50000 - 35, 66666 + 50,
+ 0,
+ 30
+ },
+ /* EN-6*/
+ /* width 0.8 - 2 us*/
+ /* PRF 400 - 1200 Hz*/
+ /* PRI 2500 - 833 us (T: 16666 - 50000)*/
+ /* Staggered PRF, 80 - 400 pps*/
+ {
+ NEW_DFS_EU,
+ 0xf,
+ 10, 800,
+ 0,
+ 1,
+ 16666 - 13, 50000 + 35,
+ 0,
+ 30
+ },
+
+ {
+ NEW_DFS_END,
+ 0,
+ 0, 0,
+ 0,
+ 0,
+ 0, 0,
+ 0,
+ 0,
+ },
+};
+
+static NewDFSTable NewDFSTable1[] =
+{
+ {
+ /* ch, mode(0~7), M(~511), el, eh(~4095), wl, wh(~4095), err_w, tl, th, err_t, bl, bh*/
+ NEW_DFS_FCC,
+ {
+ {0, 0, 10, 8, 16, 6, 2000, 5, 2900, 29000, 5, 0, 0},
+ {1, 0, 70, 42, 126, 20, 5000, 5, 2900, 29000, 10, 0, 0},
+ {2, 0, 100, 42, 160, 20, 5000, 25, 2900, 10100, 20, 0, 0},
+ {3, 2, 200, 20, 150, 900, 2200, 50, 1000, 999999999, 200, 0, 999999999},
+ }
+ },
+
+ {
+ NEW_DFS_EU,
+ {
+ {0, 0, 10, 10, 18, 4, 4095, 5, 7800, 101000, 5, 0, 0},
+ {1, 0, 70, 42, 90, 20, 4095, 3, 4900, 101000, 10, 0, 0},
+ {2, 0, 100, 42, 160, 20, 4095, 5, 4900, 101000, 20, 0, 0},
+ {3, 3, 200, 20, 150, 200, 4095, 100, 4900, 11000, 200, 0, 0},
+ {4, 8, 0, 8, 17, 7, 70, 2, 32500, 200500, 10, 0, 0},
+ /*{5, 1, 0, 12, 16, 8, 700, 5, 33000, 135000, 100, 0, 0},*/
+ }
+ },
+
+ {
+ NEW_DFS_JAP,
+ {
+ {0, 0, 10, 8, 16, 4, 2000, 5, 2900, 85000, 5, 0, 0},
+ {1, 0, 70, 48, 126, 20, 5000, 5, 2900, 85000, 10, 0, 0},
+ {2, 0, 100, 48, 160, 20, 5000, 25, 2900, 85000, 20, 0, 0},
+ {3, 2, 200, 20, 150, 900, 2200, 50, 1000, 999999999, 200, 0, 999999999},
+ }
+ },
+
+ {
+ NEW_DFS_JAP_W53,
+ {
+ {0, 0, 10, 8, 16, 8, 2000, 5, 28000, 85000, 10},
+ {1, 0, 32, 24, 64, 20, 2000, 5, 28000, 85000, 10},
+ {2, 0, 100, 42, 160, 20, 2000, 25, 28000, 85000, 10},
+ /*{3, 2, 200, 20, 150, 300, 2000, 50, 15000, 45000, 200},*/
+ }
+ },
+};
+
+static void dfs_sw_init(
+ IN PRTMP_ADAPTER pAd);
+
+static BOOLEAN StagerRadarCheck(
+ IN PRTMP_ADAPTER pAd,
+ UINT8 dfs_channel);
+
+static BOOLEAN ChirpRadarCheck(
+ IN PRTMP_ADAPTER pAd);
+
+static BOOLEAN DfsEventDataFetch(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ OUT PDFS_EVENT pDfsEvent);
+
+static VOID DfsCheckBusyIdle(
+ IN PRTMP_ADAPTER pAd);
+
+static BOOLEAN DfsChannelCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 DfsChannel);
+
+static VOID ChannelSelectOnRadarDetection(
+ IN PRTMP_ADAPTER pAd);
+
+static BOOLEAN DfsEventDrop(
+ IN PRTMP_ADAPTER pAd,
+ IN PDFS_EVENT pDfsEvent);
+
+static inline BOOLEAN NewRadarDetectionMcuStart(PRTMP_ADAPTER pAd)
+{
+ /*
+ 8051 firmware don't care parameter Token, Arg0 and Arg1
+ */
+ return AsicSendCommandToMcu(pAd, DFS_ONOFF_MCU_CMD, 0xff, 0x01, 0x01, FALSE);
+}
+
+static inline BOOLEAN NewRadarDetectionMcuStop(PRTMP_ADAPTER pAd)
+{
+ /*
+ 8051 firmware don't care parameter Token, Arg0 and Arg1
+ */
+ return AsicSendCommandToMcu(pAd, DFS_ONOFF_MCU_CMD, 0xff, 0x01, 0x00, FALSE);
+}
+
+
+#ifdef RTMP_MAC_USB
+static VOID SwCheckDfsEventWithFw(
+ IN PRTMP_ADAPTER pAd);
+#endif /*RTMP_MAC_USB */
+
+/*
+ ========================================================================
+ Routine Description:
+ Radar wave detection. The API should be invoke each second.
+
+ Arguments:
+ pAd - Adapter pointer
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID ApRadarDetectPeriodic(
+ IN PRTMP_ADAPTER pAd)
+{
+ INT i;
+
+ pAd->Dot11_H.InServiceMonitorCount++;
+
+ for (i=0; i<pAd->ChannelListNum; i++)
+ {
+ if (pAd->ChannelList[i].RemainingTimeForUse > 0)
+ {
+ pAd->ChannelList[i].RemainingTimeForUse --;
+ if ((pAd->Mlme.PeriodicRound%5) == 0)
+ {
+ DBGPRINT(RT_DEBUG_INFO, ("RadarDetectPeriodic - ch=%d, RemainingTimeForUse=%d\n",
+ pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse));
+ }
+ }
+ }
+ /*radar detect*/
+ if ((pAd->CommonCfg.Channel > 14)
+ && (pAd->CommonCfg.bIEEE80211H == 1)
+ && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
+ {
+ RadarDetectPeriodic(pAd);
+ }
+ return;
+}
+
+
+/* 0 = Switch Channel when Radar Hit (Normal mode)
+ 1 = Don't Switch Channel when Radar Hit */
+INT Set_RadarDebug_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+
+ pRadarDetect->McuRadarDebug = simple_strtol(arg, 0, 16);
+
+ if (pRadarDetect->McuRadarDebug & RADAR_DONT_SWITCH)
+ printk("Dont Switch Channel\n");
+
+ if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SILENCE)
+ printk("Silence\n");
+
+ if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_EVENT)
+ {
+ if (pRadarDetect->bDfsSwDisable == 1)
+ DBGPRINT(RT_DEBUG_ERROR, ("%s(): Warning!! DfsSwDisable is 1\n", __FUNCTION__));
+ printk("Show effective event\n");
+ }
+
+ if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SW_SILENCE)
+ printk("SW detection Silence\n");
+ return TRUE;
+}
+
+INT Set_ResetRadarHwDetect_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR channel = 0;
+#ifdef RT65xx
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ /* Reset status */
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R1, pRadarDetect->EnabledChMask);
+#else
+ /*Set BBP_R140=0x02 and Read BBP_R141 to store at channel */
+ RTMP_DFS_IO_READ8(pAd, 0x2, &channel);
+ /* reset the radar channel for new counting */
+ RTMP_DFS_IO_WRITE8(pAd, 0x2, channel);
+#endif
+ printk("==>reset the radar channel for new counting channel =0x%x\n",channel);
+ return TRUE;
+}
+
+
+INT Set_DfsLowerLimit_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+
+ pRadarDetect->DfsLowerLimit = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_DfsUpperLimit_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+
+ pRadarDetect->DfsUpperLimit = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+
+INT Set_DfsSwDisable_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+
+ pRadarDetect->bDfsSwDisable = simple_strtol(arg, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("pRadarDetect->bDfsSwDisable = %u\n", pRadarDetect->bDfsSwDisable));
+ return TRUE;
+}
+
+INT Set_DfsEnvtDropAdjTime_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+ pDfsSwParam->EvtDropAdjTime = simple_strtol(arg, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("EventDropAdjTime = %u\n", pDfsSwParam->EvtDropAdjTime));
+ return TRUE;
+}
+
+INT Set_RadarStart_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam;
+
+ if (simple_strtol(arg, 0, 10) == 0)
+ {
+ NewRadarDetectionStart(pAd);
+ }
+ else if ((simple_strtol(arg, 0, 10) >= 1) && (simple_strtol(arg, 0, 10) <= pAd->CommonCfg.RadarDetect.EnabledChMask))
+ {
+ pDfsProgramParam->ChEnable = simple_strtol(arg, 0, 10);
+ printk("Ch Enable == 0x%x\n", pDfsProgramParam->ChEnable);
+ NewRadarDetectionStart(pAd);
+ }
+
+ return TRUE;
+}
+
+INT Set_RadarStop_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ NewRadarDetectionStop(pAd);
+ return TRUE;
+}
+
+
+INT Set_RadarSetTbl1_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PUCHAR p2 = arg;
+ ULONG idx, value;
+ PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam;
+
+ while((*p2 != ':') && (*p2 != '\0'))
+ {
+ p2++;
+ }
+
+ if (*p2 == ':')
+ {
+ A2Dec(idx, arg);
+ A2Dec(value, p2+ 1);
+ if (idx == 0)
+ {
+ pDfsProgramParam->DeltaDelay = value;
+ printk("Delta_Delay = %d\n", pDfsProgramParam->DeltaDelay);
+ }
+ else
+ modify_table1(pAd, idx, value);
+ NewRadarDetectionStart(pAd);
+ }
+ else
+ printk("please enter iwpriv ra0 set RadarT1=xxx:yyy\n");
+
+ return TRUE;
+}
+
+INT Set_RadarSetTbl2_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PUCHAR p2 = arg;
+ ULONG idx, value;
+
+ while((*p2 != ':') && (*p2 != '\0'))
+ {
+ p2++;
+ }
+
+ if (*p2 == ':')
+ {
+ A2Dec(idx, arg);
+ A2Dec(value, p2+ 1);
+ modify_table2(pAd, idx, value);
+ }
+ else
+ printk("please enter iwpriv ra0 set RadarT2=xxx:yyy\n");
+
+ return TRUE;
+}
+
+
+INT Set_Fcc5Thrd_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+ pDfsSwParam->fcc_5_threshold = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_ChBusyThrd_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int i;
+ PUCHAR p1 = arg, p2;
+ ULONG value;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+
+ pRadarDetect->fdf_num = 0;
+ for (i = 0; i < MAX_FDF_NUMBER; i++)
+ {
+ p2 = p1;
+ while((*p2 != ':') && (*p2 != '\0'))
+ {
+ p2++;
+ }
+
+ if (*p2 == ':')
+ {
+ if (*p1 == '-')
+ {
+ p1++;
+ A2Dec(value, p1);
+ value *= -1;
+ }
+ else
+ A2Dec(value, p1);
+
+ pRadarDetect->ch_busy_threshold[i] = value;
+ printk("pRadarDetect->ch_busy_threshold[%d] = %d\n", i, pRadarDetect->ch_busy_threshold[i]);
+ pRadarDetect->fdf_num++;
+ p1 = p2 + 1;
+ }
+ else
+ {
+ pRadarDetect->ch_busy_threshold[i] = simple_strtol(p1, 0, 10);
+ printk("pRadarDetect->ch_busy_threshold[%d] = %d\n", i, pRadarDetect->ch_busy_threshold[i]);
+ pRadarDetect->fdf_num++;
+ break;
+ }
+ }
+ printk("pRadarDetect->fdf_num = %d\n", pRadarDetect->fdf_num);
+
+ return TRUE;
+}
+
+
+INT Set_RssiThrd_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int i;
+ PUCHAR p1 = arg, p2;
+ ULONG value;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+
+ pRadarDetect->fdf_num = 0;
+ for (i = 0; i < MAX_FDF_NUMBER; i++)
+ {
+ p2 = p1;
+ while((*p2 != ':') && (*p2 != '\0'))
+ {
+ p2++;
+ }
+
+ if (*p2 == ':')
+ {
+ if (*p1 == '-')
+ {
+ p1++;
+ A2Dec(value, p1);
+ value *= -1;
+ }
+ else
+ A2Dec(value, p1);
+
+ pRadarDetect->rssi_threshold[i] = value;
+ printk("pRadarDetect->rssi_threshold[%d] = %d\n", i, pRadarDetect->rssi_threshold[i]);
+ pRadarDetect->fdf_num++;
+ p1 = p2 + 1;
+ }
+ else
+ {
+ pRadarDetect->rssi_threshold[i] = simple_strtol(p1, 0, 10);
+ printk("pRadarDetect->rssi_threshold[%d] = %d\n", i, pRadarDetect->rssi_threshold[i]);
+ pRadarDetect->fdf_num++;
+ break;
+ }
+ }
+ printk("pRadarDetect->fdf_num = %d\n", pRadarDetect->fdf_num);
+
+ return TRUE;
+ pRadarDetect->rssi_threshold[0] = simple_strtol(arg, 0, 10);
+
+ return TRUE;
+}
+
+INT Set_PollTime_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ pRadarDetect->PollTime = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_Ch0LErr_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+ pDfsSwParam->dfs_width_ch0_err_L = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_DeclareThres_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+ pDfsSwParam->dfs_declare_thres = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_CheckLoop_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+ pDfsSwParam->dfs_check_loop = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_MaxPeriod_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+ pDfsSwParam->dfs_max_period = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_PeriodErr_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+ pDfsSwParam->dfs_period_err = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_Ch0HErr_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+ pDfsSwParam->dfs_width_ch0_err_H = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_Ch1Shift_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+ pDfsSwParam->dfs_width_diff_ch1_Shift = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_Ch2Shift_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+ pDfsSwParam->dfs_width_diff_ch2_Shift = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+
+#ifdef DFS_DEBUG
+INT Set_CEPrintDebug_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int i;
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+
+ if (simple_strtol(arg, 0, 10) == 0)
+ {
+ pDfsSwParam->DebugPortPrint = 1;
+ }
+
+ if (simple_strtol(arg, 0, 10) == 1)
+ {
+ if (pDfsSwParam->DebugPortPrint == 3)
+ {
+ for (i = 0; i < 384; i++)
+ {
+ printk("%02x ", pDfsSwParam->DebugPort[i]);
+ if (((i+1) % 18) == 0)
+ printk("\n");
+ }
+ pDfsSwParam->DebugPortPrint = 0;
+ }
+ }
+ return TRUE;
+}
+#endif /* DFS_DEBUG */
+
+
+INT Set_RadarSim_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+int i=0, id=0;
+int dfs_data[] = { 208, 142172,
+ 160, 260514,
+ 208, 363873,
+ 160, 482216,
+ 208, 585575,
+ 164, 703918,
+ 208, 807277,
+ 160, 925620,
+ 208, 1028979,
+ 164, 1147321};
+
+ pDfsSwParam->dfs_w_counter++;
+ for (i = 0; i < 10; i++)
+ {
+ pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].counter = pDfsSwParam->dfs_w_counter;
+ pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].timestamp = dfs_data[2*i+1];
+ pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].width = dfs_data[2*i];
+ pDfsSwParam->dfs_w_last_idx[id] = pDfsSwParam->dfs_w_idx[id];
+ pDfsSwParam->dfs_w_idx[id]++;
+ if (pDfsSwParam->dfs_w_idx[id] >= NEW_DFS_DBG_PORT_ENT_NUM)
+ pDfsSwParam->dfs_w_idx[id] = 0;
+ }
+ pDfsSwParam->hw_idx[0] = pDfsSwParam->dfs_w_idx[0];
+ SWRadarCheck(pAd, 0);
+ return TRUE;
+}
+
+INT Set_PrintBusyIdle_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ pRadarDetect->print_ch_busy_sta = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_BusyIdleRatio_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ pRadarDetect->ch_busy_idle_ratio = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_DfsRssiHigh_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ pRadarDetect->DfsRssiHigh = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+
+INT Set_DfsRssiLow_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ pRadarDetect->DfsRssiLow = simple_strtol(arg, 0, 10);
+ return TRUE;
+}
+INT Set_EventExpire_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam;
+ UINT8 dfs_channel, bbp_val;
+ UINT32 EventExpiration = 0;
+ STRING StrBuf[64];
+ PSTRING SubStr = NULL;
+
+ strncpy(StrBuf, arg, 64);
+ if ((SubStr = strchr(StrBuf, '_')) != NULL)
+ {
+ *SubStr = '\0';
+ SubStr++;
+ EventExpiration = (UINT32) simple_strtol(SubStr, 0, 16);
+ dfs_channel = (UINT8) simple_strtol(StrBuf, 0, 16);
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("%s(): dfs_channel = %u, EventExpiration = 0x%08x\n",
+ __FUNCTION__, dfs_channel, EventExpiration));
+
+ pDfsProgramParam->RadarEventExpire[dfs_channel] = EventExpiration;
+
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R0, dfs_channel); /* disable DFS and select channel */
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R17, EventExpiration); /* set value */
+ /* Enable detection*/
+ bbp_val = (pDfsProgramParam->ChEnable << 16);
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R0, bbp_val);
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("%s(): Input format Error. (should be <Channel>_<value>)\n", __FUNCTION__));
+ return 0;
+ }
+
+ return TRUE;
+}
+INT Set_CEPrint_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+ int i, j, id = simple_strtol(arg, 0, 10);
+ int n = pDfsSwParam->dfs_w_last_idx[id];
+
+ if ((id >= 0) && (id <= 3))
+ {
+ printk("Last Idx = %d\n", n);
+ for (i = 0; i < NEW_DFS_DBG_PORT_ENT_NUM; i++)
+ {
+ printk("Cnt=%u, w= %u Time=%u\n", (unsigned int)(pDfsSwParam->DFS_W[id][i].counter),
+ pDfsSwParam->DFS_W[id][i].width,
+ (unsigned int)pDfsSwParam->DFS_W[id][i].timestamp);
+ if (pDfsSwParam->DFS_W[id][i].counter == 0)
+ break;
+ }
+ }
+
+ if ((id >= 10) && (id < 13))
+ {
+ id -= 10;
+ for (i = 0; i < NEW_DFS_MPERIOD_ENT_NUM; i++)
+ {
+ printk("T=%u, w1= %u(%u), w2= %u(%u)\n", (unsigned int)(pDfsSwParam->DFS_T[id][i].period),
+ pDfsSwParam->DFS_T[id][i].width, pDfsSwParam->DFS_T[id][i].idx,
+ pDfsSwParam->DFS_T[id][i].width2, pDfsSwParam->DFS_T[id][i].idx2);
+ if (pDfsSwParam->DFS_T[id][i].period == 0)
+ break;
+ }
+
+ }
+ if (id == 77)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < NEW_DFS_DBG_PORT_ENT_NUM; j++)
+ {
+ pDfsSwParam->DFS_W[i][j].counter = 0;
+ pDfsSwParam->DFS_W[i][j].width = 0;
+ pDfsSwParam->DFS_W[i][j].timestamp = 0;
+ }
+ for (j = 0; j < NEW_DFS_MPERIOD_ENT_NUM; j++)
+ {
+ pDfsSwParam->DFS_T[i][j].period = 0;
+ pDfsSwParam->DFS_T[i][j].width = 0;
+ pDfsSwParam->DFS_T[i][j].width2 = 0;
+ pDfsSwParam->DFS_T[i][j].idx = 0;
+ pDfsSwParam->DFS_T[i][j].idx2 = 0;
+ }
+ }
+ }
+#ifdef DFS_DEBUG
+ if (id > 20)
+ {
+ pDfsSwParam->BBP127Repeat = id - 20;
+ }
+
+ if (id == 5)
+ {
+
+ for (i = 0; i < NEW_DFS_DBG_PORT_ENT_NUM; i++)
+ {
+ printk("Cnt=%u, w= %u Time=%lu, start_idx = %u end_idx = %u\n", (unsigned int)(pDfsSwParam->CE_DebugCh0[i].counter),
+ (unsigned int)pDfsSwParam->CE_DebugCh0[i].width, pDfsSwParam->CE_DebugCh0[i].timestamp,
+ pDfsSwParam->CE_DebugCh0[i].start_idx, pDfsSwParam->CE_DebugCh0[i].end_idx);
+ }
+
+ for (i = 0; i < NEW_DFS_MPERIOD_ENT_NUM; i++)
+ {
+ printk("T=%lu, w1= %u(%u), w2= %u(%u)\n", (pDfsSwParam->CE_TCh0[i].period),
+ pDfsSwParam->CE_TCh0[i].width, pDfsSwParam->CE_TCh0[i].idx,
+ pDfsSwParam->CE_TCh0[i].width2, pDfsSwParam->CE_TCh0[i].idx2);
+ }
+
+ }
+#endif /* DFS_DEBUG */
+
+ return TRUE;
+}
+
+
+INT Set_RfReg_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+
+ printk("1 %x\n", pAd->LatchRfRegs.R1);
+ printk("2 %x\n", pAd->LatchRfRegs.R2);
+ printk("3 %x\n", pAd->LatchRfRegs.R3);
+ printk("4 %x\n", pAd->LatchRfRegs.R4);
+ return TRUE;
+}
+
+INT Show_BlockCh_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int i;
+
+ for (i=0; i<pAd->ChannelListNum; i++)
+ {
+ if (pAd->ChannelList[i].RemainingTimeForUse != 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Ch%d: RemainingTimeForUse:%d sec;\n",
+ pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse));
+ }
+ }
+ return TRUE;
+}
+
+
+VOID DFSInit(PRTMP_ADAPTER pAd)
+{
+ INT i;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam;
+
+ pRadarDetect->ch_busy_countdown = -1;
+ pRadarDetect->EnabledChMask = ((1 << pAd->chipCap.DfsEngineNum) -1);
+ pRadarDetect->PollTime = 3;
+ pRadarDetect->DfsRssiHigh = -30;
+ pRadarDetect->DfsRssiLow = -90;
+ pRadarDetect->DFSWatchDogIsRunning=FALSE;
+ pRadarDetect->use_tasklet = 1;
+ pRadarDetect->McuRadarDebug = RADAR_DONT_SWITCH; //snowpin test 0;
+ pRadarDetect->radarDeclared = 0;
+ pRadarDetect->dfs_func = HARDWARE_DFS_V2;
+ pDfsProgramParam->DeltaDelay = 0x3;
+ pDfsProgramParam->ChEnable = pRadarDetect->EnabledChMask;
+ for (i=0; i < pAd->chipCap.DfsEngineNum; i++)
+ {
+ if ((i == 3) &&
+ (pAd->CommonCfg.RDDurRegion == FCC || pAd->CommonCfg.RDDurRegion == JAP))
+ pDfsProgramParam->RadarEventExpire[i] = 0x10000000; /* for Chirp Radar */
+ else
+ pDfsProgramParam->RadarEventExpire[i] = 0x1000000;
+ }
+ /*pDfsProgramParam->RadarEventExpire[0] = 0x1000000;*/
+ /*pDfsProgramParam->RadarEventExpire[3] = 0x99999999;*/
+ pDfsProgramParam->Symmetric_Round = 1;
+ pDfsProgramParam->VGA_Mask = 45;
+ pDfsProgramParam->Packet_End_Mask = 45;
+ pDfsProgramParam->Rx_PE_Mask = 45;
+
+ /*pAd->CommonCfg.ce_sw_check = CE_SW_CHECK;*/
+ /*pDfsSwParam->ce_sw_id_check = 0;*/
+ /*pDfsSwParam->ce_sw_t_diff = 14;*/
+
+ /* from dfs_mcu.c, one time init */
+ dfs_sw_init(pAd);
+
+}
+
+void NewRadarDetectionStart(PRTMP_ADAPTER pAd)
+{
+ pNewDFSTable pDFS2Table;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ /*PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam;*/
+
+ pRadarDetect->bDfsInit = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--->NewRadarDetectionStart()\n"));
+
+ DFSInit(pAd);
+
+#ifdef RTMP_MAC_USB
+ INIT_DFS_EVENT_BUFF_SHARED_MEMORY(pAd, BBPR127TABLE_OFFSET, 8, 0xfe);
+#endif /* RTMP_MAC_USB */
+
+ RTMP_CHIP_RADAR_GLRT_COMPENSATE(pAd);
+
+ if ((pAd->CommonCfg.RDDurRegion == CE) && RESTRICTION_BAND_1(pAd))
+ pAd->Dot11_H.ChMovingTime = 605;
+ else
+ pAd->Dot11_H.ChMovingTime = 65;
+
+ if (pAd->CommonCfg.RDDurRegion == FCC)
+ {
+ if (pRadarDetect->ch_busy_idle_ratio == 0)
+ pRadarDetect->ch_busy_idle_ratio = 2;
+
+ pDFS2Table = &NewDFSTable1[0];
+ DBGPRINT(RT_DEBUG_TRACE,("DFS start, use FCC table\n"));
+ }
+ else if (pAd->CommonCfg.RDDurRegion == CE)
+ {
+ if (pRadarDetect->ch_busy_idle_ratio == 0)
+ pRadarDetect->ch_busy_idle_ratio = 3;
+
+ pDFS2Table = &NewDFSTable1[1];
+ DBGPRINT(RT_DEBUG_TRACE,("DFS start, use CE table\n"));
+ }
+ else /* JAP*/
+ {
+
+ if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64))
+ {
+ pDFS2Table = &NewDFSTable1[3];
+
+ if (pRadarDetect->ch_busy_idle_ratio == 0)
+ pRadarDetect->ch_busy_idle_ratio = 3;
+ }
+ else
+ {
+ pDFS2Table = &NewDFSTable1[2];
+ /*pDfsProgramParam->Symmetric_Round = 1;*/
+
+ if (pRadarDetect->ch_busy_idle_ratio == 0)
+ pRadarDetect->ch_busy_idle_ratio = 2;
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("DFS start, use JAP table\n"));
+ }
+
+ NewRadarDetectionProgram(pAd, pDFS2Table);
+
+ /*the usage of dfs_sw_init*/
+ /*dfs_sw_init(pAd);*/
+
+#ifdef RTMP_MAC_USB
+ if (NewRadarDetectionMcuStart(pAd) == FALSE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("NewRadarDetectionMcuStart failed.\n"));
+ }
+#endif /* RTMP_MAC_USB */
+ pRadarDetect->bDfsInit = TRUE;
+ DBGPRINT(RT_DEBUG_TRACE,("Poll Time=%d\n", pRadarDetect->PollTime));
+}
+
+VOID NewRadarDetectionStop(
+ IN PRTMP_ADAPTER pAd)
+{
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("NewRadarDetectionStop\n"));
+
+ /* set init bit = false to prevent dfs rotines */
+ pRadarDetect->bDfsInit = FALSE;
+ pRadarDetect->radarDeclared = 0;
+
+#ifdef RT65xx
+ /* Disable detection*/
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R0, 0);
+
+ /* Clear status */
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R1, pRadarDetect->EnabledChMask);
+#else
+ /* Disable detection*/
+ RTMP_DFS_IO_WRITE8(pAd, 0x1, 0);
+
+ /* Clear Status */
+ RTMP_DFS_IO_WRITE8(pAd, 0x2, pRadarDetect->EnabledChMask);
+#endif
+
+#ifdef RTMP_MAC_USB
+ if (NewRadarDetectionMcuStop(pAd) == FALSE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("NewRadarDetectionMcuStop failed.\n"));
+ }
+#endif /* RTMP_MAC_USB */
+
+}
+
+
+/* the debug port have timestamp 22 digit, the max number is 0x3fffff, each unit is 25ns for 40Mhz mode and 50ns for 20Mhz mode*/
+/* so a round of timestamp is about 25 * 0x3fffff / 1000 = 104857us (about 100ms) or*/
+/* 50 * 0x3fffff / 1000 = 209715us (about 200ms) in 20Mhz mode*/
+/* 3ms = 3000,000 ns / 25ns = 120000 -- a unit */
+/* 0x3fffff/120000 = 34.9 ~= 35*/
+/* CE Staggered radar check*/
+/* At beginning, the goal is to detect staggered radar, now, we also detect regular radar with this function.*/
+
+
+int SWRadarCheck(
+ IN PRTMP_ADAPTER pAd, USHORT id)
+{
+ int i, j, start_idx, end_idx;
+ pNewDFSDebugPort pCurrent, p1, pEnd;
+ ULONG period;
+ int radar_detected = 0;
+ USHORT widthsum;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam;
+ /*ENTRY_PLUS could be replace by (pDfsSwParam->sw_idx[id]+1)%128*/
+ USHORT Total, SwIdxPlus = ENTRY_PLUS(pDfsSwParam->sw_idx[id], 1, NEW_DFS_DBG_PORT_ENT_NUM);
+ UCHAR CounterToCheck;
+
+ if (!DFS_CHECK_FLAGS(pAd, pRadarDetect) ||
+ (SwIdxPlus == pDfsSwParam->hw_idx[id])) /* no entry to process*/
+ return 0;
+
+ /* process how many entries?? total NEW_DFS_DBG_PORT_ENT_NUM*/
+ if (pDfsSwParam->hw_idx[id] > SwIdxPlus)
+ Total = pDfsSwParam->hw_idx[id] - SwIdxPlus;
+ else
+ Total = pDfsSwParam->hw_idx[id] + NEW_DFS_DBG_PORT_ENT_NUM - SwIdxPlus;
+
+ if (Total > NEW_DFS_DBG_PORT_ENT_NUM)
+ pDfsSwParam->pr_idx[id] = ENTRY_PLUS(pDfsSwParam->sw_idx[id], MAX_PROCESS_ENTRY, NEW_DFS_DBG_PORT_ENT_NUM);
+ else
+ pDfsSwParam->pr_idx[id] = ENTRY_PLUS(pDfsSwParam->sw_idx[id], Total, NEW_DFS_DBG_PORT_ENT_NUM);
+
+
+ start_idx = ENTRY_PLUS(pDfsSwParam->pr_idx[id], 1, NEW_DFS_DBG_PORT_ENT_NUM);
+ end_idx = pDfsSwParam->pr_idx[id];
+
+ pEnd = &pDfsSwParam->DFS_W[id][end_idx];
+ /*printk("start_idx = %d, end_idx=%d, counter=%d\n", start_idx, end_idx, pEnd->counter);*/
+
+ /*if (pDfsSwParam->dfs_w_counter != pEnd->counter)*/
+ /* return 0;*/
+
+ if (start_idx > end_idx)
+ end_idx += NEW_DFS_DBG_PORT_ENT_NUM;
+
+
+ pDfsSwParam->sw_idx[id] = pDfsSwParam->pr_idx[id];
+
+ /* FCC && Japan*/
+
+ if (pAd->CommonCfg.RDDurRegion != CE)
+ {
+ ULONG minPeriod = (3000 << 1);
+ /* Calculate how many counters to check*/
+ /* if pRadarDetect->PollTime is 1ms, a round of timestamp is 107 for 20Mhz, 53 for 40Mhz*/
+ /* if pRadarDetect->PollTime is 2ms, a round of timestamp is 71 for 20Mhz, 35 for 40Mhz*/
+ /* if pRadarDetect->PollTime is 3ms, a round of timestamp is 53 for 20Mhz, 27 for 40Mhz*/
+ /* if pRadarDetect->PollTime is 4ms, a round of timestamp is 43 for 20Mhz, 21 for 40Mhz*/
+ /* the max period to check for 40Mhz for FCC is 28650 * 2*/
+ /* the max period to check for 40Mhz for Japan is 80000 * 2*/
+ /* 0x40000 = 4194304 / 57129 = 73.xxx*/
+ /* 0x40000 = 4194304 / 160000 = 26.2144*/
+ /* 53/73 < 1 (1+1)*/
+ /* 53/26.2144 = 2.02... (2+1)*/
+ /* 27/26.2144 = 1.02... (1+1)*/
+ /* 20M should use the same value as 40Mhz mode*/
+
+
+ if (pRadarDetect->MCURadarRegion == NEW_DFS_JAP_W53)
+ {
+ minPeriod = 28500 << 1;
+ }
+
+
+ if (pAd->CommonCfg.RDDurRegion == FCC)
+ {
+ CounterToCheck = 1+1;
+ }
+ else /* if (pAd->CommonCfg.RDDurRegion == JAP)*/
+ {
+ if (pRadarDetect->PollTime <= 2)
+ CounterToCheck = 2+1;
+ else
+ CounterToCheck = 1+1;
+ }
+
+
+
+ /* First Loop for FCC/JAP*/
+ for (i = end_idx; i > start_idx; i--)
+ {
+ pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK];
+
+ /* we only handle entries has same counter with the last one*/
+ if (pCurrent->counter != pEnd->counter)
+ break;
+
+ pCurrent->start_idx = 0xffff;
+
+ /* calculate if any two pulse become a valid period, add it in period table,*/
+ for (j = i - 1; j > start_idx; j--)
+ {
+ p1 = &pDfsSwParam->DFS_W[id][j & NEW_DFS_DBG_PORT_MASK];
+
+ /* check period, must within max period*/
+ if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)
+ {
+ if (p1->counter + CounterToCheck < pCurrent->counter)
+ break;
+
+ widthsum = p1->width + pCurrent->width;
+ if (id == 0)
+ {
+ if (widthsum < 600)
+ pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L;
+ else
+ pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift;
+ }
+ else if (id == 1)
+ pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch1_Shift;
+ else if (id == 2)
+ pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift;
+
+ if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) ||
+ (PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) )
+ {
+ if (p1->timestamp >= pCurrent->timestamp)
+ period = 0x400000 + pCurrent->timestamp - p1->timestamp;
+ else
+ period = pCurrent->timestamp - p1->timestamp;
+
+ if ((period >= (minPeriod - 2)) && (period <= pDfsSwParam->dfs_max_period))
+ {
+
+ /* add in period table*/
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK);
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width;
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK);
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width;
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period;
+
+
+ if (pCurrent->start_idx == 0xffff)
+ pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id];
+ pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id];
+
+ pDfsSwParam->dfs_t_idx[id]++;
+ if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM)
+ pDfsSwParam->dfs_t_idx[id] = 0;
+ }
+ else if (period > pDfsSwParam->dfs_max_period)
+ break;
+ }
+
+ }
+ else
+ {
+ if (p1->counter + CounterToCheck < pCurrent->counter)
+ break;
+
+ widthsum = p1->width + pCurrent->width;
+ if (id == 0)
+ {
+ if (widthsum < 600)
+ pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L;
+ else
+ pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift;
+ }
+ else if (id == 1)
+ pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch1_Shift;
+ else if (id == 2)
+ pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift;
+
+
+ if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) ||
+ (PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) )
+
+ {
+ if (p1->timestamp >= pCurrent->timestamp)
+ period = 0x400000 + pCurrent->timestamp - p1->timestamp;
+ else
+ period = pCurrent->timestamp - p1->timestamp;
+
+ if ((period >= ((minPeriod >> 1) - 2)) && (period <= (pDfsSwParam->dfs_max_period >> 1)))
+ {
+ /* add in period table*/
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK);
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width;
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK);
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width;
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period;
+
+ if (pCurrent->start_idx == 0xffff)
+ pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id];
+ pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id];
+
+ pDfsSwParam->dfs_t_idx[id]++;
+ if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM)
+ pDfsSwParam->dfs_t_idx[id] = 0;
+ }
+ else if (period > (pDfsSwParam->dfs_max_period >> 1))
+ break;
+ }
+ }
+
+ } /* for (j = i - 1; j > start_idx; j--)*/
+
+ } /* for (i = end_idx; i > start_idx; i--)*/
+
+
+ /* Second Loop for FCC/JAP*/
+ for (i = end_idx; i > start_idx; i--)
+ {
+
+ pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK];
+
+ /* we only handle entries has same counter with the last one*/
+ if (pCurrent->counter != pEnd->counter)
+ break;
+ if (pCurrent->start_idx != 0xffff)
+ {
+ /*pNewDFSDebugPort p2, p3, p4, p5, p6;*/
+ pNewDFSDebugPort p2, p3;
+ pNewDFSMPeriod pCE_T;
+ ULONG idx[10], T[10];
+
+ for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++)
+ {
+
+ pCE_T = &pDfsSwParam->DFS_T[id][idx[0]];
+
+ p2 = &pDfsSwParam->DFS_W[id][pCE_T->idx2];
+
+ if (p2->start_idx == 0xffff)
+ continue;
+
+ T[0] = pCE_T->period;
+
+
+ for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++)
+ {
+
+ pCE_T = &pDfsSwParam->DFS_T[id][idx[1]];
+
+ p3 = &pDfsSwParam->DFS_W[id][pCE_T->idx2];
+
+ if (idx[0] == idx[1])
+ continue;
+
+ if (p3->start_idx == 0xffff)
+ continue;
+
+
+
+ T[1] = pCE_T->period;
+
+
+ if ( PERIOD_MATCH(T[0], T[1], pDfsSwParam->dfs_period_err))
+ {
+ if (id <= 2) /* && (id >= 0)*/
+ {
+
+ /*if (((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (T[1] > minPeriod)) ||*/
+ /* ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_20) && (T[1] > (minPeriod >> 1))) )*/
+ {
+ unsigned int loop, PeriodMatched = 0, idx1;
+ for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++)
+ {
+ idx1 = (idx[1] >= loop)? (idx[1] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[1] - loop);
+ if (PERIOD_MATCH(pDfsSwParam->DFS_T[id][idx1].period, T[1], pDfsSwParam->dfs_period_err))
+ {
+#ifdef DFS_DEBUG
+ if (PeriodMatched < 5)
+ {
+ pDfsSwParam->CounterStored[PeriodMatched] = pDfsSwParam->DFS_W[id][pDfsSwParam->DFS_T[id][idx1].idx].counter;
+ pDfsSwParam->CounterStored2[PeriodMatched] = loop;
+ pDfsSwParam->CounterStored3 = idx[1];
+ }
+#endif
+ /*printk("%d %d\n", loop, pDfsSwParam->DFS_T[id][idx[1]-loop].period);*/
+ PeriodMatched++;
+ }
+
+ }
+
+
+ if (PeriodMatched > pDfsSwParam->dfs_declare_thres)
+ {
+#ifdef DFS_DEBUG
+ if (PeriodMatched == 3)
+ {
+ pDfsSwParam->T_Matched_3++;
+ /*printk("counter=%d %d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1], pDfsSwParam->CounterStored[2]);*/
+ /*printk("idx[1]=%d, loop =%d %d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1], pDfsSwParam->CounterStored2[2]);*/
+ }
+ else if (PeriodMatched == 4)
+ {
+ pDfsSwParam->T_Matched_4++;
+ /*printk("counter=%d %d %d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1], pDfsSwParam->CounterStored[2], pDfsSwParam->CounterStored[3]);*/
+ /*printk("idx[1]=%d, loop =%d %d %d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1], pDfsSwParam->CounterStored2[2], pDfsSwParam->CounterStored2[3]);*/
+ }
+ else
+ {
+ pDfsSwParam->T_Matched_5++;
+ /*printk("counter=%d %d %d %d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1], pDfsSwParam->CounterStored[2], pDfsSwParam->CounterStored[3], pDfsSwParam->CounterStored[4]);*/
+ /*printk("idx[1]=%d, loop =%d %d %d %d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1], pDfsSwParam->CounterStored2[2], pDfsSwParam->CounterStored2[3], pDfsSwParam->CounterStored2[4]);*/
+ }
+
+ pDfsSwParam->DebugPortPrint = 1;
+
+#endif
+
+ {
+ pNewDFSValidRadar pDFSValidRadar;
+ ULONG T1 = (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)? (T[1]>>1) : T[1];
+
+ pDFSValidRadar = &NewDFSValidTable[0];
+
+
+ while (pDFSValidRadar->type != NEW_DFS_END)
+ {
+ if ((pDFSValidRadar->type & pRadarDetect->MCURadarRegion) == 0)
+ {
+ pDFSValidRadar++;
+ continue;
+ }
+
+ if (pDFSValidRadar->TLow)
+ {
+ if ( (T1 > (pDFSValidRadar->TLow - pDFSValidRadar->TMargin)) &&
+ (T1 < (pDFSValidRadar->THigh + pDFSValidRadar->TMargin)) )
+ {
+ radar_detected = 1;
+ }
+ }
+ else
+ {
+ if ( (T1 > (pDFSValidRadar->T - pDFSValidRadar->TMargin)) &&
+ (T1 < (pDFSValidRadar->T + pDFSValidRadar->TMargin)) )
+ {
+ radar_detected = 1;
+ break;
+ }
+ }
+
+ pDFSValidRadar++;
+ }
+ if (radar_detected == 1)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("W=%d, T=%d (%d), period matched=%d\n", (unsigned int)pCE_T->width, (unsigned int)T1, (unsigned int)id, PeriodMatched));
+ printk("SWRadarCheck: Radar Detected\n");
+ return radar_detected;
+ }
+ else if (pRadarDetect->MCURadarRegion != NEW_DFS_JAP_W53)
+ DBGPRINT(RT_DEBUG_TRACE, ("W=%d, T=%d (%d), period matched=%d\n", (unsigned int)pCE_T->width, (unsigned int)T1, (unsigned int)id, PeriodMatched));
+
+ }
+
+
+ }
+#ifdef DFS_DEBUG
+ else if (PeriodMatched == 2)
+ {
+ pDfsSwParam->T_Matched_2++;
+ }
+#endif
+
+
+ }
+
+ } /* if (id <= 2) && (id >= 0)*/
+
+ }
+
+ } /* for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++)*/
+
+
+ /* increase FCC-1 detection*/
+ if (id <= 2)
+ {
+ if (IS_FCC_RADAR_1((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), T[0]))
+ {
+ int loop, idx1, PeriodMatched_fcc1 = 0;
+ for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++)
+ {
+ idx1 = (idx[0] >= loop)? (idx[0] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[0] - loop);
+ if ( IS_FCC_RADAR_1((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), pDfsSwParam->DFS_T[id][idx1].period) )
+ {
+ /*printk("%d %d %d\n", PeriodMatched_fcc1, pDfsSwParam->DFS_T[id][idx1].period, loop);*/
+ PeriodMatched_fcc1++;
+ }
+ }
+
+ if (PeriodMatched_fcc1 > 3)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeriodMatched_fcc1 = %d (%d)\n", PeriodMatched_fcc1, id));
+ radar_detected = 1;
+ return radar_detected;
+ }
+
+ }
+
+ }
+
+
+ /* increase W56-3 detection*/
+ if ((pRadarDetect->MCURadarRegion == NEW_DFS_JAP) && (id <= 2))
+ {
+ if (IS_W56_RADAR_3((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), T[0]))
+ {
+ int loop, idx1, PeriodMatched_w56_3 = 0;
+ for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++)
+ {
+ idx1 = (idx[0] >= loop)? (idx[0] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[0] - loop);
+ if ( IS_W56_RADAR_3((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), pDfsSwParam->DFS_T[id][idx1].period) )
+ {
+ /*printk("%d %d %d\n", PeriodMatched_w56_3, pDfsSwParam->DFS_T[id][idx1].period, loop);*/
+ PeriodMatched_w56_3++;
+ }
+ }
+
+ if (PeriodMatched_w56_3 > 3)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeriodMatched_w56_3 = %d (%d)\n", PeriodMatched_w56_3, id));
+ radar_detected = 1;
+ return radar_detected;
+ }
+
+ }
+
+ }
+
+
+ if ((pRadarDetect->MCURadarRegion == NEW_DFS_JAP_W53) && (id <= 2) && IS_W53_RADAR_2((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), T[0]))
+ {
+ int loop, idx1, PeriodMatched_W56_2 = 0;
+
+ for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++)
+ {
+ idx1 = (idx[0] >= loop)? (idx[0] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[0] - loop);
+ if ( IS_W53_RADAR_2((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), pDfsSwParam->DFS_T[id][idx1].period) )
+ {
+ /*printk("%d %d %d\n", PeriodMatched_W56_2, pDfsSwParam->DFS_T[id][idx1].period, loop);*/
+ PeriodMatched_W56_2++;
+ }
+ }
+
+ if (PeriodMatched_W56_2 >= 3)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeriodMatched_W56_2 = %d(%d)\n", PeriodMatched_W56_2, id));
+ radar_detected = 1;
+ return radar_detected;
+ }
+ }
+
+
+
+ } /* for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++)*/
+ } /* if (pCurrent->start_idx != 0xffff)*/
+ } /* for (i = end_idx; i > start_idx; i--)*/
+
+ return radar_detected;
+ }
+
+ /* CE have staggered radar */
+
+ /* Calculate how many counters to check*/
+ /* if pRadarDetect->PollTime is 1ms, a round of timestamp is 107 for 20Mhz, 53 for 40Mhz*/
+ /* if pRadarDetect->PollTime is 2ms, a round of timestamp is 71 for 20Mhz, 35 for 40Mhz*/
+ /* if pRadarDetect->PollTime is 3ms, a round of timestamp is 53 for 20Mhz, 27 for 40Mhz*/
+ /* if pRadarDetect->PollTime is 4ms, a round of timestamp is 43 for 20Mhz, 21 for 40Mhz*/
+ /* if pRadarDetect->PollTime is 8ms, a round of timestamp is ?? for 20Mhz, 12 for 40Mhz*/
+ /* the max period to check for 40Mhz is 133333 + 125000 + 117647 = 375980*/
+ /* 0x40000 = 4194304 / 375980 = 11.1556*/
+ /* 53/11.1556 = 4.75...*/
+ /* 35/11.1556 = 3.1374, (4+1) is safe, (3+1) to save CPU power, but may lost some data*/
+ /* 27/11.1556 = 2.42, (3+1) is OK*/
+ /* 21/11.1556 = 1.88, (2+1) is OK*/
+ /* 20M should use the same value as 40Mhz mode*/
+ if (pRadarDetect->PollTime == 1)
+ CounterToCheck = 5+1;
+ else if (pRadarDetect->PollTime == 2)
+ CounterToCheck = 4+1;
+ else if (pRadarDetect->PollTime == 3)
+ CounterToCheck = 3+1;
+ else if (pRadarDetect->PollTime <= 8)
+ CounterToCheck = 2+1;
+ else
+ CounterToCheck = 1+1;
+
+ /* First Loop for CE*/
+ for (i = end_idx; i > start_idx; i--)
+ {
+ pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK];
+
+ /* we only handle entries has same counter with the last one*/
+ if (pCurrent->counter != pEnd->counter)
+ break;
+
+ pCurrent->start_idx = 0xffff;
+
+ /* calculate if any two pulse become a valid period, add it in period table,*/
+ for (j = i - 1; j > start_idx; j--)
+ {
+ p1 = &pDfsSwParam->DFS_W[id][j & NEW_DFS_DBG_PORT_MASK];
+
+
+ /* check period, must within 16666 ~ 66666*/
+ if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)
+ {
+ if (p1->counter + CounterToCheck < pCurrent->counter)
+ break;
+
+ widthsum = p1->width + pCurrent->width;
+ if (id == 0)
+ {
+ if (((p1->width > 310) && (pCurrent->width < 300)) || ((pCurrent->width > 310) && ((p1->width < 300))) )
+ continue;
+ if (widthsum < 620)
+ pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_H;
+ else
+ pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L;
+
+ }
+ else if (id == 1)
+ pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch1_Shift;
+ else if (id == 2)
+ pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift;
+
+ if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) ||
+ (PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) )
+ {
+ if (p1->timestamp >= pCurrent->timestamp)
+ period = 0x400000 + pCurrent->timestamp - p1->timestamp;
+ else
+ period = pCurrent->timestamp - p1->timestamp;
+
+ /*if ((period >= (33333 - 20)) && (period <= (133333 + 20)))*/
+ if ((period >= (33333 - 20)) && (period <= pDfsSwParam->dfs_max_period))
+ //if ((period >= (10000 - 2)) && (period <= pDfsSwParam->dfs_max_period))
+ {
+
+ /* add in period table*/
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK);
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width;
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK);
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width;
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period;
+
+
+ if (pCurrent->start_idx == 0xffff)
+ pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id];
+ pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id];
+
+ pDfsSwParam->dfs_t_idx[id]++;
+ if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM)
+ pDfsSwParam->dfs_t_idx[id] = 0;
+ }
+ else if (period > pDfsSwParam->dfs_max_period) /* to allow miss a pulse*/
+ break;
+ }
+
+ }
+ else
+ {
+ if (p1->counter + CounterToCheck < pCurrent->counter)
+ break;
+
+ widthsum = p1->width + pCurrent->width;
+ if (id == 0)
+ {
+ if (((p1->width > 300) && (pCurrent->width < 300)) || ((pCurrent->width > 300) && ((p1->width < 300))) )
+ continue;
+ if (widthsum < 620)
+ pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_H;
+ else
+ pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L;
+ }
+ else if (id == 1)
+ {
+ pDfsSwParam->dfs_width_diff = widthsum >> 3; /* for 20M verified */
+ //printk("dfs_width_diff = %u\n",pDfsSwParam->dfs_width_diff);
+ }
+ else if (id == 2)
+ pDfsSwParam->dfs_width_diff = widthsum >> 6;
+
+ if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) ||
+ (PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) )
+
+ {
+ if (p1->timestamp >= pCurrent->timestamp)
+ period = 0x400000 + pCurrent->timestamp - p1->timestamp;
+ else
+ period = pCurrent->timestamp - p1->timestamp;
+
+ //if ((period >= (5000 - 2)) && (period <= (pDfsSwParam->dfs_max_period >> 1)))
+ if ((period >= (16666 - 20)) && (period <= (pDfsSwParam->dfs_max_period >> 1)))//neil modify for ce 5-1
+ {
+ /* add in period table*/
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK);
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width;
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK);
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width;
+ pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period;
+
+ if (pCurrent->start_idx == 0xffff)
+ pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id];
+ pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id];
+
+ pDfsSwParam->dfs_t_idx[id]++;
+ if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM)
+ pDfsSwParam->dfs_t_idx[id] = 0;
+ }
+ else if (period > (pDfsSwParam->dfs_max_period >> 1))
+ break;
+ }
+ }
+ } /* for (j = i - 1; j > start_idx; j--)*/
+ }
+
+ /* Second Loop for CE*/
+ for (i = end_idx; i > start_idx; i--)
+ {
+ pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK];
+
+ /* we only handle entries has same counter with the last one*/
+ if (pCurrent->counter != pEnd->counter)
+ break;
+
+ /* Check Staggered radar*/
+ if (pCurrent->start_idx != 0xffff)
+ {
+ pNewDFSDebugPort p2, p3;
+ pNewDFSMPeriod pCE_T;
+ ULONG idx[10], T[10];
+
+ /*printk("pCurrent=%d, idx=%d~%d\n", pCurrent->timestamp, pCurrent->start_idx, pCurrent->end_idx);*/
+
+ for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++)
+ {
+ pCE_T = &pDfsSwParam->DFS_T[id][idx[0]];
+
+ p2 = &pDfsSwParam->DFS_W[id][pCE_T->idx2];
+
+ /*printk("idx[0]= %d, idx=%d p2=%d, idx=%d~%d\n", idx[0], pCE_T->idx2, p2->timestamp, p2->start_idx, p2->end_idx);*/
+
+ if (p2->start_idx == 0xffff)
+ continue;
+
+ T[0] = pCE_T->period;
+
+
+ for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++)
+ {
+
+ pCE_T = &pDfsSwParam->DFS_T[id][idx[1]];
+
+ p3 = &pDfsSwParam->DFS_W[id][pCE_T->idx2];
+
+ /*printk("p3=%d, idx=%d~%d\n", p3->timestamp, p3->start_idx, p3->end_idx);*/
+
+ if (idx[0] == idx[1])
+ continue;
+
+ if (p3->start_idx == 0xffff)
+ continue;
+
+
+
+ T[1] = pCE_T->period;
+
+
+ if (PERIOD_MATCH(T[0], T[1], pDfsSwParam->dfs_period_err))
+ {
+ if (id <= 2) /* && (id >= 0)*/
+ {
+
+
+ if (((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (T[1] > 66666)) ||
+ ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_20) && (T[1] > 33333)) )
+ {
+ unsigned int loop, PeriodMatched = 0, idx1;
+
+ for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++)
+ {
+ idx1 = (idx[1] >= loop)? (idx[1] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[1] - loop);
+ if (PERIOD_MATCH(pDfsSwParam->DFS_T[id][idx1].period, T[1], pDfsSwParam->dfs_period_err))
+ {
+#ifdef DFS_DEBUG
+ if (PeriodMatched < 5)
+ {
+ pDfsSwParam->CounterStored[PeriodMatched] = pDfsSwParam->DFS_W[id][pDfsSwParam->DFS_T[id][idx1].idx].counter;
+ pDfsSwParam->CounterStored2[PeriodMatched] = loop;
+ pDfsSwParam->CounterStored3 = idx[1];
+ }
+#endif
+ /*printk("%d %d\n", loop, pDfsSwParam->DFS_T[id][idx[1]-loop].period);*/
+ PeriodMatched++;
+ }
+
+ }
+
+
+ if (PeriodMatched > pDfsSwParam->dfs_declare_thres)
+ {
+#ifdef DFS_DEBUG
+ if (PeriodMatched == 3)
+ {
+ pDfsSwParam->T_Matched_3++;
+ /*printk("counter=%d %d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1], pDfsSwParam->CounterStored[2]);*/
+ /*printk("idx[1]=%d, loop =%d %d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1], pDfsSwParam->CounterStored2[2]);*/
+ }
+ else if (PeriodMatched == 4)
+ {
+ pDfsSwParam->T_Matched_4++;
+ /*printk("counter=%d %d %d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1], pDfsSwParam->CounterStored[2], pDfsSwParam->CounterStored[3]);*/
+ /*printk("idx[1]=%d, loop =%d %d %d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1], pDfsSwParam->CounterStored2[2], pDfsSwParam->CounterStored2[3]);*/
+ }
+ else
+ {
+ pDfsSwParam->T_Matched_5++;
+ /*printk("counter=%d %d %d %d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1], pDfsSwParam->CounterStored[2], pDfsSwParam->CounterStored[3], pDfsSwParam->CounterStored[4]);*/
+ /*printk("idx[1]=%d, loop =%d %d %d %d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1], pDfsSwParam->CounterStored2[2], pDfsSwParam->CounterStored2[3], pDfsSwParam->CounterStored2[4]);*/
+ }
+
+ pDfsSwParam->DebugPortPrint = 1;
+#endif
+ printk("Radar Detected(CE), W=%d, T=%d (%d), period matched=%d\n", (unsigned int)pCE_T->width, (unsigned int)T[1], (unsigned int)id, PeriodMatched);
+
+
+ if (PeriodMatched > (pDfsSwParam->dfs_declare_thres + 1))
+ radar_detected = 1;
+ return radar_detected;
+ }
+#ifdef DFS_DEBUG
+ else if (PeriodMatched == 2)
+ {
+ pDfsSwParam->T_Matched_2++;
+ /*printk("counter=%d %d\n", pDfsSwParam->CounterStored[0], pDfsSwParam->CounterStored[1]);*/
+ /*printk("idx[1]=%d, loop =%d %d\n", pDfsSwParam->CounterStored3, pDfsSwParam->CounterStored2[0], pDfsSwParam->CounterStored2[1]);*/
+ }
+#endif
+
+
+ }
+ }
+
+ }
+
+ } /* for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++)*/
+
+ } /* for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++)*/
+
+ }
+
+ } /* for (i = end_idx; i < start_idx; i--)*/
+
+
+ return radar_detected;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Recheck DFS radar of stager type.
+ Arguments:
+ pAdapter Pointer to our adapter
+ dfs_channel DFS detect channel
+ Return Value:
+ "TRUE" if check pass, "FALSE" otherwise.
+ Note:
+ ==========================================================================
+ */
+static BOOLEAN StagerRadarCheck(IN PRTMP_ADAPTER pAd, UINT8 dfs_channel)
+{
+ UINT T1=0, T2=0, T3=0, T_all=0, F1, F2, F3 = 0, Fmax = 0, freq_diff_min, freq_diff_max;
+ UINT8 dfs_stg2=0, dfs_typ5=0; /*, bbp141=0;*/
+ UINT F_MAX, F_MID, F_MIN;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--->StagerRadarCheck()\n"));
+ {
+ UINT32 bbp_val = 0;
+ PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam;
+
+ /* select channel */
+ bbp_val = (pDfsProgramParam->ChEnable << 16) | dfs_channel;
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R0, bbp_val);
+
+ RTMP_BBP_IO_READ32(pAd, DFS_R19, &T_all);
+ RTMP_BBP_IO_READ32(pAd, DFS_R22, &T1);
+ RTMP_BBP_IO_READ32(pAd, DFS_R25, &T2);
+ }
+
+ T3 = T_all - T1 -T2;
+
+ if (T3 < 5)
+ T3 = 0;
+
+ /*1. Check radar stagger2 or stagger3*/
+ if (T3 == 0 || ((T3 > (T1 + T2) ? (T3 - T1 - T2) : (T1 + T2 - T3)) < 25))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("stg2 confirmed\n"));
+ dfs_stg2 =1;
+ F1 = 20000000/T1; /*hz*/
+ F2 = 20000000/T2;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("stg3 confirmed\n"));
+ F1 = 20000000/T1; /*hz*/
+ F2 = 20000000/T2;
+ F3 = 20000000/T3;
+ }
+
+ F_MAX = (F1 > F2) ? ( (F1 > F3) ? F1 : F3 ) : ( (F2 > F3) ? F2 : F3 );
+ F_MIN = (F1 < F2) ? ( (F1 < F3) ? F1 : F3 ) : ( (F2 < F3) ? F2 : F3 );
+ F_MID = (F1 > F2) ? ((F1 < F3) ? F1 : ( (F2 > F3) ? F2 : F3 )) : ( F2 < F3 ? F2 : ((F1 > F3) ? F1 :F3) );
+
+ DBGPRINT(RT_DEBUG_TRACE, ("F_MAX=%d F_MID=%d F_MIN=%d\n", F_MAX, F_MID, F_MIN));
+
+ F1 = F_MAX;
+ F2 = F_MID;
+ F3 = F_MIN;
+
+ Fmax = F1;
+
+ /*2. Check radar type 5 or type6*/
+ if (Fmax>295 && Fmax<=405)
+ {
+ dfs_typ5 = 1;
+ DBGPRINT(RT_DEBUG_TRACE, ("type5 confirmed\n"));
+ freq_diff_min = 20;
+ freq_diff_max = 50;
+ }
+ else if (Fmax>405 && Fmax<=1205) /* tolerate more range for looser type6 */
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("type6 confirmed\n"));
+ freq_diff_min = 80;
+ freq_diff_max = 400;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck failed, T1=%d, T2=%d, T3=%d\n", T1, T2, T3));
+ return FALSE;
+ }
+
+ /*3. According to decision of stagger and type do period check */
+ if (dfs_stg2 == 1)
+ {
+ UINT freq_diff = (F1 - F2);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck freq_diff_min=%d freq_diff_max=%d \n", freq_diff_min, freq_diff_max));
+ DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck dfs_stg2, dff=%d \n", freq_diff));
+
+ if ((freq_diff >= freq_diff_min) && (freq_diff <= freq_diff_max))
+ return TRUE; /* S/W check success */
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck failed, F1=%d, F2=%d\n", F1, F2));
+ DBGPRINT(RT_DEBUG_TRACE, ("stg2 fail on S/W Freq confirmed\n"));
+ return FALSE; /* S/W check fail */
+ }
+ }
+ else /* dfs_stg3 */
+ {
+ UINT freq_diff_1 = (F1 - F2);
+ UINT freq_diff_2 = (F2 - F3);
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck freq_diff_min=%d freq_diff_max=%d \n", freq_diff_min, freq_diff_max));
+ DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck dfs_stg3, dff_1=%d, dff_2=%d \n", freq_diff_1, freq_diff_2));
+
+
+ if( (freq_diff_1 >= freq_diff_min) && (freq_diff_1 <= freq_diff_max) && (freq_diff_2 >= freq_diff_min) && (freq_diff_2 <= freq_diff_max) )
+ return TRUE; /* S/W check success */
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("StagerRadarCheck failed, F1=%d, F2=%d, F3=%d\n", F1, F2, F3));
+ DBGPRINT(RT_DEBUG_TRACE, ("stg3 fail on S/W Freq confirmed\n"));
+ return FALSE; /* S/W check fail */
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<---StagerRadarCheck()\n"));
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Recheck DFS radar of chrp type.
+ Arguments:
+ pAdapter Pointer to our adapter
+ dfs_channel DFS detect channel
+ Return Value:
+ "TRUE" if check pass, "FALSE" otherwise.
+ Note:
+ ==========================================================================
+ */
+static BOOLEAN ChirpRadarCheck(IN PRTMP_ADAPTER pAd)
+{
+ UINT32 CurrentTime, delta;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+
+
+ RTMP_IO_READ32(pAd, PBF_LIFE_TIMER, &CurrentTime);
+ delta = CurrentTime - pRadarDetect->TimeStamp;
+ pRadarDetect->TimeStamp = CurrentTime;
+
+ /* ChirpCheck = 0 means the very first detection since start up*/
+ if (pRadarDetect->ChirpCheck++ == 0)
+ return FALSE;
+
+ if (delta <= (12*(1<<20))) /* 12 sec */
+ {
+ if (pRadarDetect->ChirpCheck >= 2)
+ {
+ /* Anouce the radar on any mutiple detection within 12 sec*/
+ DBGPRINT(RT_DEBUG_TRACE, ("ChirpRadarCheck OK.\n"));
+ return TRUE;
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ChirpRadarCheck failed, discard previous detection.\n"));
+ pRadarDetect->ChirpCheck = 1;
+ return FALSE;
+ }
+ /* default */
+ return FALSE;
+}
+
+static VOID DfsCheckBusyIdle(
+ IN PRTMP_ADAPTER pAd)
+{
+ int busy_delta, idle_delta;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+
+ RTMP_IO_READ32(pAd, CH_IDLE_STA, &pRadarDetect->idle_time);
+ RTMP_IO_READ32(pAd, CH_BUSY_STA, &pRadarDetect->busy_time);
+
+ /*ch_busy_sta_index begining at 0.*/
+ busy_delta = pRadarDetect->busy_time - pRadarDetect->ch_busy_sta[pRadarDetect->ch_busy_sta_index];
+ idle_delta = pRadarDetect->idle_time - pRadarDetect->ch_idle_sta[pRadarDetect->ch_busy_sta_index];
+
+ if (busy_delta < 0)
+ {
+ busy_delta = ~busy_delta;
+ busy_delta = (busy_delta >> CH_BUSY_SAMPLE_POWER);
+ busy_delta = ~busy_delta;
+ }
+ else
+ busy_delta = busy_delta >> CH_BUSY_SAMPLE_POWER;
+
+ if (idle_delta < 0)
+ {
+ idle_delta = ~idle_delta;
+ idle_delta = idle_delta >> CH_BUSY_SAMPLE_POWER;
+ idle_delta = ~idle_delta;
+ }
+ else
+ idle_delta = idle_delta >> CH_BUSY_SAMPLE_POWER;
+
+ pRadarDetect->ch_busy_sum += busy_delta;
+ pRadarDetect->ch_idle_sum += idle_delta;
+
+ /* not sure if this is necessary??*/
+ if (pRadarDetect->ch_busy_sum < 0)
+ pRadarDetect->ch_busy_sum = 0;
+ if (pRadarDetect->ch_idle_sum < 0)
+ pRadarDetect->ch_idle_sum = 0;
+
+ pRadarDetect->ch_busy_sta[pRadarDetect->ch_busy_sta_index] = pRadarDetect->busy_time;
+ pRadarDetect->ch_idle_sta[pRadarDetect->ch_busy_sta_index] = pRadarDetect->idle_time;
+
+ pRadarDetect->ch_busy_sta_index++;
+ pRadarDetect->ch_busy_sta_index &= CH_BUSY_MASK;
+
+ if ((pRadarDetect->ch_idle_sum >> pRadarDetect->ch_busy_idle_ratio) < pRadarDetect->ch_busy_sum )
+ {
+
+ if (!(pRadarDetect->McuRadarDebug & RADAR_DEBUG_DONT_CHECK_BUSY))
+ pRadarDetect->ch_busy = 1;
+ }
+ else
+ {
+ if (!(pRadarDetect->McuRadarDebug & RADAR_DEBUG_DONT_CHECK_RSSI))
+ {
+ if ((pAd->ApCfg.RssiSample.AvgRssi0) && (pAd->ApCfg.RssiSample.AvgRssi0 > pRadarDetect->DfsRssiHigh))
+ pRadarDetect->ch_busy = 2;
+ else if ((pAd->ApCfg.RssiSample.AvgRssi0) && (pAd->ApCfg.RssiSample.AvgRssi0 < pRadarDetect->DfsRssiLow))
+ pRadarDetect->ch_busy = 3;
+ else
+ pRadarDetect->ch_busy = 0;
+ }
+ }
+
+ if (pRadarDetect->print_ch_busy_sta)
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("%d %d %d %d\n", pRadarDetect->ch_idle_sum, pRadarDetect->ch_busy_sum, pAd->ApCfg.RssiSample.AvgRssi0, pRadarDetect->ch_busy));
+
+}
+
+static BOOLEAN DfsChannelCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 DfsChannel)
+{
+ pNewDFSTable pDFS2Table;
+ UINT8 i;
+ UINT32 W, T;
+ BOOLEAN radarDeclared = 0;
+ /*UCHAR BBP_1 = 0, BBP_2 = 0, BBP_3 = 0, BBP_4 = 0;*/
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("DFS HW check channel = 0x%x\n", DfsChannel));
+ /*Select the DFS table based on radar country region*/
+ if (pAd->CommonCfg.RDDurRegion == FCC)
+ pDFS2Table = &NewDFSTable1[0];
+ else if (pAd->CommonCfg.RDDurRegion == CE)
+ {
+ pDFS2Table = &NewDFSTable1[1];
+ }
+ else /* Japan*/
+ {
+ if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64))
+ {
+ pDFS2Table = &NewDFSTable1[3];
+ }
+ else
+ {
+ pDFS2Table = &NewDFSTable1[2];
+ }
+ }
+ /*check which channe(0~3) is detecting radar signals*/
+ for (i = 0; i < pAd->chipCap.DfsEngineNum; i++)
+ {
+
+ if (DfsChannel & (0x1 << i))
+ {
+ UINT32 bbp_val = 0;
+ PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam;
+
+ /* select channel */
+ bbp_val = (pDfsProgramParam->ChEnable << 16) | i;
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R0, bbp_val);
+
+ RTMP_BBP_IO_READ32(pAd, DFS_R19, &T);
+ RTMP_BBP_IO_READ32(pAd, DFS_R20, &W);
+ if (DfsSwCheckOnHwDetection(pAd, pDFS2Table, i, T, W) == FALSE)
+ continue;
+
+ printk("T = %u, W= %u detected by ch %d\n", T, W, i);
+ RTMP_BBP_IO_READ32(pAd, 0x2a70, &bbp_val);
+ printk("bbp 0x2a70 = 0x%08x\n", bbp_val);
+
+ /*set this variable to 1 for announcing that we find the radar signals.*/
+ radarDeclared = 1;
+
+ if ( ((i == 3) || (i == 2)) && (pDFS2Table->entry[i].mode != 0) )
+ {
+ ULONG B, W2;
+ RTMP_BBP_IO_READ32(pAd, DFS_R22, &B);
+ DBGPRINT(RT_DEBUG_TRACE, ("Burst = %lu(0x%lx)\n", B, B));
+
+ RTMP_BBP_IO_READ32(pAd, DFS_R23, &W2);
+ DBGPRINT(RT_DEBUG_TRACE, ("The second Width = %lu(0x%lx)\n", W2, W2));
+ }
+
+ }
+ }
+ return radarDeclared;
+}
+
+static BOOLEAN DfsEventDataFetch(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ OUT PDFS_EVENT pDfsEvent)
+{
+ pDfsEvent->EngineId = pData[0];
+ if (pDfsEvent->EngineId == 0xff) /* end of event */
+ return FALSE;
+
+ pDfsEvent->TimeStamp = pData[1];
+ pDfsEvent->TimeStamp |= (pData[2] << 8);
+ pDfsEvent->TimeStamp |= (pData[3] << 16);
+
+ pDfsEvent->Width = pData[4];
+ pDfsEvent->Width |= (pData[5] << 8);
+
+ /* Check if event is valid */
+ if (!DFS_EVENT_SANITY_CHECK(pAd, *pDfsEvent))
+ return FALSE;
+
+ return TRUE;
+}
+
+VOID NewRadarDetectionProgram(PRTMP_ADAPTER pAd, pNewDFSTable pDFS2Table)
+{
+ UINT8 idx, TalbeIdx, DFSR3;
+ UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam;
+
+
+ pRadarDetect->bDfsInit = FALSE;
+
+ /* Get Table index*/
+ for (TalbeIdx = 0; !((1<<TalbeIdx) & pDFS2Table->type); TalbeIdx++)
+ {
+ if (TalbeIdx > MAX_RD_REGION)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Table index out of range.\n"));
+ return;
+ }
+ }
+
+ for(idx = 0; idx<DfsEngineNum; idx++)
+ {
+ if ((pRadarDetect->DFSParamFromConfig & (0x1<<idx)) && pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].valid)
+ {
+ pDFS2Table->entry[idx].mode = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].mode;
+ pDFS2Table->entry[idx].avgLen = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].avgLen;
+ pDFS2Table->entry[idx].ELow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].ELow;
+ pDFS2Table->entry[idx].EHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EHigh;
+ pDFS2Table->entry[idx].WLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].WLow;
+ pDFS2Table->entry[idx].WHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].WHigh;
+ pDFS2Table->entry[idx].EpsilonW = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EpsilonW;
+ pDFS2Table->entry[idx].TLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].TLow;
+ pDFS2Table->entry[idx].THigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].THigh;
+ pDFS2Table->entry[idx].EpsilonT = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EpsilonT;
+ pDFS2Table->entry[idx].BLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].BLow;
+ pDFS2Table->entry[idx].BHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].BHigh;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("TalbeIdx = %d; idx = %d; DFSParam = %2d; %3d; %3d; %3d; %3d; %4d; %3d; %6lu; %7lu; %4d; %2lu; %2lu\n", TalbeIdx, idx,
+ pDFS2Table->entry[idx].mode, pDFS2Table->entry[idx].avgLen, pDFS2Table->entry[idx].ELow,
+ pDFS2Table->entry[idx].EHigh, pDFS2Table->entry[idx].WLow, pDFS2Table->entry[idx].WHigh,
+ pDFS2Table->entry[idx].EpsilonW, pDFS2Table->entry[idx].TLow, pDFS2Table->entry[idx].THigh,
+ pDFS2Table->entry[idx].EpsilonT, pDFS2Table->entry[idx].BLow, pDFS2Table->entry[idx].BHigh));
+ }
+ }
+
+ /* Symmetric round*/
+ if(pRadarDetect->SymRoundFromCfg != 0)
+ {
+ pDfsProgramParam->Symmetric_Round = pRadarDetect->SymRoundFromCfg;
+ DBGPRINT(RT_DEBUG_TRACE, ("Symmetric_Round = %d\n", pDfsProgramParam->Symmetric_Round));
+ }
+
+ /* BusyIdleRatio*/
+ if(pRadarDetect->BusyIdleFromCfg != 0)
+ {
+ pRadarDetect->ch_busy_idle_ratio = pRadarDetect->BusyIdleFromCfg;
+ DBGPRINT(RT_DEBUG_TRACE, ("ch_busy_idle_ratio = %d\n", pRadarDetect->ch_busy_idle_ratio));
+ }
+ /* DfsRssiHigh*/
+ if(pRadarDetect->DfsRssiHighFromCfg != 0)
+ {
+ pRadarDetect->DfsRssiHigh = pRadarDetect->DfsRssiHighFromCfg;
+ DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiHigh = %d\n", pRadarDetect->DfsRssiHigh));
+ }
+ /* DfsRssiLow*/
+ if(pRadarDetect->DfsRssiLowFromCfg != 0)
+ {
+ pRadarDetect->DfsRssiLow = pRadarDetect->DfsRssiLowFromCfg;
+ DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiLow = %d\n", pRadarDetect->DfsRssiLow));
+ }
+
+ /*pRadarDetect->MCURadarRegion = pAd->CommonCfg.RDDurRegion;*/
+ pRadarDetect->MCURadarRegion = pDFS2Table->type;
+
+ {
+ UINT32 bbp_val = 0;
+
+ DFSR3 = pDfsProgramParam->Symmetric_Round << 4;
+
+ /* Full 40Mhz*/
+ if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)
+ DFSR3 |= 0x80; /* BW 40*/
+
+ /* Delta Delay*/
+ DFSR3 |= (pDfsProgramParam->DeltaDelay & 0xf);
+ DBGPRINT(RT_DEBUG_TRACE,("R3 = 0x%x\n", DFSR3));
+
+ /* VGA Mask*/
+ DBGPRINT(RT_DEBUG_TRACE,("VGA_Mask = 0x%x\n", pDfsProgramParam->VGA_Mask));
+
+ /* Input Control 0 */
+ bbp_val = (pDfsProgramParam->VGA_Mask << 16) | (DFSR3);
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R2, bbp_val);
+
+
+ /* packet end Mask*/
+ DBGPRINT(RT_DEBUG_TRACE,("Packet_End_Mask = 0x%x\n", pDfsProgramParam->Packet_End_Mask));
+
+ /* Rx PE Mask*/
+ DBGPRINT(RT_DEBUG_TRACE,("Rx_PE_Mask = 0x%x\n", pDfsProgramParam->Rx_PE_Mask));
+
+ /* Input Control 1 */
+ bbp_val = (pDfsProgramParam->Rx_PE_Mask << 16) | (pDfsProgramParam->Packet_End_Mask);
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R3, bbp_val);
+
+ /* program each channel*/
+ for (idx = 0; idx < DfsEngineNum; idx++)
+ {
+ /* select channel*/
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R0, idx);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("write DFS Channle[%d] configuration \n", idx));
+
+ /* Detection Mode */
+ bbp_val = (pDFS2Table->entry[idx].mode & 0xf);
+
+ if (pAd->chipCap.DfsEngineNum > 4 && (idx==4 || idx==5))
+ bbp_val |= ((pDFS2Table->entry[idx].avgLen & 0x3) << 28);
+ else
+ bbp_val |= ((pDFS2Table->entry[idx].avgLen & 0x1ff) << 16);
+
+ /* DFS Mode */
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R4, bbp_val);
+
+ /* DFS Energy */
+ bbp_val = ((pDFS2Table->entry[idx].EHigh & 0x0fff) << 16) | (pDFS2Table->entry[idx].ELow & 0x0fff);
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R5, bbp_val);
+
+ /* DFS Period Low */
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R7, pDFS2Table->entry[idx].TLow);
+
+ /* DFS Period High */
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R9, pDFS2Table->entry[idx].THigh);
+
+ /* DFS Burst Low */
+ /* DFS Burst High */
+
+ /* DFS Width */
+ bbp_val = ((pDFS2Table->entry[idx].WHigh & 0x0fff) << 16) | (pDFS2Table->entry[idx].WLow & 0x0fff);
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R14, bbp_val);
+
+
+ /* DFS Measurement Uncertainty */
+ bbp_val = (pDFS2Table->entry[idx].EpsilonW << 16) | (pDFS2Table->entry[idx].EpsilonT);
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R15, bbp_val);
+
+ /* DFS Event Expiration */
+ if (pDfsProgramParam->RadarEventExpire[idx] != 0)
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R17, pDfsProgramParam->RadarEventExpire[idx]);
+
+ }
+
+ /* Reset status */
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R1, pRadarDetect->EnabledChMask);
+
+ /* Enable detection*/
+ bbp_val = (pDfsProgramParam->ChEnable << 16);
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R0, bbp_val);
+ }
+ pRadarDetect->bDfsInit = TRUE;
+
+}
+
+BOOLEAN DfsSwCheckOnHwDetection(
+ IN PRTMP_ADAPTER pAd,
+ IN pNewDFSTable pDFS2Table,
+ IN UINT8 DfsChannel,
+ IN ULONG RadarPeriod,
+ IN ULONG RadarWidth)
+{
+ BOOLEAN bRadarCheck = TRUE;
+ if (!RadarPeriod || !RadarWidth)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Block eception on zero RadarPeriod or RadarWidth\n"));
+ return FALSE;
+ }
+
+ if (pDFS2Table->type == NEW_DFS_JAP)
+ {
+ /* Double check on pusle Width and Period*/
+ if (DfsChannel < 3)
+ {
+ /*check short pulse*/
+ if (RadarWidth < 375)
+ {
+ /* block the illegal period */
+ if ((RadarPeriod < 2800) ||
+ (RadarPeriod > 5000 && RadarPeriod < 6400) ||
+ (RadarPeriod > 6800 && RadarPeriod < 27560)||
+ (RadarPeriod > 27960 && RadarPeriod < 28360) ||
+ (RadarPeriod > 28700 && RadarPeriod < 79900) ||
+ (RadarPeriod > 80100))
+ {
+ /*(0~140), (250~320us), (340~1378us), (1398~1418), (1435~3995us) and (4005us~) according to the spec*/
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth));
+ bRadarCheck = FALSE;
+ }
+ }
+ else if (RadarWidth > 375)
+ {
+ if ((RadarPeriod<3500) || (RadarPeriod>10400))
+ {
+ /* block the illegal period */
+ /*(0~175) and (520us~) according to the spec*/
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth));
+ bRadarCheck = FALSE;
+ }
+ }
+ }
+ else if (DfsChannel == 3)
+ {
+ bRadarCheck = ChirpRadarCheck(pAd);
+ }
+ }
+ else if (pDFS2Table->type == NEW_DFS_EU)
+ {
+ if (DfsChannel == 4) /* to do: check dfs mode 8or9*/
+ {
+ if (StagerRadarCheck(pAd, DfsChannel) == FALSE)
+ bRadarCheck = FALSE;
+ }
+ }
+ return bRadarCheck;
+}
+
+static VOID ChannelSelectOnRadarDetection(
+ IN PRTMP_ADAPTER pAd)
+{
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ UINT i;
+
+ if (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)
+ return;
+
+ for (i=0; i<pAd->ChannelListNum; i++)
+ {
+ if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel)
+ {
+ if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)
+ {
+ if ((pAd->ChannelList[i].Channel >> 2) & 1)
+ {
+ if ((pAd->ChannelList[i+1].Channel - pAd->ChannelList[i].Channel) == 4 )
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Find extend channel = %u\n", pAd->ChannelList[i+1].Channel));
+ pAd->ChannelList[i+1].RemainingTimeForUse = 1800;
+ }
+ }
+ else
+ {
+ if ((pAd->ChannelList[i].Channel - pAd->ChannelList[i-1].Channel) == 4 )
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Find extend channel = %u\n", pAd->ChannelList[i-1].Channel));
+ pAd->ChannelList[i-1].RemainingTimeForUse = 1800;
+ }
+ }
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("BW is not 40.\n"));
+
+ pAd->ChannelList[i].RemainingTimeForUse = 1800;/*30 min = 1800 sec*/
+ break;
+ }
+ }
+
+ /*when find an radar, the ChMovingTime will be set to announce how many seconds to sending software radar detection time.*/
+ if ((pAd->CommonCfg.RDDurRegion == CE) && RESTRICTION_BAND_1(pAd))
+ pAd->Dot11_H.ChMovingTime = 605;
+ else
+ pAd->Dot11_H.ChMovingTime = 65;
+
+ /*if the Radar country region is JAP, we need find a new clear channel */
+ if (pAd->CommonCfg.RDDurRegion == JAP_W56)
+ {
+ for (i = 0; i < pAd->ChannelListNum ; i++)
+ {
+ pAd->CommonCfg.Channel = APAutoSelectChannel(pAd, FALSE);
+ if ((pAd->CommonCfg.Channel >= 100) && (pAd->CommonCfg.Channel <= 140))
+ break;
+ }
+ }
+ else if (pAd->CommonCfg.RDDurRegion == JAP_W53)
+ {
+ for (i = 0; i < pAd->ChannelListNum ; i++)
+ {
+ pAd->CommonCfg.Channel = APAutoSelectChannel(pAd, FALSE);
+ if ((pAd->CommonCfg.Channel >= 36) && (pAd->CommonCfg.Channel <= 60))
+ break;
+ }
+ }
+ else
+ pAd->CommonCfg.Channel = APAutoSelectChannel(pAd, FALSE);
+
+#ifdef DOT11_N_SUPPORT
+ N_ChannelCheck(pAd);
+#endif /* DOT11_N_SUPPORT */
+
+ /*ApSelectChannelCheck(pAd);*/
+ if (pAd->Dot11_H.RDMode == RD_NORMAL_MODE)
+ {
+ pAd->Dot11_H.RDMode = RD_SWITCHING_MODE;
+ /* Prepare a count-down for channel switching */
+ pAd->Dot11_H.CSCount = 0;
+ }
+ else if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE)
+ {
+ pAd->Dot11_H.RDMode = RD_SWITCHING_MODE;
+ /*set this flag to 1 and the AP will restart to switch into new channel */
+ pRadarDetect->DFSAPRestart = 1;
+ schedule_dfs_task(pAd);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s(): Error! Unexpected radar state.\n", __FUNCTION__));
+ }
+ pRadarDetect->radarDeclared = 0;
+}
+
+static BOOLEAN DfsEventDrop(
+ IN PRTMP_ADAPTER pAd,
+ IN PDFS_EVENT pDfsEvent)
+{
+ UINT32 TimeDiff = 0; /* unit: 50ns */
+ UINT16 PreEnvtWidth = 0;
+ BOOLEAN RetVal = FALSE;
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pAd->CommonCfg.RadarDetect.DfsSwParam;
+ PDFS_EVENT pPreDfsEvent = &pDfsSwParam->PreDfsEvent;
+
+ if (pDfsEvent->EngineId != pPreDfsEvent->EngineId)
+ {
+ /* update prevoius event record then leave */
+ NdisCopyMemory(pPreDfsEvent, pDfsEvent, DFS_EVENT_SIZE);
+ return FALSE;
+ }
+
+ if (pDfsEvent->EngineId == 0x01 || pDfsEvent->EngineId == 0x02)
+ {
+ if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)
+ {
+ TimeDiff = ((pDfsEvent->TimeStamp - pPreDfsEvent->TimeStamp) >> 1); /* 25ns to 50ns*/
+ PreEnvtWidth = pPreDfsEvent->Width >> 1;
+ }
+ else
+ {
+ TimeDiff = (pDfsEvent->TimeStamp - pPreDfsEvent->TimeStamp);
+ PreEnvtWidth = pPreDfsEvent->Width;
+ }
+
+ if (TimeDiff < pDfsSwParam->EvtDropAdjTime &&
+ PreEnvtWidth >= 200)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("%s(): EngineId = %x, Width = %u, TimeStamp = %u\n",
+ __FUNCTION__,
+ pDfsEvent->EngineId,
+ pDfsEvent->Width,
+ pDfsEvent->TimeStamp));
+ RetVal = TRUE;
+ }
+ }
+
+ /* update prevoius event record */
+ NdisCopyMemory(pPreDfsEvent, pDfsEvent, DFS_EVENT_SIZE);
+
+ return RetVal;
+}
+
+static void dfs_sw_init(PRTMP_ADAPTER pAd)
+{
+ int j, k;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam;
+
+ pDfsSwParam->fcc_5_threshold = 1000;
+ pDfsSwParam->fcc_5_idx = 0;
+ pDfsSwParam->fcc_5_last_idx = 0;
+ pDfsSwParam->dfs_check_loop = DFS_SW_RADAR_CHECK_LOOP;
+ pDfsSwParam->dfs_width_diff_ch1_Shift = DFS_SW_RADAR_CH1_SHIFT;
+ pDfsSwParam->dfs_width_diff_ch2_Shift = DFS_SW_RADAR_CH2_SHIFT;
+ pDfsSwParam->PreDfsEvent.EngineId = 0xff;
+ pDfsSwParam->EvtDropAdjTime = 2000;
+
+ /* clear long pulse table */
+ pDfsSwParam->FCC_5[pDfsSwParam->fcc_5_idx].counter = 0;
+ pDfsSwParam->fcc_5_idx = 0;
+ pDfsSwParam->fcc_5_last_idx = 0;
+
+ /*pDfsSwParam->dfs_width_diff_Shift = DFS_SW_RADAR_SHIFT;*/
+ pDfsSwParam->dfs_width_ch0_err_L = DFS_SW_RADAR_CH0_ERR;
+ if (pAd->CommonCfg.RDDurRegion == CE)
+ pDfsSwParam->dfs_period_err = (DFS_SW_RADAR_PERIOD_ERR << 2);
+ else
+ pDfsSwParam->dfs_period_err = DFS_SW_RADAR_PERIOD_ERR;
+ if (pAd->CommonCfg.RDDurRegion == CE)
+ {
+ pDfsSwParam->dfs_width_ch0_err_H = CE_STAGGERED_RADAR_CH0_H_ERR;
+ pDfsSwParam->dfs_declare_thres = CE_STAGGERED_RADAR_DECLARE_THRES;
+ pDfsSwParam->dfs_max_period = CE_STAGGERED_RADAR_PERIOD_MAX;
+ }
+ else
+ {
+ /*pDfsSwParam->dfs_declare_thres = DFS_SW_RADAR_DECLARE_THRES;*/
+ if (pAd->CommonCfg.RDDurRegion == FCC)
+ pDfsSwParam->dfs_max_period = FCC_RADAR_PERIOD_MAX;
+ else if (pAd->CommonCfg.RDDurRegion == JAP)
+ pDfsSwParam->dfs_max_period = JAP_RADAR_PERIOD_MAX;
+ }
+
+ pDfsSwParam->dfs_check_loop = DFS_SW_RADAR_CHECK_LOOP;
+ pDfsSwParam->dfs_width_diff_ch1_Shift = DFS_SW_RADAR_CH1_SHIFT;
+ pDfsSwParam->dfs_width_diff_ch2_Shift = DFS_SW_RADAR_CH2_SHIFT;
+ pDfsSwParam->dfs_width_ch0_err_L = DFS_SW_RADAR_CH0_ERR;
+ if (pAd->CommonCfg.RDDurRegion == CE)
+ pDfsSwParam->dfs_period_err = (DFS_SW_RADAR_PERIOD_ERR << 2);
+ else
+ pDfsSwParam->dfs_period_err = DFS_SW_RADAR_PERIOD_ERR;
+
+ if (pAd->CommonCfg.RDDurRegion == CE)
+ {
+ pDfsSwParam->dfs_width_ch0_err_H = CE_STAGGERED_RADAR_CH0_H_ERR;
+ pDfsSwParam->dfs_declare_thres = CE_STAGGERED_RADAR_DECLARE_THRES;
+ pDfsSwParam->dfs_max_period = CE_STAGGERED_RADAR_PERIOD_MAX;
+ }
+ else
+ {
+ /*pDfsSwParam->dfs_declare_thres = DFS_SW_RADAR_DECLARE_THRES;*/
+ if (pAd->CommonCfg.RDDurRegion == FCC)
+ pDfsSwParam->dfs_max_period = FCC_RADAR_PERIOD_MAX;
+ else if (pAd->CommonCfg.RDDurRegion == JAP)
+ pDfsSwParam->dfs_max_period = JAP_RADAR_PERIOD_MAX;
+ }
+
+ if (pRadarDetect->use_tasklet)
+ pRadarDetect->PollTime = NEW_DFS_CHECK_TIME_TASKLET;
+ else
+ pRadarDetect->PollTime = NEW_DFS_CHECK_TIME;
+
+ for (k = 0; k < pAd->chipCap.DfsEngineNum; k++)
+ {
+ for (j = 0; j < NEW_DFS_DBG_PORT_ENT_NUM; j++)
+ {
+ pDfsSwParam->DFS_W[k][j].start_idx = 0xffff;
+ }
+ }
+
+ for (k = 0; k < pAd->chipCap.DfsEngineNum; k++)
+ {
+ pDfsSwParam->sw_idx[k] = NEW_DFS_DBG_PORT_ENT_NUM - 1;
+ pDfsSwParam->hw_idx[k] = 0;
+ }
+
+ NdisZeroMemory(pDfsSwParam->DFS_T, sizeof(pDfsSwParam->DFS_T));
+ NdisZeroMemory(pDfsSwParam->DFS_W, sizeof(pDfsSwParam->DFS_W));
+}
+
+void modify_table1(PRTMP_ADAPTER pAd, ULONG idx, ULONG value)
+{
+ pNewDFSTable pDFS2Table;
+ ULONG x, y;
+ UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam;
+
+ if (pAd->CommonCfg.RDDurRegion == FCC)
+ pDFS2Table = &NewDFSTable1[0];
+ else if (pAd->CommonCfg.RDDurRegion == CE)
+ {
+ pDFS2Table = &NewDFSTable1[1];
+ }
+ else /* Japan*/
+ {
+ if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64))
+ {
+ pDFS2Table = &NewDFSTable1[3];
+ }
+ else
+ {
+ pDFS2Table = &NewDFSTable1[2];
+ }
+ }
+
+ if (idx == 0)
+ {
+ pDfsProgramParam->DeltaDelay = value;
+ }
+ else if (idx <= (DfsEngineNum*16))
+ {
+ x = idx / 16;
+ y = idx % 16;
+ pRadarDetect->DFSParamFromConfig = 0; /* to prevent table be loaded from config file again */
+ switch (y)
+ {
+ case 1:
+ pDFS2Table->entry[x].mode = (USHORT)value;
+ break;
+ case 2:
+ pDFS2Table->entry[x].avgLen = (USHORT)value;
+ break;
+ case 3:
+ pDFS2Table->entry[x].ELow = (USHORT)value;
+ break;
+
+ case 4:
+ pDFS2Table->entry[x].EHigh = (USHORT)value;
+ break;
+
+ case 5:
+ pDFS2Table->entry[x].WLow = (USHORT)value;
+ break;
+
+ case 6:
+ pDFS2Table->entry[x].WHigh = (USHORT)value;
+ break;
+
+ case 7:
+ pDFS2Table->entry[x].EpsilonW = (USHORT)value;
+ break;
+
+ case 8:
+ pDFS2Table->entry[x].TLow = (ULONG)value;
+ break;
+
+ case 9:
+ pDFS2Table->entry[x].THigh = (ULONG)value;
+ break;
+
+ case 0xa:
+ pDFS2Table->entry[x].EpsilonT = (USHORT)value;
+ break;
+
+ case 0xb:
+ pDFS2Table->entry[x].BLow= (USHORT)value;
+ break;
+ case 0xc:
+ pDFS2Table->entry[x].BHigh = (USHORT)value;
+ break;
+
+ default:
+ break;
+ }
+
+ }
+ else if (idx == (DfsEngineNum*16 +1))
+ {
+ pDfsProgramParam->Symmetric_Round = (ULONG)value;
+ }
+ else if (idx == (DfsEngineNum*16 +2))
+ {
+ pDfsProgramParam->VGA_Mask = (ULONG)value;
+ }
+ else if (idx == (DfsEngineNum*16 +3))
+ {
+ pDfsProgramParam->Packet_End_Mask = (ULONG)value;
+ }
+ else if (idx == (DfsEngineNum*16 +4))
+ {
+ pDfsProgramParam->Rx_PE_Mask = (ULONG)value;
+ }
+
+ printk("Delta_Delay(0) = %d\n", pDfsProgramParam->DeltaDelay);
+
+ for (x = 0; x < DfsEngineNum; x++)
+ {
+ printk("Channel %lu\n", x);
+ printk("\t\tmode(%02lu)=%d, M(%02lu)=%03d, EL(%02lu)=%03d EH(%02lu)=%03d, WL(%02lu)=%03d WH(%02lu)=%04d, eW(%02lu)=%02d\n\t\tTL(%02lu)=%05u TH(%02lu)=%06u, eT(%02lu)=%03d, BL(%02lu)=%u, BH(%02lu)=%u\n",
+ (x*16+1), (unsigned int)pDFS2Table->entry[x].mode,
+ (x*16+2), (unsigned int)pDFS2Table->entry[x].avgLen,
+ (x*16+3), (unsigned int)pDFS2Table->entry[x].ELow,
+ (x*16+4), (unsigned int)pDFS2Table->entry[x].EHigh,
+ (x*16+5), (unsigned int)pDFS2Table->entry[x].WLow,
+ (x*16+6), (unsigned int)pDFS2Table->entry[x].WHigh,
+ (x*16+7), (unsigned int)pDFS2Table->entry[x].EpsilonW,
+ (x*16+8), (unsigned int)pDFS2Table->entry[x].TLow,
+ (x*16+9), (unsigned int)pDFS2Table->entry[x].THigh,
+ (x*16+0xa), (unsigned int)pDFS2Table->entry[x].EpsilonT,
+ (x*16+0xb), (unsigned int)pDFS2Table->entry[x].BLow,
+ (x*16+0xc), (unsigned int)pDFS2Table->entry[x].BHigh);
+ }
+
+ printk("Symmetric_Round(%02d) = %d\n", (DfsEngineNum*16 +1), pDfsProgramParam->Symmetric_Round);
+ printk("VGA_Mask(%02d) = %d\n", (DfsEngineNum*16 +2), pDfsProgramParam->VGA_Mask);
+ printk("Packet_End_Mask(%02d) = %d\n", (DfsEngineNum*16 +3), pDfsProgramParam->Packet_End_Mask);
+ printk("Rx_PE_Mask(%02d) = %d\n", (DfsEngineNum*16 +4), pDfsProgramParam->Rx_PE_Mask);
+
+}
+
+
+void modify_table2(PRTMP_ADAPTER pAd, ULONG idx, ULONG value)
+{
+ pNewDFSValidRadar pDFSValidRadar;
+ ULONG x, y;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+
+ idx--;
+
+ x = idx / 17;
+ y = idx % 17;
+
+ pDFSValidRadar = &NewDFSValidTable[0];
+
+ while (pDFSValidRadar->type != NEW_DFS_END)
+ {
+ if (pDFSValidRadar->type & pRadarDetect->MCURadarRegion)
+ {
+ if (x == 0)
+ break;
+ else
+ {
+ x--;
+ pDFSValidRadar++;
+ }
+ }
+ else
+ pDFSValidRadar++;
+ }
+
+ if (pDFSValidRadar->type == NEW_DFS_END)
+ {
+ printk("idx=%d exceed max number\n", (unsigned int)idx);
+ return;
+ }
+ switch(y)
+ {
+ case 0:
+ pDFSValidRadar->channel = value;
+ break;
+ case 1:
+ pDFSValidRadar->WLow = value;
+ break;
+ case 2:
+ pDFSValidRadar->WHigh = value;
+ break;
+ case 3:
+ pDFSValidRadar->W = value;
+ break;
+ case 8:
+ pDFSValidRadar->WMargin = value;
+ break;
+ case 9:
+ pDFSValidRadar->TLow = value;
+ break;
+ case 10:
+ pDFSValidRadar->THigh = value;
+ break;
+ case 11:
+ pDFSValidRadar->T = value;
+ break;
+ case 16:
+ pDFSValidRadar->TMargin = value;
+ break;
+ }
+
+ pDFSValidRadar = &NewDFSValidTable[0];
+ while (pDFSValidRadar->type != NEW_DFS_END)
+ {
+ if (pDFSValidRadar->type & pRadarDetect->MCURadarRegion)
+ {
+ printk("ch = %x --- ", pDFSValidRadar->channel);
+ printk("wl:wh = %d:%d ", pDFSValidRadar->WLow, pDFSValidRadar->WHigh);
+ printk("W = %u --- ", pDFSValidRadar->W);
+ printk("W Margin = %d\n", pDFSValidRadar->WMargin);
+ printk("Tl:Th = %d:%d ", (unsigned int)pDFSValidRadar->TLow, (unsigned int)pDFSValidRadar->THigh);
+ printk("T = %lu --- ", pDFSValidRadar->T);
+ printk("T Margin = %d\n", pDFSValidRadar->TMargin);
+ }
+ pDFSValidRadar++;
+ }
+
+}
+
+
+#ifdef RTMP_MAC_USB
+VOID NewUsbTimerCB_Radar(
+ IN PRTMP_ADAPTER pAd)
+
+{
+ UCHAR channel=0;
+ UCHAR radarDeclared = 0;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+
+#ifdef RALINK_ATE
+ /* Nothing to do in ATE mode */
+ if (ATE_ON(pAd))
+ return;
+#endif /* RALINK_ATE */
+
+ if (!DFS_CHECK_FLAGS(pAd, pRadarDetect) ||
+ (pRadarDetect->PollTime == 0))
+ return;
+
+ if (pRadarDetect->RadarTimeStampLow++ > 5)
+ pRadarDetect->RadarTimeStampLow = 0;
+
+ /*500ms*/
+ if ((pRadarDetect->RadarTimeStampLow % 5) == 0)
+ DfsCheckBusyIdle(pAd);
+
+ if (!pRadarDetect->bDfsSwDisable &&
+ (pRadarDetect->RadarTimeStampLow & 0x1) && /* 200ms */
+ !pRadarDetect->ch_busy)
+ SwCheckDfsEventWithFw(pAd);
+
+ /*
+ The following codes is used to check if the hardware find the Radar Signal
+ Read the 0~3 channel which had detected radar signals
+ Poll Status register
+ Set BBP_R140=0x02 and Read BBP_R141 to store at channel
+ */
+ //RTMP_DFS_IO_READ8(pAd, 0x2, &channel);
+ RTMP_BBP_IO_READ32(pAd, DFS_R1, &channel);
+
+ if (channel & pRadarDetect->EnabledChMask)
+ {
+ radarDeclared = DfsChannelCheck(pAd, channel & pRadarDetect->EnabledChMask);
+ }
+
+ /* reset the radar channel for new counting */
+ //RTMP_DFS_IO_WRITE8(pAd, 0x2, channel);
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R1, channel);
+
+
+ if (pRadarDetect->McuRadarDebug & RADAR_SIMULATE)
+ {
+ radarDeclared = 1;
+ pRadarDetect->McuRadarDebug &= ~RADAR_SIMULATE;
+ }
+
+ /* Now, find an Radar signal */
+ if (radarDeclared || pRadarDetect->radarDeclared)
+ {
+ /*
+ Radar found!!!
+ Announce that this channel could not use in 30 minutes if we need find a clear channel
+ */
+ if (!(pRadarDetect->McuRadarDebug & RADAR_DONT_SWITCH))
+ {
+ ChannelSelectOnRadarDetection(pAd);
+ }
+ else
+ pRadarDetect->radarDeclared = 0;
+
+ }
+}
+
+static VOID SwCheckDfsEventWithFw(
+ IN PRTMP_ADAPTER pAd)
+{
+ int k, NumEvent = 64; /* event number per event buffer */
+ UCHAR id = 0;
+ UCHAR BBPR127_Table[DFS_EVENT_BUFFER_SIZE];
+ UCHAR BBPR127_OWERID;
+ UCHAR OwenerIDValue = 0;
+ UCHAR BBP127TableIdx = 0;
+ DFS_EVENT DfsEvent;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam;
+
+ /*pRadarDetect->McuRadarTick = 0;*/
+
+ for (BBP127TableIdx = 0; BBP127TableIdx < 6; BBP127TableIdx++)
+ {
+ RTUSBMultiRead(pAd, BBPR127TABLE_OWNERID + BBP127TableIdx, &BBPR127_OWERID, 1);
+
+ if (BBPR127_OWERID == 1)
+ continue;
+
+ NdisZeroMemory(BBPR127_Table, DFS_EVENT_BUFFER_SIZE);
+ RTUSBMultiRead(pAd, BBPR127TABLE_OFFSET + (BBP127TableIdx * 512), BBPR127_Table, DFS_EVENT_BUFFER_SIZE);
+
+ OwenerIDValue = 0x01;
+ RTUSBMultiWrite_OneByte(pAd, BBPR127TABLE_OWNERID + BBP127TableIdx, &OwenerIDValue);
+
+ pDfsSwParam->dfs_w_counter++;
+
+ if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SHOW_RAW_EVENT)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("\n=============0x%02x==============\n", BBP127TableIdx));
+ if (IS_RT3572(pAd))
+ {
+ DFS_EVENT_BUFF_PRINT(1, BBPR127_Table, DFS_EVENT_BUFFER_SIZE);
+ }
+ else
+ {
+ DFS_EVENT_BUFF_PRINT(0, BBPR127_Table, DFS_EVENT_BUFFER_SIZE);
+ }
+ }
+
+ for (k = 0; k < NumEvent; k++)
+ {
+ PUCHAR pTableOffset = NULL;
+ if (IS_RT3572(pAd))
+ {
+ pTableOffset = (BBPR127_Table+1) + (DFS_EVENT_SIZE*k);
+ }
+ else
+ {
+ pTableOffset = BBPR127_Table + (DFS_EVENT_SIZE*k);
+ }
+
+ if (DfsEventDataFetch(pAd, pTableOffset, &DfsEvent) == FALSE)
+ break;
+
+ if (DfsEventDrop(pAd, &DfsEvent) == TRUE)
+ continue;
+
+ if (pRadarDetect->use_tasklet)
+ {
+ id = DfsEvent.EngineId;
+
+ if (id < pAd->chipCap.DfsEngineNum)
+ {
+ /*if (DfsEvent.TimeStamp != pDfsSwParam->DFS_W[id][((pDfsSwParam->dfs_w_idx[id] == 0)? (NEW_DFS_DBG_PORT_ENT_NUM-1):(pDfsSwParam->dfs_w_idx[id] - 1))].timestamp)*/
+ {
+ pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].counter = pDfsSwParam->dfs_w_counter;
+ pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].timestamp = DfsEvent.TimeStamp;
+ pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].width = DfsEvent.Width;
+
+ if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_EVENT)
+ {
+ printk("counter = %lu ", pDfsSwParam->dfs_w_counter);
+ DFS_EVENT_PRINT(DfsEvent);
+ }
+
+ pDfsSwParam->dfs_w_last_idx[id] = pDfsSwParam->dfs_w_idx[id];
+ pDfsSwParam->dfs_w_idx[id]++;
+
+ if (pDfsSwParam->dfs_w_idx[id] >= NEW_DFS_DBG_PORT_ENT_NUM)
+ pDfsSwParam->dfs_w_idx[id] = 0;
+ }
+ }
+ }
+ }
+
+ if (pRadarDetect->use_tasklet)
+ {
+ /* set hw_idx*/
+ pDfsSwParam->hw_idx[0] = pDfsSwParam->dfs_w_idx[0];
+ pDfsSwParam->hw_idx[1] = pDfsSwParam->dfs_w_idx[1];
+ pDfsSwParam->hw_idx[2] = pDfsSwParam->dfs_w_idx[2];
+ pDfsSwParam->hw_idx[3] = pDfsSwParam->dfs_w_idx[3];
+
+ /*dfs tasklet will call SWRadarCheck*/
+ schedule_dfs_task(pAd);
+ }
+ }
+}
+
+void schedule_dfs_task(PRTMP_ADAPTER pAd)
+{
+ POS_COOKIE pObj;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ if (pRadarDetect->DFSAPRestart == 1)
+ {
+ int i, j;
+
+ pDfsSwParam->dfs_w_counter += 10;
+ /* reset period table */
+ for (i = 0; i < pAd->chipCap.DfsEngineNum; i++)
+ {
+ for (j = 0; j < NEW_DFS_MPERIOD_ENT_NUM; j++)
+ {
+ pDfsSwParam->DFS_T[i][j].period = 0;
+ pDfsSwParam->DFS_T[i][j].idx = 0;
+ pDfsSwParam->DFS_T[i][j].idx2 = 0;
+ }
+ }
+
+ APStop(pAd);
+ APStartUp(pAd);
+ RTMP_BBP_IO_WRITE32(pAd, DFS_R0, (pRadarDetect->EnabledChMask << 16)); /* re-enable DFS engine */
+ //RTMP_DFS_IO_WRITE8(pAd, pRadarDetect->EnabledChMask, 1); /* re-enable DFS engine */
+ pRadarDetect->DFSAPRestart = 0;
+ }
+ else
+ {
+ /*s/w check radar event buffer*/
+ int idx;
+ if (pRadarDetect->radarDeclared == 0)
+ {
+ for (idx = 0; idx < 4; idx++)
+ {
+ if (SWRadarCheck(pAd, idx) == 1)
+ {
+ //radar signals found
+ pRadarDetect->radarDeclared = 1;
+ break;
+ }
+ }
+ }
+ }
+}
+#endif /* RTMP_MAC_USB */
+#endif /*CONFIG_AP_SUPPORT*/
+#endif /* DFS_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_info.c b/cleopatre/devkit/mt7601udrv/common/cmm_info.c
new file mode 100644
index 0000000000..4d69674a66
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_info.c
@@ -0,0 +1,6151 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ****************************************************************************
+
+ Module Name:
+ cmm_info.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ --------- ---------- ----------------------------------------------
+ */
+
+#include "rt_config.h"
+
+
+
+/*
+ ==========================================================================
+ Description:
+ Get Driver version.
+
+ Return:
+ ==========================================================================
+*/
+INT Set_DriverVersion_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ DBGPRINT(RT_DEBUG_TRACE, ("Driver version-%s\n", AP_DRIVER_VERSION));
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set Country Region.
+ This command will not work, if the field of CountryRegion in eeprom is programmed.
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_CountryRegion_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int retval;
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+ return -EOPNOTSUPP;
+#endif /* EXT_BUILD_CHANNEL_LIST */
+
+ retval = RT_CfgSetCountryRegion(pAd, arg, BAND_24G);
+ if (retval == FALSE)
+ return FALSE;
+
+ /* if set country region, driver needs to be reset*/
+ BuildChannelList(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegion_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegion));
+
+ return TRUE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Set Country Region for A band.
+ This command will not work, if the field of CountryRegion in eeprom is programmed.
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_CountryRegionABand_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int retval;
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+ return -EOPNOTSUPP;
+#endif /* EXT_BUILD_CHANNEL_LIST */
+
+ retval = RT_CfgSetCountryRegion(pAd, arg, BAND_5G);
+ if (retval == FALSE)
+ return FALSE;
+
+ /* if set country region, driver needs to be reset*/
+ BuildChannelList(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegionABand_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegionForABand));
+
+ return TRUE;
+}
+
+
+INT Set_Cmm_WirelessMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg,
+ IN BOOLEAN FlgIsDiffMbssModeUsed)
+{
+ INT success = TRUE;
+#ifdef CONFIG_AP_SUPPORT
+ UINT32 i = 0;
+#ifdef MBSS_SUPPORT
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ if (FlgIsDiffMbssModeUsed) {
+ LONG cfg_mode = simple_strtol(arg, 0, 10);
+
+ /* assign wireless mode for the BSS */
+ pAd->ApCfg.MBSSID[pObj->ioctl_if].PhyMode =
+ cfgmode_2_wmode((UCHAR)cfg_mode);
+
+ /*
+ If the band is different with other BSS, we will correct it in
+ RT_CfgSetMbssWirelessMode()
+ */
+ success = RT_CfgSetMbssWirelessMode(pAd, arg);
+ }
+ else
+#endif /* MBSS_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ success = RT_CfgSetWirelessMode(pAd, arg);
+
+ if (success)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* recover Wmm Capable for "each" BSS */
+ /* all phy mode of MBSS are the same */
+ for(i=0; i<pAd->ApCfg.BssidNum; i++)
+ {
+ pAd->ApCfg.MBSSID[i].bWmmCapable = \
+ pAd->ApCfg.MBSSID[i].bWmmCapableOrg;
+
+#ifdef MBSS_SUPPORT
+ /* In Same-MBSS Mode, all phy modes are the same */
+ if (FlgIsDiffMbssModeUsed == 0)
+ pAd->ApCfg.MBSSID[i].PhyMode = pAd->CommonCfg.PhyMode;
+#endif /* MBSS_SUPPORT */
+ }
+
+ RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef MBSS_SUPPORT
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_Cmm_WirelessMode_Proc::(=%d)\n", pAd->CommonCfg.PhyMode));
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_Cmm_WirelessMode_Proc::(BSS%d=%d)\n",
+ pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].PhyMode));
+
+ for(i=0; i<pAd->ApCfg.BssidNum; i++)
+ {
+ /*
+ When last mode is not 11B-only, new mode is 11B, we need to re-make
+ beacon frame content.
+
+ Because we put support rate/extend support rate element in
+ APMakeBssBeacon(), not APUpdateBeaconFrame().
+ */
+ APMakeBssBeacon(pAd, i);
+ }
+#endif /* MBSS_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_WirelessMode_Proc::parameters out of range\n"));
+ }
+
+ return success;
+}
+
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef MBSS_SUPPORT
+/*
+ ==========================================================================
+ Description:
+ Set Wireless Mode for MBSS
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_MBSS_WirelessMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ return Set_Cmm_WirelessMode_Proc(pAd, arg, 1);
+}
+#endif /* MBSS_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+/*
+ ==========================================================================
+ Description:
+ Set Wireless Mode
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_WirelessMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ return Set_Cmm_WirelessMode_Proc(pAd, arg, 0);
+}
+
+
+
+
+/*
+ ==========================================================================
+ Description:
+ Set Channel
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_Channel_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+#ifdef CONFIG_AP_SUPPORT
+ INT i;
+#endif /* CONFIG_AP_SUPPORT */
+ INT success = TRUE;
+ UCHAR Channel;
+
+ Channel = (UCHAR) simple_strtol(arg, 0, 10);
+
+ /* check if this channel is valid*/
+ if (ChannelSanity(pAd, Channel) == TRUE)
+ {
+ success = TRUE;
+ }
+ else
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ Channel = FirstChannel(pAd);
+ DBGPRINT(RT_DEBUG_WARN,("This channel is out of channel list, set as the first channel(%d) \n ", Channel));
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if ((WMODE_CAP_5G(pAd->CommonCfg.PhyMode))
+ && (pAd->CommonCfg.bIEEE80211H == TRUE))
+ {
+ for (i = 0; i < pAd->ChannelListNum; i++)
+ {
+ if (pAd->ChannelList[i].Channel == Channel)
+ {
+ if (pAd->ChannelList[i].RemainingTimeForUse > 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR: previous detection of a radar on this channel(Channel=%d)\n", Channel));
+ success = FALSE;
+ break;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_INFO, ("RemainingTimeForUse %d ,Channel %d\n",
+ pAd->ChannelList[i].RemainingTimeForUse, Channel));
+ }
+ }
+ }
+ }
+
+ if (success == TRUE)
+ {
+ pAd->CommonCfg.Channel = Channel;
+#ifdef DOT11_N_SUPPORT
+ N_ChannelCheck(pAd);
+#endif /* DOT11_N_SUPPORT */
+
+ if ((pAd->CommonCfg.Channel > 14 )
+ && (pAd->CommonCfg.bIEEE80211H == TRUE))
+ {
+ if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE)
+ {
+ APStop(pAd);
+ APStartUp(pAd);
+ }
+ else
+ {
+ NotifyChSwAnnToPeerAPs(pAd, ZERO_MAC_ADDR, pAd->CurrentAddress, 1, pAd->CommonCfg.Channel);
+ pAd->Dot11_H.RDMode = RD_SWITCHING_MODE;
+ pAd->Dot11_H.CSCount = 0;
+ }
+ }
+ else
+ {
+ APStop(pAd);
+ APStartUp(pAd);
+ }
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (success == TRUE)
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_Channel_Proc::(Channel=%d)\n", pAd->CommonCfg.Channel));
+
+ return success;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Set Short Slot Time Enable or Disable
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ShortSlot_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int retval;
+
+ retval = RT_CfgSetShortSlot(pAd, arg);
+ if (retval == TRUE)
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_ShortSlot_Proc::(ShortSlot=%d)\n", pAd->CommonCfg.bUseShortSlotTime));
+
+ return retval;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Set Tx power
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_TxPower_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ LONG TxPower;
+ INT success = FALSE;
+
+ TxPower = simple_strtol(arg, 0, 10);
+ if (TxPower <= 100)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ pAd->CommonCfg.TxPowerPercentage = TxPower;
+#endif /* CONFIG_AP_SUPPORT */
+
+ success = TRUE;
+ }
+ else
+ success = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPower_Proc::(TxPowerPercentage=%ld)\n", pAd->CommonCfg.TxPowerPercentage));
+
+ return success;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set 11B/11G Protection
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_BGProtection_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ switch (simple_strtol(arg, 0, 10))
+ {
+ case 0: /*AUTO*/
+ pAd->CommonCfg.UseBGProtection = 0;
+ break;
+ case 1: /*Always On*/
+ pAd->CommonCfg.UseBGProtection = 1;
+ break;
+ case 2: /*Always OFF*/
+ pAd->CommonCfg.UseBGProtection = 2;
+ break;
+ default: /*Invalid argument */
+ return FALSE;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ APUpdateCapabilityAndErpIe(pAd);
+#endif /* CONFIG_AP_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_BGProtection_Proc::(BGProtection=%ld)\n", pAd->CommonCfg.UseBGProtection));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set TxPreamble
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_TxPreamble_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ RT_802_11_PREAMBLE Preamble;
+
+ Preamble = (RT_802_11_PREAMBLE)simple_strtol(arg, 0, 10);
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ if (Preamble == Rt802_11PreambleAuto)
+ return FALSE;
+#endif /* CONFIG_AP_SUPPORT */
+
+ switch (Preamble)
+ {
+ case Rt802_11PreambleShort:
+ pAd->CommonCfg.TxPreamble = Preamble;
+ break;
+ case Rt802_11PreambleLong:
+ pAd->CommonCfg.TxPreamble = Preamble;
+ break;
+ default: /*Invalid argument */
+ return FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPreamble_Proc::(TxPreamble=%ld)\n", pAd->CommonCfg.TxPreamble));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set RTS Threshold
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_RTSThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ NDIS_802_11_RTS_THRESHOLD RtsThresh;
+
+ RtsThresh = simple_strtol(arg, 0, 10);
+
+ if((RtsThresh > 0) && (RtsThresh <= MAX_RTS_THRESHOLD))
+ pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh;
+ else
+ return FALSE; /*Invalid argument */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_RTSThreshold_Proc::(RTSThreshold=%d)\n", pAd->CommonCfg.RtsThreshold));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set Fragment Threshold
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_FragThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh;
+
+ FragThresh = simple_strtol(arg, 0, 10);
+
+ if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD)
+ {
+ /*Illegal FragThresh so we set it to default*/
+ pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;
+ }
+ else if (FragThresh % 2 == 1)
+ {
+ /*
+ The length of each fragment shall always be an even number of octets,
+ except for the last fragment of an MSDU or MMPDU, which may be either
+ an even or an odd number of octets.
+ */
+ pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1);
+ }
+ else
+ {
+ pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh;
+ }
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_FragThreshold_Proc::(FragThreshold=%d)\n", pAd->CommonCfg.FragmentThreshold));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set TxBurst
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_TxBurst_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ LONG TxBurst;
+
+ TxBurst = simple_strtol(arg, 0, 10);
+ if (TxBurst == 1)
+ pAd->CommonCfg.bEnableTxBurst = TRUE;
+ else if (TxBurst == 0)
+ pAd->CommonCfg.bEnableTxBurst = FALSE;
+ else
+ return FALSE; /*Invalid argument */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_TxBurst_Proc::(TxBurst=%d)\n", pAd->CommonCfg.bEnableTxBurst));
+
+ return TRUE;
+}
+
+
+
+
+#ifdef AGGREGATION_SUPPORT
+/*
+ ==========================================================================
+ Description:
+ Set TxBurst
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_PktAggregate_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ LONG aggre;
+
+ aggre = simple_strtol(arg, 0, 10);
+
+ if (aggre == 1)
+ pAd->CommonCfg.bAggregationCapable = TRUE;
+ else if (aggre == 0)
+ pAd->CommonCfg.bAggregationCapable = FALSE;
+ else
+ return FALSE; /*Invalid argument */
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef PIGGYBACK_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ pAd->CommonCfg.bPiggyBackCapable = pAd->CommonCfg.bAggregationCapable;
+ RTMPSetPiggyBack(pAd, pAd->CommonCfg.bPiggyBackCapable);
+ }
+#endif /* PIGGYBACK_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_PktAggregate_Proc::(AGGRE=%d)\n", pAd->CommonCfg.bAggregationCapable));
+
+ return TRUE;
+}
+#endif
+
+
+#ifdef INF_PPA_SUPPORT
+INT Set_INF_AMAZON_SE_PPA_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG aggre;
+ UINT status;
+
+ aggre = simple_strtol(arg, 0, 10);
+
+ if (aggre == 1)
+ {
+ if(pAd->PPAEnable==TRUE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("INF_AMAZON_SE_PPA already enabled \n"));
+ }
+ else
+ {
+ if (ppa_hook_directpath_register_dev_fn)
+ {
+ UINT32 g_if_id;
+
+ if (pAd->pDirectpathCb == NULL)
+ {
+/* pAd->pDirectpathCb = (PPA_DIRECTPATH_CB *) kmalloc (sizeof(PPA_DIRECTPATH_CB), GFP_ATOMIC);*/
+ os_alloc_mem(NULL, (UCHAR **)&(pAd->pDirectpathCb), sizeof(PPA_DIRECTPATH_CB));
+ DBGPRINT(RT_DEBUG_TRACE, ("Realloc memory for pDirectpathCb ??\n"));
+ }
+
+ /* register callback */
+ pAd->pDirectpathCb->rx_fn = ifx_ra_start_xmit;
+ pAd->pDirectpathCb->stop_tx_fn = NULL;
+ pAd->pDirectpathCb->start_tx_fn = NULL;
+
+ status = ppa_hook_directpath_register_dev_fn(&g_if_id, pAd->net_dev, pAd->pDirectpathCb, PPA_F_DIRECTPATH_REGISTER|PPA_F_DIRECTPATH_ETH_IF);
+
+ if(status==IFX_SUCCESS)
+ {
+ pAd->g_if_id=g_if_id;
+ DBGPRINT(RT_DEBUG_TRACE, ("register INF_AMAZON_SE_PPA success :ret:%d id:%d:%d\n",status,pAd->g_if_id,g_if_id));
+ pAd->PPAEnable=TRUE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("register INF_AMAZON_SE_PPA fail :ret:%d\n",status));
+ }
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("INF_AMAZON_SE_PPA enable fail : there is no INF_AMAZON_SE_PPA module . \n"));
+ }
+ }
+
+
+ }
+ else if (aggre == 0)
+ {
+ if(pAd->PPAEnable==FALSE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("INF_AMAZON_SE_PPA already disable \n"));
+ }
+ else
+ {
+ if (ppa_hook_directpath_register_dev_fn)
+ {
+ UINT32 g_if_id;
+ g_if_id=pAd->g_if_id;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("g_if_id=%d \n",pAd->g_if_id));
+ status=ppa_hook_directpath_register_dev_fn(&g_if_id, pAd->net_dev, NULL, 0/*PPA_F_DIRECTPATH_REGISTER*/);
+
+ if(status==1)
+ {
+ pAd->g_if_id=0;
+ DBGPRINT(RT_DEBUG_TRACE, ("unregister INF_AMAZON_SE_PPA success :ret:%d\n",status));
+ pAd->PPAEnable=FALSE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("unregister INF_AMAZON_SE_PPA fail :ret:%d\n",status));
+ }
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("INF_AMAZON_SE_PPA enable fail : there is no INF_AMAZON_SE_PPA module . \n"));
+ }
+ }
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Invalid argument %d \n",aggre));
+ return FALSE; /*Invalid argument */
+ }
+
+ return TRUE;
+
+}
+#endif /* INF_PPA_SUPPORT */
+
+
+/*
+ ==========================================================================
+ Description:
+ Set IEEE80211H.
+ This parameter is 1 when needs radar detection, otherwise 0
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_IEEE80211H_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ LONG ieee80211h;
+
+ ieee80211h = simple_strtol(arg, 0, 10);
+
+ if (ieee80211h == 1)
+ pAd->CommonCfg.bIEEE80211H = TRUE;
+ else if (ieee80211h == 0)
+ pAd->CommonCfg.bIEEE80211H = FALSE;
+ else
+ return FALSE; /*Invalid argument */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_IEEE80211H_Proc::(IEEE80211H=%d)\n", pAd->CommonCfg.bIEEE80211H));
+
+ return TRUE;
+}
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+/*
+ ==========================================================================
+ Description:
+ Set Country Code.
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ExtCountryCode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+
+ if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) == NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s can only be used when interface is down.\n", __FUNCTION__));
+ return TRUE;
+ }
+
+ if(strlen(arg) == 2)
+ {
+ NdisMoveMemory(pAd->CommonCfg.CountryCode, arg, 2);
+ pAd->CommonCfg.bCountryFlag = TRUE;
+ }
+ else
+ {
+ NdisZeroMemory(pAd->CommonCfg.CountryCode, 3);
+ pAd->CommonCfg.bCountryFlag = FALSE;
+ }
+
+ {
+ UCHAR CountryCode[3] = {0};
+ NdisMoveMemory(CountryCode, pAd->CommonCfg.CountryCode, 2);
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryCode_Proc::(bCountryFlag=%d, CountryCode=%s)\n",
+ pAd->CommonCfg.bCountryFlag,
+ CountryCode));
+ }
+ return TRUE;
+}
+/*
+ ==========================================================================
+ Description:
+ Set Ext DFS Type
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ExtDfsType_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR *pDfsType = &pAd->CommonCfg.DfsType;
+ if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) == NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s can only be used when interface is down.\n", __FUNCTION__));
+ return TRUE;
+ }
+
+ if (!strcmp(arg, "CE"))
+ *pDfsType = CE;
+ else if (!strcmp(arg, "FCC"))
+ *pDfsType = FCC;
+ else if (!strcmp(arg, "JAP"))
+ *pDfsType = JAP;
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("Unsupported DFS type:%s (Legal types are: CE, FCC, JAP)\n", arg));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Add new channel list
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ChannelListAdd_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ CH_DESP inChDesp;
+ PCH_REGION pChRegion = NULL;
+
+ if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) == NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s can only be used when interface is down.\n", __FUNCTION__));
+ return TRUE;
+ }
+
+ /* Get Channel Region (CountryCode)*/
+ {
+ INT loop = 0;
+
+ while (strcmp((PSTRING) ChRegion[loop].CountReg, "") != 0)
+ {
+ if (strncmp((PSTRING) ChRegion[loop].CountReg, pAd->CommonCfg.CountryCode, 2) == 0)
+ {
+ pChRegion = &ChRegion[loop];
+ break;
+ }
+ loop++;
+ }
+ if (pChRegion == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CountryCode is not configured or not valid\n"));
+ return TRUE;
+ }
+ }
+
+ /* Parsing the arg, IN:arg; OUT:inChRegion */
+ {
+ UCHAR strBuff[64], count = 0;
+ PUCHAR pStart, pEnd, tempIdx, tempBuff[5];
+
+ if (strlen(arg) <64)
+ NdisCopyMemory(strBuff, arg, strlen(arg));
+
+ if ((pStart = rtstrchr(strBuff, '[')) != NULL)
+ {
+ if ((pEnd = rtstrchr(pStart++, ']')) != NULL)
+ {
+ tempBuff[count++] = pStart;
+ for(tempIdx = pStart ;tempIdx != pEnd; tempIdx++)
+ {
+ if(*tempIdx == ',')
+ {
+ *tempIdx = '\0';
+ tempBuff[count++] = ++tempIdx;
+ }
+ }
+ *(pEnd) = '\0';
+
+ if (count != 5)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Input Error. Too more or too less parameters.\n"));
+ return TRUE;
+ }
+ else
+ {
+ inChDesp.FirstChannel = (UCHAR) simple_strtol(tempBuff[0], 0, 10);
+ inChDesp.NumOfCh = (UCHAR) simple_strtol(tempBuff[1], 0, 10);
+ inChDesp.MaxTxPwr = (UCHAR) simple_strtol(tempBuff[2], 0, 10);
+ inChDesp.Geography = (!strcmp(tempBuff[3], "BOTH") ? BOTH: (!strcmp(tempBuff[3], "IDOR") ? IDOR : ODOR));
+ inChDesp.DfsReq= (!strcmp(tempBuff[4], "TRUE") ? TRUE : FALSE);
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Missing End \"]\"\n"));
+ return TRUE;
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Invalid input format.\n", __FUNCTION__));
+ return TRUE;
+ }
+ }
+
+ /* Add entry to Channel List*/
+ {
+ UCHAR EntryIdx;
+ PCH_DESP pChDesp = NULL;
+ UCHAR CountryCode[3] = {0};
+ if (pAd->CommonCfg.pChDesp == NULL)
+ {
+ os_alloc_mem(pAd, &pAd->CommonCfg.pChDesp, MAX_PRECONFIG_DESP_ENTRY_SIZE*sizeof(CH_DESP));
+ pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp;
+ if (pChDesp)
+ {
+ for (EntryIdx= 0; pChRegion->pChDesp[EntryIdx].FirstChannel != 0; EntryIdx++)
+ {
+ if (EntryIdx == (MAX_PRECONFIG_DESP_ENTRY_SIZE-2)) /* Keep an NULL entry in the end of table*/
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Table is full.\n"));
+ return TRUE;
+ }
+ NdisCopyMemory(&pChDesp[EntryIdx], &pChRegion->pChDesp[EntryIdx], sizeof(CH_DESP));
+ }
+ /* Copy the NULL entry*/
+ NdisCopyMemory(&pChDesp[EntryIdx], &pChRegion->pChDesp[EntryIdx], sizeof(CH_DESP));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("os_alloc_mem failded.\n"));
+ return FALSE;
+ }
+ }
+ else
+ {
+ pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp;
+ for (EntryIdx= 0; pChDesp[EntryIdx].FirstChannel != 0; EntryIdx++)
+ {
+ if(EntryIdx == (MAX_PRECONFIG_DESP_ENTRY_SIZE-2)) /* Keep an NULL entry in the end of table*/
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Table is full.\n"));
+ return TRUE;
+ }
+ }
+ }
+ NdisMoveMemory(CountryCode, pAd->CommonCfg.CountryCode, 2);
+ DBGPRINT(RT_DEBUG_TRACE, ("Add channel lists {%u, %u, %u, %s, %s} to %s.\n",
+ inChDesp.FirstChannel,
+ inChDesp.NumOfCh,
+ inChDesp.MaxTxPwr,
+ (inChDesp.Geography == BOTH) ? "BOTH" : (inChDesp.Geography == IDOR) ? "IDOR" : "ODOR",
+ (inChDesp.DfsReq == TRUE) ? "TRUE" : "FALSE",
+ CountryCode));
+ NdisCopyMemory(&pChDesp[EntryIdx], &inChDesp, sizeof(CH_DESP));
+ pChDesp[++EntryIdx].FirstChannel = 0;
+ }
+ return TRUE;
+}
+
+INT Set_ChannelListShow_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PCH_REGION pChRegion = NULL;
+ UCHAR EntryIdx, CountryCode[3]={0};
+
+ /* Get Channel Region (CountryCode)*/
+ {
+ INT loop = 0;
+
+ while (strcmp((PSTRING) ChRegion[loop].CountReg, "") != 0)
+ {
+ if (strncmp((PSTRING) ChRegion[loop].CountReg, pAd->CommonCfg.CountryCode, 2) == 0)
+ {
+ pChRegion = &ChRegion[loop];
+ break;
+ }
+ loop++;
+ }
+ if (pChRegion == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CountryCode is not configured or not valid\n"));
+ return TRUE;
+ }
+ }
+
+ NdisMoveMemory(CountryCode, pAd->CommonCfg.CountryCode, 2);
+ if (pAd->CommonCfg.DfsType == MAX_RD_REGION)
+ pAd->CommonCfg.DfsType = pChRegion->DfsType;
+ DBGPRINT(RT_DEBUG_ERROR, ("=========================================\n"));
+ DBGPRINT(RT_DEBUG_ERROR, ("CountryCode:%s\n", CountryCode));
+ DBGPRINT(RT_DEBUG_ERROR, ("DfsType:%s\n",
+ (pAd->CommonCfg.DfsType == JAP) ? "JAP" :
+ ((pAd->CommonCfg.DfsType == FCC) ? "FCC" : "CE" )));
+
+ if (pAd->CommonCfg.pChDesp != NULL)
+ {
+ PCH_DESP pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp;
+ for (EntryIdx = 0; pChDesp[EntryIdx].FirstChannel != 0; EntryIdx++)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%u. {%3u, %2u, %2u, %s, %5s}.\n",
+ EntryIdx,
+ pChDesp[EntryIdx].FirstChannel,
+ pChDesp[EntryIdx].NumOfCh,
+ pChDesp[EntryIdx].MaxTxPwr,
+ (pChDesp[EntryIdx].Geography == BOTH) ? "BOTH" : (pChDesp[EntryIdx].Geography == IDOR) ? "IDOR" : "ODOR",
+ (pChDesp[EntryIdx].DfsReq == TRUE) ? "TRUE" : "FALSE"));
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Default channel list table:\n"));
+ for (EntryIdx = 0; pChRegion->pChDesp[EntryIdx].FirstChannel != 0; EntryIdx++)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%u. {%3u, %2u, %2u, %s, %5s}.\n",
+ EntryIdx,
+ pChRegion->pChDesp[EntryIdx].FirstChannel,
+ pChRegion->pChDesp[EntryIdx].NumOfCh,
+ pChRegion->pChDesp[EntryIdx].MaxTxPwr,
+ (pChRegion->pChDesp[EntryIdx].Geography == BOTH) ? "BOTH" : (pChRegion->pChDesp[EntryIdx].Geography == IDOR) ? "IDOR" : "ODOR",
+ (pChRegion->pChDesp[EntryIdx].DfsReq == TRUE) ? "TRUE" : "FALSE"));
+ }
+ }
+ DBGPRINT(RT_DEBUG_ERROR, ("=========================================\n"));
+ return TRUE;
+}
+
+INT Set_ChannelListDel_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR EntryIdx, TargetIdx, NumOfEntry;
+ PCH_REGION pChRegion = NULL;
+ PCH_DESP pChDesp = NULL;
+ TargetIdx = simple_strtol(arg, 0, 10);
+ if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) == NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s can only be used when interface is down.\n", __FUNCTION__));
+ return TRUE;
+ }
+
+ /* Get Channel Region (CountryCode)*/
+ {
+ INT loop = 0;
+ while (strcmp((PSTRING) ChRegion[loop].CountReg, "") != 0)
+ {
+ if (strncmp((PSTRING) ChRegion[loop].CountReg, pAd->CommonCfg.CountryCode, 2) == 0)
+ {
+ pChRegion = &ChRegion[loop];
+ break;
+ }
+ loop++;
+ }
+ if (pChRegion == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CountryCode is not configured or not valid\n"));
+ return TRUE;
+ }
+ }
+
+ if (pAd->CommonCfg.pChDesp == NULL)
+ {
+ os_alloc_mem(pAd, &pAd->CommonCfg.pChDesp, MAX_PRECONFIG_DESP_ENTRY_SIZE*sizeof(CH_DESP));
+ if (pAd->CommonCfg.pChDesp)
+ {
+ pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp;
+ for (EntryIdx= 0; pChRegion->pChDesp[EntryIdx].FirstChannel != 0; EntryIdx++)
+ {
+ if (EntryIdx == (MAX_PRECONFIG_DESP_ENTRY_SIZE-2)) /* Keep an NULL entry in the end of table*/
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Table is full.\n"));
+ return TRUE;
+ }
+ NdisCopyMemory(&pChDesp[EntryIdx], &pChRegion->pChDesp[EntryIdx], sizeof(CH_DESP));
+ }
+ /* Copy the NULL entry*/
+ NdisCopyMemory(&pChDesp[EntryIdx], &pChRegion->pChDesp[EntryIdx], sizeof(CH_DESP));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("os_alloc_mem failded.\n"));
+ return FALSE;
+ }
+ }
+ else
+ pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp;
+
+ if (!strcmp(arg, "default"))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Default table used.\n" ));
+ if (pAd->CommonCfg.pChDesp != NULL)
+ os_free_mem(NULL, pAd->CommonCfg.pChDesp);
+ pAd->CommonCfg.pChDesp = NULL;
+ pAd->CommonCfg.DfsType = MAX_RD_REGION;
+ }
+ else if (!strcmp(arg, "all"))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Remove all entries.\n" ));
+ for (EntryIdx = 0; EntryIdx < MAX_PRECONFIG_DESP_ENTRY_SIZE; EntryIdx++)
+ NdisZeroMemory(&pChDesp[EntryIdx], sizeof(CH_DESP));
+ }
+ else if (TargetIdx < (MAX_PRECONFIG_DESP_ENTRY_SIZE-1))
+ {
+ for (EntryIdx= 0; pChDesp[EntryIdx].FirstChannel != 0; EntryIdx++)
+ {
+ if(EntryIdx == (MAX_PRECONFIG_DESP_ENTRY_SIZE-2)) /* Keep an NULL entry in the end of table */
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Last entry should be NULL.\n"));
+ pChDesp[EntryIdx].FirstChannel = 0;
+ return TRUE;
+ }
+ }
+ NumOfEntry = EntryIdx;
+ if (TargetIdx >= NumOfEntry)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Out of table range.\n"));
+ return TRUE;
+ }
+ for (EntryIdx = TargetIdx; EntryIdx < NumOfEntry; EntryIdx++)
+ NdisCopyMemory(&pChDesp[EntryIdx], &pChDesp[EntryIdx+1], sizeof(CH_DESP));
+ NdisZeroMemory(&pChDesp[EntryIdx], sizeof(CH_DESP)); /*NULL entry*/
+ DBGPRINT(RT_DEBUG_TRACE, ("Entry %u deleted.\n", TargetIdx));
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("Entry not found.\n"));
+
+ return TRUE;
+}
+#endif /* EXT_BUILD_CHANNEL_LIST */
+
+#ifdef WSC_INCLUDED
+INT Set_WscGenPinCode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PWSC_CTRL pWscControl = NULL;
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+ UCHAR apidx = pObj->ioctl_if;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (pObj->ioctl_if_type == INT_APCLI)
+ {
+ pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl;
+ DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscGenPinCode_Proc:: This command is from apcli interface now.\n", apidx));
+ }
+ else
+#endif /* APCLI_SUPPORT */
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl;
+ DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscGenPinCode_Proc:: This command is from ra interface now.\n", apidx));
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+ if (pWscControl == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pWscControl == NULL!\n", __FUNCTION__));
+ return TRUE;
+ }
+
+ if (pWscControl->WscEnrollee4digitPinCode)
+ {
+ pWscControl->WscEnrolleePinCodeLen = 4;
+ pWscControl->WscEnrolleePinCode = WscRandomGen4digitPinCode(pAd);
+ }
+ else
+ {
+ pWscControl->WscEnrolleePinCodeLen = 8;
+ pWscControl->WscEnrolleePinCode = WscRandomGeneratePinCode(pAd, apidx);
+ }
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_WscGenPinCode_Proc:: Enrollee PinCode\t\t%08u\n", pWscControl->WscEnrolleePinCode));
+
+ return TRUE;
+}
+
+INT Set_WscVendorPinCode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PWSC_CTRL pWscControl = NULL;
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+ UCHAR apidx = pObj->ioctl_if;
+
+#ifdef CONFIG_AP_SUPPORT
+/* POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;*/
+/* UCHAR apidx = pObj->ioctl_if;*/
+
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (pObj->ioctl_if_type == INT_APCLI)
+ {
+ pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl;
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_WscVendorPinCode_Proc() for apcli(%d)\n", apidx));
+ }
+ else
+#endif /* APCLI_SUPPORT */
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl;
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_WscVendorPinCode_Proc() for ra%d!\n", apidx));
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+ if (!pWscControl)
+ return FALSE;
+ else
+ return RT_CfgSetWscPinCode(pAd, arg, pWscControl);
+}
+#endif /* WSC_INCLUDED */
+
+#ifdef DBG
+/*
+ ==========================================================================
+ Description:
+ For Debug information
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_Debug_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ DBGPRINT(RT_DEBUG_TRACE, ("==>%s()\n", __FUNCTION__));
+
+ if(simple_strtol(arg, 0, 10) <= RT_DEBUG_LOUD)
+ RTDebugLevel = simple_strtol(arg, 0, 10);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<==%s(RTDebugLevel = %ld)\n",
+ __FUNCTION__, RTDebugLevel));
+
+ return TRUE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ For DebugFunc information
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_DebugFunc_Proc(
+ IN RTMP_ADAPTER *pAd,
+ IN PSTRING arg)
+{
+ DBGPRINT_S(RT_DEBUG_TRACE, ("==>%s()\n", __FUNCTION__));
+ RTDebugFunc = simple_strtol(arg, 0, 10);
+ DBGPRINT_S(RT_DEBUG_TRACE, ("Set RTDebugFunc = 0x%x\n",__FUNCTION__, RTDebugFunc));
+
+ return TRUE;
+}
+#endif
+
+
+INT Show_DescInfo_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Reset statistics counter
+
+ Arguments:
+ pAd Pointer to our adapter
+ arg
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ResetStatCounter_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ /*UCHAR i;*/
+ /*MAC_TABLE_ENTRY *pEntry;*/
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==>Set_ResetStatCounter_Proc\n"));
+
+ /* add the most up-to-date h/w raw counters into software counters*/
+ NICUpdateRawCounters(pAd);
+
+ NdisZeroMemory(&pAd->WlanCounters, sizeof(COUNTER_802_11));
+ NdisZeroMemory(&pAd->Counters8023, sizeof(COUNTER_802_3));
+ NdisZeroMemory(&pAd->RalinkCounters, sizeof(COUNTER_RALINK));
+
+#ifdef CONFIG_AP_SUPPORT
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef TXBF_SUPPORT
+ if (pAd->chipCap.FlgHwTxBfCap)
+ {
+ int i;
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ NdisZeroMemory(&pAd->MacTab.Content[i].TxBFCounters, sizeof(pAd->MacTab.Content[i].TxBFCounters));
+ }
+#endif /* TXBF_SUPPORT */
+
+ return TRUE;
+}
+
+
+BOOLEAN RTMPCheckStrPrintAble(
+ IN CHAR *pInPutStr,
+ IN UCHAR strLen)
+{
+ UCHAR i=0;
+
+ for (i=0; i<strLen; i++)
+ {
+ if ((pInPutStr[i] < 0x20) ||
+ (pInPutStr[i] > 0x7E))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Remove WPA Key process
+
+ Arguments:
+ pAd Pointer to our adapter
+ pBuf Pointer to the where the key stored
+
+ Return Value:
+ NDIS_SUCCESS Add key successfully
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+
+#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_WPA_SUPPLICANT_SUPPORT)
+NDIS_STATUS RTMPWPARemoveKeyProc(
+ IN PRTMP_ADAPTER pAd,
+ IN PVOID pBuf)
+{
+ PNDIS_802_11_REMOVE_KEY pKey;
+ ULONG KeyIdx;
+ NDIS_STATUS Status = NDIS_STATUS_FAILURE;
+ BOOLEAN bTxKey; /* Set the key as transmit key*/
+ BOOLEAN bPairwise; /* Indicate the key is pairwise key*/
+ BOOLEAN bKeyRSC; /* indicate the receive SC set by KeyRSC value.*/
+ /* Otherwise, it will set by the NIC.*/
+ BOOLEAN bAuthenticator; /* indicate key is set by authenticator.*/
+ INT i;
+#ifdef APCLI_SUPPORT
+#ifdef APCLI_WPA_SUPPLICANT_SUPPORT
+ UCHAR ifIndex;
+ BOOLEAN apcliEn=FALSE;
+ INT idx, BssIdx;
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/
+#endif/*APCLI_SUPPORT*/
+ DBGPRINT(RT_DEBUG_TRACE,("---> RTMPWPARemoveKeyProc\n"));
+
+ pKey = (PNDIS_802_11_REMOVE_KEY) pBuf;
+ KeyIdx = pKey->KeyIndex & 0xff;
+ /* Bit 31 of Add-key, Tx Key*/
+ bTxKey = (pKey->KeyIndex & 0x80000000) ? TRUE : FALSE;
+ /* Bit 30 of Add-key PairwiseKey*/
+ bPairwise = (pKey->KeyIndex & 0x40000000) ? TRUE : FALSE;
+ /* Bit 29 of Add-key KeyRSC*/
+ bKeyRSC = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE;
+ /* Bit 28 of Add-key Authenticator*/
+ bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE;
+
+ /* 1. If bTx is TRUE, return failure information*/
+ if (bTxKey == TRUE)
+ return(NDIS_STATUS_INVALID_DATA);
+
+ /* 2. Check Pairwise Key*/
+ if (bPairwise)
+ {
+ /* a. If BSSID is broadcast, remove all pairwise keys.*/
+ /* b. If not broadcast, remove the pairwise specified by BSSID*/
+ for (i = 0; i < SHARE_KEY_NUM; i++)
+ {
+#ifdef APCLI_SUPPORT
+#ifdef APCLI_WPA_SUPPLICANT_SUPPORT
+ if (pObj->ioctl_if_type == INT_APCLI)
+ {
+ /*if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ifIndex].SharedKey[i].BssId, pKey->BSSID)) */
+ {
+ ifIndex = pObj->ioctl_if;
+ BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + ifIndex;
+ DBGPRINT(RT_DEBUG_TRACE,("APCLI RTMPWPARemoveKeyProc(KeyIdx=%d)\n", i));
+ pAd->ApCfg.ApCliTab[ifIndex].SharedKey[i].KeyLen = 0;
+ pAd->ApCfg.ApCliTab[ifIndex].SharedKey[i].CipherAlg = CIPHER_NONE;
+ AsicRemoveSharedKeyEntry(pAd, BssIdx, (UCHAR)i);
+ Status = NDIS_STATUS_SUCCESS;
+ break;
+ }
+ }
+ else
+#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/
+#endif/*APCLI_SUPPORT*/
+ {
+ }
+ }
+ }
+ /* 3. Group Key*/
+ else
+ {
+ /* a. If BSSID is broadcast, remove all group keys indexed*/
+ /* b. If BSSID matched, delete the group key indexed.*/
+ DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%ld)\n", KeyIdx));
+ pAd->SharedKey[BSS0][KeyIdx].KeyLen = 0;
+ pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE;
+ AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)KeyIdx);
+ Status = NDIS_STATUS_SUCCESS;
+ }
+
+ return (Status);
+}
+#endif /* defined(CONFIG_STA_SUPPORT) || defined(APCLI_WPA_SUPPLICANT_SUPPORT) */
+
+
+
+
+/*
+ ========================================================================
+ Routine Description:
+ Change NIC PHY mode. Re-association may be necessary
+
+ Arguments:
+ pAd - Pointer to our adapter
+ phymode -
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+VOID RTMPSetPhyMode(
+ IN RTMP_ADAPTER *pAd,
+ IN ULONG phymode)
+{
+ INT i;
+ /* the selected phymode must be supported by the RF IC encoded in E2PROM*/
+
+ pAd->CommonCfg.PhyMode = (UCHAR)phymode;
+
+ DBGPRINT(RT_DEBUG_TRACE,("RTMPSetPhyMode : PhyMode=%d, channel=%d \n", pAd->CommonCfg.PhyMode, pAd->CommonCfg.Channel));
+#ifdef EXT_BUILD_CHANNEL_LIST
+ BuildChannelListEx(pAd);
+#else
+ BuildChannelList(pAd);
+#endif /* EXT_BUILD_CHANNEL_LIST */
+
+ /* sanity check user setting*/
+ for (i = 0; i < pAd->ChannelListNum; i++)
+ {
+ if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel)
+ break;
+ }
+
+ if (i == pAd->ChannelListNum)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ if (pAd->CommonCfg.Channel != 0)
+ pAd->CommonCfg.Channel = FirstChannel(pAd);
+#endif /* CONFIG_AP_SUPPORT */
+ DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetPhyMode: channel is out of range, use first channel=%d \n", pAd->CommonCfg.Channel));
+ }
+
+ NdisZeroMemory(pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
+ NdisZeroMemory(pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
+ NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES);
+ switch (phymode) {
+ case (WMODE_B):
+ pAd->CommonCfg.SupRate[0] = 0x82; /* 1 mbps, in units of 0.5 Mbps, basic rate*/
+ pAd->CommonCfg.SupRate[1] = 0x84; /* 2 mbps, in units of 0.5 Mbps, basic rate*/
+ pAd->CommonCfg.SupRate[2] = 0x8B; /* 5.5 mbps, in units of 0.5 Mbps, basic rate*/
+ pAd->CommonCfg.SupRate[3] = 0x96; /* 11 mbps, in units of 0.5 Mbps, basic rate*/
+ pAd->CommonCfg.SupRateLen = 4;
+ pAd->CommonCfg.ExtRateLen = 0;
+ pAd->CommonCfg.DesireRate[0] = 2; /* 1 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[1] = 4; /* 2 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[2] = 11; /* 5.5 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[3] = 22; /* 11 mbps, in units of 0.5 Mbps*/
+ /*pAd->CommonCfg.HTPhyMode.field.MODE = MODE_CCK; This MODE is only FYI. not use*/
+ break;
+
+ /*
+ In current design, we will put supported/extended rate element in
+ beacon even we are 11n-only mode.
+ Or some 11n stations will not connect to us if we do not put
+ supported/extended rate element in beacon.
+ */
+ case (WMODE_G):
+ case (WMODE_B | WMODE_G):
+ case (WMODE_A | WMODE_B | WMODE_G):
+#ifdef DOT11_N_SUPPORT
+ case (WMODE_GN):
+ case (WMODE_A | WMODE_B | WMODE_G | WMODE_GN | WMODE_AN):
+ case (WMODE_B | WMODE_G | WMODE_GN):
+ case (WMODE_G | WMODE_GN):
+#endif /* DOT11_N_SUPPORT */
+ pAd->CommonCfg.SupRate[0] = 0x82; /* 1 mbps, in units of 0.5 Mbps, basic rate*/
+ pAd->CommonCfg.SupRate[1] = 0x84; /* 2 mbps, in units of 0.5 Mbps, basic rate*/
+ pAd->CommonCfg.SupRate[2] = 0x8B; /* 5.5 mbps, in units of 0.5 Mbps, basic rate*/
+ pAd->CommonCfg.SupRate[3] = 0x96; /* 11 mbps, in units of 0.5 Mbps, basic rate*/
+ pAd->CommonCfg.SupRate[4] = 0x12; /* 9 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.SupRate[5] = 0x24; /* 18 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.SupRate[6] = 0x48; /* 36 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.SupRateLen = 8;
+ pAd->CommonCfg.ExtRate[0] = 0x0C; /* 6 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.ExtRate[1] = 0x18; /* 12 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.ExtRate[2] = 0x30; /* 24 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.ExtRate[3] = 0x60; /* 48 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.ExtRateLen = 4;
+ pAd->CommonCfg.DesireRate[0] = 2; /* 1 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[1] = 4; /* 2 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[2] = 11; /* 5.5 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[3] = 22; /* 11 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[4] = 12; /* 6 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[5] = 18; /* 9 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[6] = 24; /* 12 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[7] = 36; /* 18 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[8] = 48; /* 24 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[9] = 72; /* 36 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[10] = 96; /* 48 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[11] = 108; /* 54 mbps, in units of 0.5 Mbps*/
+ break;
+
+ case (WMODE_A):
+#ifdef DOT11_N_SUPPORT
+ case (WMODE_A | WMODE_AN):
+ case (WMODE_A | WMODE_G | WMODE_GN | WMODE_AN):
+ case (WMODE_AN):
+#endif /* DOT11_N_SUPPORT */
+#ifdef DOT11_VHT_AC
+ case (WMODE_A | WMODE_AN | WMODE_AC):
+ case (WMODE_AN | WMODE_AC):
+#endif /* DOT11_VHT_AC */
+ pAd->CommonCfg.SupRate[0] = 0x8C; /* 6 mbps, in units of 0.5 Mbps, basic rate*/
+ pAd->CommonCfg.SupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.SupRate[2] = 0x98; /* 12 mbps, in units of 0.5 Mbps, basic rate*/
+ pAd->CommonCfg.SupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.SupRate[4] = 0xb0; /* 24 mbps, in units of 0.5 Mbps, basic rate*/
+ pAd->CommonCfg.SupRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.SupRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.SupRateLen = 8;
+ pAd->CommonCfg.ExtRateLen = 0;
+ pAd->CommonCfg.DesireRate[0] = 12; /* 6 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[1] = 18; /* 9 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[2] = 24; /* 12 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[3] = 36; /* 18 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[4] = 48; /* 24 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[5] = 72; /* 36 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[6] = 96; /* 48 mbps, in units of 0.5 Mbps*/
+ pAd->CommonCfg.DesireRate[7] = 108; /* 54 mbps, in units of 0.5 Mbps*/
+ /*pAd->CommonCfg.HTPhyMode.field.MODE = MODE_OFDM; This MODE is only FYI. not use*/
+ break;
+
+ default:
+ break;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ UINT apidx;
+
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ MlmeUpdateTxRates(pAd, FALSE, apidx);
+ }
+#ifdef WDS_SUPPORT
+ for (apidx = 0; apidx < MAX_WDS_ENTRY; apidx++)
+ {
+ MlmeUpdateTxRates(pAd, FALSE, apidx + MIN_NET_DEVICE_FOR_WDS);
+ }
+#endif /* WDS_SUPPORT */
+#ifdef APCLI_SUPPORT
+ for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++)
+ {
+ MlmeUpdateTxRates(pAd, FALSE, apidx + MIN_NET_DEVICE_FOR_APCLI);
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef DOT11_N_SUPPORT
+ SetCommonHT(pAd);
+#endif /* DOT11_N_SUPPORT */
+
+#ifdef DOT11_VHT_AC
+ SetCommonVHT(pAd);
+#endif /* DOT11_VHT_AC */
+}
+
+
+/*
+ ========================================================================
+ Description:
+ Add Client security information into ASIC WCID table and IVEIV table.
+ Return:
+ ========================================================================
+*/
+VOID RTMPAddWcidAttributeEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssIdx,
+ IN UCHAR KeyIdx,
+ IN UCHAR CipherAlg,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ UINT32 WCIDAttri = 0;
+ USHORT offset;
+ UCHAR IVEIV = 0;
+ USHORT Wcid = 0;
+#ifdef CONFIG_AP_SUPPORT
+ BOOLEAN IEEE8021X = FALSE;
+#endif /* CONFIG_AP_SUPPORT */
+
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (BssIdx >= MIN_NET_DEVICE_FOR_APCLI)
+ {
+ if (pEntry)
+ BssIdx -= MIN_NET_DEVICE_FOR_APCLI;
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("RTMPAddWcidAttributeEntry: AP-Client link doesn't need to set Group WCID Attribute. \n"));
+ return;
+ }
+ }
+ else
+#endif /* APCLI_SUPPORT */
+#ifdef WDS_SUPPORT
+ if (BssIdx >= MIN_NET_DEVICE_FOR_WDS)
+ {
+ if (pEntry)
+ BssIdx = BSS0;
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("RTMPAddWcidAttributeEntry: WDS link doesn't need to set Group WCID Attribute. \n"));
+ return;
+ }
+ }
+ else
+#endif /* WDS_SUPPORT */
+ {
+ if (BssIdx >= pAd->ApCfg.BssidNum)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for MBSSID link. \n", BssIdx));
+ return;
+ }
+ }
+
+ /* choose wcid number*/
+ if (pEntry)
+ Wcid = pEntry->Aid;
+ else
+ GET_GroupKey_WCID(pAd, Wcid, BssIdx);
+
+#ifdef DOT1X_SUPPORT
+ if ((BssIdx < pAd->ApCfg.BssidNum) && (BssIdx < MAX_MBSSID_NUM(pAd)) && (BssIdx < HW_BEACON_MAX_NUM))
+ IEEE8021X = pAd->ApCfg.MBSSID[BssIdx].IEEE8021X;
+#endif /* DOT1X_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+ /* Update WCID attribute table*/
+ offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /*
+ 1. Wds-links and Mesh-links always use Pair-wise key table.
+ 2. When the CipherAlg is TKIP, AES or the dynamic WEP is enabled,
+ it needs to set key into Pair-wise Key Table.
+ 3. The pair-wise key security mode is set NONE, it means as no security.
+ */
+ if (pEntry && (IS_ENTRY_WDS(pEntry) || IS_ENTRY_MESH(pEntry)))
+ WCIDAttri = (BssIdx<<4) | (CipherAlg<<1) | PAIRWISEKEYTABLE;
+ else if ((pEntry) &&
+ ((CipherAlg == CIPHER_TKIP) ||
+ (CipherAlg == CIPHER_AES) ||
+ (CipherAlg == CIPHER_NONE) ||
+ (IEEE8021X == TRUE)))
+ WCIDAttri = (BssIdx<<4) | (CipherAlg<<1) | PAIRWISEKEYTABLE;
+ else
+ WCIDAttri = (BssIdx<<4) | (CipherAlg<<1) | SHAREDKEYTABLE;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
+
+
+ /* Update IV/EIV table*/
+ offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE);
+
+ /* WPA mode*/
+ if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_AES))
+ {
+ /* Eiv bit on. keyid always is 0 for pairwise key */
+ IVEIV = (KeyIdx <<6) | 0x20;
+ }
+ else
+ {
+ /* WEP KeyIdx is default tx key. */
+ IVEIV = (KeyIdx << 6);
+ }
+
+ /* For key index and ext IV bit, so only need to update the position(offset+3).*/
+#ifdef RTMP_MAC_USB
+ RTUSBMultiWrite_OneByte(pAd, offset+3, &IVEIV);
+#endif /* RTMP_MAC_USB */
+
+ DBGPRINT(RT_DEBUG_TRACE,("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n",Wcid, KeyIdx, CipherName[CipherAlg]));
+ DBGPRINT(RT_DEBUG_TRACE,(" WCIDAttri = 0x%x \n", WCIDAttri));
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ Parse encryption type
+Arguments:
+ pAdapter Pointer to our adapter
+ wrq Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+PSTRING GetEncryptType(CHAR enc)
+{
+ if(enc == Ndis802_11WEPDisabled)
+ return "NONE";
+ if(enc == Ndis802_11WEPEnabled)
+ return "WEP";
+ if(enc == Ndis802_11Encryption2Enabled)
+ return "TKIP";
+ if(enc == Ndis802_11Encryption3Enabled)
+ return "AES";
+ if(enc == Ndis802_11Encryption4Enabled)
+ return "TKIPAES";
+#ifdef WAPI_SUPPORT
+ if(enc == Ndis802_11EncryptionSMS4Enabled)
+ return "SMS4";
+#endif /* WAPI_SUPPORT */
+ else
+ return "UNKNOW";
+}
+
+PSTRING GetAuthMode(CHAR auth)
+{
+ if(auth == Ndis802_11AuthModeOpen)
+ return "OPEN";
+ if(auth == Ndis802_11AuthModeShared)
+ return "SHARED";
+ if(auth == Ndis802_11AuthModeAutoSwitch)
+ return "AUTOWEP";
+ if(auth == Ndis802_11AuthModeWPA)
+ return "WPA";
+ if(auth == Ndis802_11AuthModeWPAPSK)
+ return "WPAPSK";
+ if(auth == Ndis802_11AuthModeWPANone)
+ return "WPANONE";
+ if(auth == Ndis802_11AuthModeWPA2)
+ return "WPA2";
+ if(auth == Ndis802_11AuthModeWPA2PSK)
+ return "WPA2PSK";
+ if(auth == Ndis802_11AuthModeWPA1WPA2)
+ return "WPA1WPA2";
+ if(auth == Ndis802_11AuthModeWPA1PSKWPA2PSK)
+ return "WPA1PSKWPA2PSK";
+#ifdef WAPI_SUPPORT
+ if(auth == Ndis802_11AuthModeWAICERT)
+ return "WAI-CERT";
+ if(auth == Ndis802_11AuthModeWAIPSK)
+ return "WAI-PSK";
+#endif /* WAPI_SUPPORT */
+
+ return "UNKNOW";
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Get site survey results
+ Arguments:
+ pAdapter Pointer to our adapter
+ wrq Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ Usage:
+ 1.) UI needs to wait 4 seconds after issue a site survey command
+ 2.) iwpriv ra0 get_site_survey
+ 3.) UI needs to prepare at least 4096bytes to get the results
+ ==========================================================================
+*/
+#define LINE_LEN (4+33+20+23+9+7+7+3) /* Channel+SSID+Bssid+Security+Signal+WiressMode+ExtCh+NetworkType*/
+
+VOID RTMPCommSiteSurveyData(
+ IN PSTRING msg,
+ IN PBSS_ENTRY pBss,
+ IN UINT32 MsgLen)
+{
+ INT Rssi = 0;
+ UINT Rssi_Quality = 0;
+ NDIS_802_11_NETWORK_TYPE wireless_mode;
+ CHAR Ssid[MAX_LEN_OF_SSID +1];
+ STRING SecurityStr[32] = {0};
+ NDIS_802_11_ENCRYPTION_STATUS ap_cipher = Ndis802_11EncryptionDisabled;
+ NDIS_802_11_AUTHENTICATION_MODE ap_auth_mode = Ndis802_11AuthModeOpen;
+
+ /*Channel*/
+ sprintf(msg+strlen(msg),"%-4d", pBss->Channel);
+
+
+ /*SSID*/
+ NdisZeroMemory(Ssid, (MAX_LEN_OF_SSID +1));
+ if (RTMPCheckStrPrintAble((PCHAR)pBss->Ssid, pBss->SsidLen))
+ NdisMoveMemory(Ssid, pBss->Ssid, pBss->SsidLen);
+ else
+ {
+ INT idx = 0;
+ sprintf(Ssid, "0x");
+ for (idx = 0; (idx < 14) && (idx < pBss->SsidLen); idx++)
+ sprintf(Ssid + 2 + (idx*2), "%02X", (UCHAR)pBss->Ssid[idx]);
+ }
+ sprintf(msg+strlen(msg),"%-33s", Ssid);
+
+ /*BSSID*/
+ sprintf(msg+strlen(msg),"%02x:%02x:%02x:%02x:%02x:%02x ",
+ pBss->Bssid[0],
+ pBss->Bssid[1],
+ pBss->Bssid[2],
+ pBss->Bssid[3],
+ pBss->Bssid[4],
+ pBss->Bssid[5]);
+
+ /*Security*/
+ RTMPZeroMemory(SecurityStr, 32);
+ if ((Ndis802_11AuthModeWPA <= pBss->AuthMode) &&
+ (pBss->AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK))
+ {
+ if (pBss->AuthMode == Ndis802_11AuthModeWPANone)
+ {
+ ap_auth_mode = pBss->AuthMode;
+ ap_cipher = pBss->WPA.PairCipher;
+ }
+ else if (pBss->AuthModeAux == Ndis802_11AuthModeOpen)
+ {
+ ap_auth_mode = pBss->AuthMode;
+ if ((ap_auth_mode == Ndis802_11AuthModeWPA) ||
+ (ap_auth_mode == Ndis802_11AuthModeWPAPSK))
+ {
+ if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
+ ap_cipher = pBss->WPA.PairCipher;
+ else
+ ap_cipher = Ndis802_11Encryption4Enabled;
+ }
+ else if ((ap_auth_mode == Ndis802_11AuthModeWPA2) ||
+ (ap_auth_mode == Ndis802_11AuthModeWPA2PSK))
+ {
+ if (pBss->WPA2.PairCipherAux == Ndis802_11WEPDisabled)
+ ap_cipher = pBss->WPA2.PairCipher;
+ else
+ ap_cipher = Ndis802_11Encryption4Enabled;
+ }
+ }
+ else if ((pBss->AuthMode == Ndis802_11AuthModeWPAPSK) ||
+ (pBss->AuthMode == Ndis802_11AuthModeWPA2PSK))
+ {
+ if ((pBss->AuthModeAux == Ndis802_11AuthModeWPAPSK) ||
+ (pBss->AuthModeAux == Ndis802_11AuthModeWPA2PSK))
+ ap_auth_mode = Ndis802_11AuthModeWPA1PSKWPA2PSK;
+ else
+ ap_auth_mode = pBss->AuthMode;
+
+ if (pBss->WPA.PairCipher != pBss->WPA2.PairCipher)
+ ap_cipher = Ndis802_11Encryption4Enabled;
+ else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) &&
+ (pBss->WPA.PairCipherAux != pBss->WPA2.PairCipherAux))
+ ap_cipher = Ndis802_11Encryption4Enabled;
+ else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) &&
+ (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) &&
+ (pBss->WPA.PairCipherAux != Ndis802_11WEPDisabled))
+ ap_cipher = Ndis802_11Encryption4Enabled;
+ else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) &&
+ (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) &&
+ (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled))
+ ap_cipher = pBss->WPA.PairCipher;
+ }
+ else if ((pBss->AuthMode == Ndis802_11AuthModeWPA) ||
+ (pBss->AuthMode == Ndis802_11AuthModeWPA2))
+ {
+ if ((pBss->AuthModeAux == Ndis802_11AuthModeWPA) ||
+ (pBss->AuthModeAux == Ndis802_11AuthModeWPA2))
+ ap_auth_mode = Ndis802_11AuthModeWPA1WPA2;
+ else
+ ap_auth_mode = pBss->AuthMode;
+
+ if (pBss->WPA.PairCipher != pBss->WPA2.PairCipher)
+ ap_cipher = Ndis802_11Encryption4Enabled;
+ else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) &&
+ (pBss->WPA.PairCipherAux != pBss->WPA2.PairCipherAux))
+ ap_cipher = Ndis802_11Encryption4Enabled;
+ else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) &&
+ (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) &&
+ (pBss->WPA.PairCipherAux != Ndis802_11WEPDisabled))
+ ap_cipher = Ndis802_11Encryption4Enabled;
+ else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) &&
+ (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) &&
+ (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled))
+ ap_cipher = pBss->WPA.PairCipher;
+ }
+
+ sprintf(SecurityStr, "%s/%s", GetAuthMode((CHAR)ap_auth_mode), GetEncryptType((CHAR)ap_cipher));
+ }
+ else
+ {
+ ap_auth_mode = pBss->AuthMode;
+ ap_cipher = pBss->WepStatus;
+ if (ap_cipher == Ndis802_11WEPDisabled)
+ sprintf(SecurityStr, "NONE");
+ else if (ap_cipher == Ndis802_11WEPEnabled)
+ sprintf(SecurityStr, "WEP");
+ else
+ sprintf(SecurityStr, "%s/%s", GetAuthMode((CHAR)ap_auth_mode), GetEncryptType((CHAR)ap_cipher));
+ }
+
+ sprintf(msg+strlen(msg), "%-23s", SecurityStr);
+
+ /* Rssi*/
+ Rssi = (INT)pBss->Rssi;
+ if (Rssi >= -50)
+ Rssi_Quality = 100;
+ else if (Rssi >= -80) /* between -50 ~ -80dbm*/
+ Rssi_Quality = (UINT)(24 + ((Rssi + 80) * 26)/10);
+ else if (Rssi >= -90) /* between -80 ~ -90dbm*/
+ Rssi_Quality = (UINT)(((Rssi + 90) * 26)/10);
+ else /* < -84 dbm*/
+ Rssi_Quality = 0;
+ sprintf(msg+strlen(msg),"%-9d", Rssi_Quality);
+
+ /* Wireless Mode*/
+ wireless_mode = NetworkTypeInUseSanity(pBss);
+ if (wireless_mode == Ndis802_11FH ||
+ wireless_mode == Ndis802_11DS)
+ sprintf(msg+strlen(msg),"%-7s", "11b");
+ else if (wireless_mode == Ndis802_11OFDM5)
+ sprintf(msg+strlen(msg),"%-7s", "11a");
+ else if (wireless_mode == Ndis802_11OFDM5_N)
+ sprintf(msg+strlen(msg),"%-7s", "11a/n");
+ else if (wireless_mode == Ndis802_11OFDM24)
+ sprintf(msg+strlen(msg),"%-7s", "11b/g");
+ else if (wireless_mode == Ndis802_11OFDM24_N)
+ sprintf(msg+strlen(msg),"%-7s", "11b/g/n");
+ else
+ sprintf(msg+strlen(msg),"%-7s", "unknow");
+
+ /* Ext Channel*/
+ if (pBss->AddHtInfoLen > 0)
+ {
+ if (pBss->AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE)
+ sprintf(msg+strlen(msg),"%-7s", " ABOVE");
+ else if (pBss->AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW)
+ sprintf(msg+strlen(msg),"%-7s", " BELOW");
+ else
+ sprintf(msg+strlen(msg),"%-7s", " NONE");
+ }
+ else
+ {
+ sprintf(msg+strlen(msg),"%-7s", " NONE");
+ }
+
+ /*Network Type */
+ if (pBss->BssType == BSS_ADHOC)
+ sprintf(msg+strlen(msg),"%-3s", " Ad");
+ else
+ sprintf(msg+strlen(msg),"%-3s", " In");
+
+ sprintf(msg+strlen(msg),"\n");
+
+ return;
+}
+
+#if defined (AP_SCAN_SUPPORT) || defined (CONFIG_STA_SUPPORT)
+VOID RTMPIoctlGetSiteSurvey(
+ IN PRTMP_ADAPTER pAdapter,
+ IN RTMP_IOCTL_INPUT_STRUCT *wrq)
+{
+ PSTRING msg;
+ INT i=0;
+ INT WaitCnt;
+ INT Status=0;
+ INT max_len = LINE_LEN;
+ PBSS_ENTRY pBss;
+ UINT32 TotalLen, BufLen = IW_SCAN_MAX_DATA;
+
+
+ TotalLen = sizeof(CHAR)*((MAX_LEN_OF_BSS_TABLE)*max_len) + 100;
+
+ if (wrq->u.data.length == 0)
+ BufLen = IW_SCAN_MAX_DATA;
+ else
+ BufLen = wrq->u.data.length;
+
+ os_alloc_mem(NULL, (PUCHAR *)&msg, TotalLen);
+
+ if (msg == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - msg memory alloc fail.\n"));
+ return;
+ }
+
+ memset(msg, 0 , TotalLen);
+ sprintf(msg,"%s","\n");
+
+ sprintf(msg+strlen(msg),"%-4s%-33s%-20s%-23s%-9s%-7s%-7s%-3s\n",
+ "Ch", "SSID", "BSSID", "Security", "Siganl(%)", "W-Mode", " ExtCH"," NT");
+
+#ifdef WSC_INCLUDED
+ sprintf(msg+strlen(msg)-1,"%-4s%-5s\n", " WPS", " DPID");
+#endif /* WSC_INCLUDED */
+
+
+ WaitCnt = 0;
+
+ while ((ScanRunning(pAdapter) == TRUE) && (WaitCnt++ < 200))
+ OS_WAIT(500);
+
+ for(i=0; i<pAdapter->ScanTab.BssNr ;i++)
+ {
+ pBss = &pAdapter->ScanTab.BssEntry[i];
+
+ if( pBss->Channel==0)
+ break;
+
+ if((strlen(msg)+100 ) >= BufLen)
+ break;
+
+
+ RTMPCommSiteSurveyData(msg, pBss, TotalLen);
+
+#ifdef WSC_INCLUDED
+ /*WPS*/
+ if (pBss->WpsAP & 0x01)
+ sprintf(msg+strlen(msg)-1,"%-4s", " YES");
+ else
+ sprintf(msg+strlen(msg)-1,"%-4s", " NO");
+
+ if (pBss->WscDPIDFromWpsAP == DEV_PASS_ID_PIN)
+ sprintf(msg+strlen(msg),"%-5s\n", " PIN");
+ else if (pBss->WscDPIDFromWpsAP == DEV_PASS_ID_PBC)
+ sprintf(msg+strlen(msg),"%-5s\n", " PBC");
+ else
+ sprintf(msg+strlen(msg),"%-5s\n", " ");
+#endif /* WSC_INCLUDED */
+
+ }
+
+ wrq->u.data.length = strlen(msg);
+ Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - wrq->u.data.length = %d\n", wrq->u.data.length));
+ os_free_mem(NULL, (PUCHAR)msg);
+}
+#endif
+
+
+
+
+#define MAC_LINE_LEN (1+14+4+4+4+4+10+10+10+6+6) /* "\n"+Addr+aid+psm+datatime+rxbyte+txbyte+current tx rate+last tx rate+"\n" */
+VOID RTMPIoctlGetMacTable(
+ IN PRTMP_ADAPTER pAd,
+ IN RTMP_IOCTL_INPUT_STRUCT *wrq)
+{
+ INT i;
+/* RT_802_11_MAC_TABLE MacTab;*/
+ RT_802_11_MAC_TABLE *pMacTab = NULL;
+ RT_802_11_MAC_ENTRY *pDst;
+ MAC_TABLE_ENTRY *pEntry;
+ char *msg;
+
+ /* allocate memory */
+ os_alloc_mem(NULL, (UCHAR **)&pMacTab, sizeof(RT_802_11_MAC_TABLE));
+ if (pMacTab == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ return;
+ }
+
+ NdisZeroMemory(pMacTab, sizeof(RT_802_11_MAC_TABLE));
+ pMacTab->Num = 0;
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ pEntry = &(pAd->MacTab.Content[i]);
+
+ if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC))
+ {
+ pDst = &pMacTab->Entry[pMacTab->Num];
+
+
+ pDst->ApIdx = (UCHAR)pEntry->apidx;
+ COPY_MAC_ADDR(pDst->Addr, &pEntry->Addr);
+ pDst->Aid = (UCHAR)pEntry->Aid;
+ pDst->Psm = pEntry->PsMode;
+#ifdef DOT11_N_SUPPORT
+ pDst->MimoPs = pEntry->MmpsMode;
+#endif /* DOT11_N_SUPPORT */
+
+ /* Fill in RSSI per entry*/
+ pDst->AvgRssi0 = pEntry->RssiSample.AvgRssi0;
+ pDst->AvgRssi1 = pEntry->RssiSample.AvgRssi1;
+ pDst->AvgRssi2 = pEntry->RssiSample.AvgRssi2;
+
+ /* the connected time per entry*/
+ pDst->ConnectedTime = pEntry->StaConnectTime;
+ pDst->TxRate.word = pEntry->HTPhyMode.word;
+
+
+ pMacTab->Num += 1;
+ }
+ }
+
+ wrq->u.data.length = sizeof(RT_802_11_MAC_TABLE);
+ if (copy_to_user(wrq->u.data.pointer, pMacTab, wrq->u.data.length))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__));
+ }
+
+
+/* msg = kmalloc(sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN), MEM_ALLOC_FLAG);*/
+ os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN));
+ if (msg == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__));
+ goto LabelOK;
+ }
+ memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN );
+ sprintf(msg,"%s","\n");
+ sprintf(msg+strlen(msg),"%-14s%-4s%-4s%-4s%-4s%-6s%-6s%-10s%-10s%-10s\n",
+ "MAC", "AP", "AID", "PSM", "AUTH", "CTxR", "LTxR","LDT", "RxB", "TxB");
+
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i];
+
+ if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC))
+ {
+ if((strlen(msg)+MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN) )
+ break;
+ sprintf(msg+strlen(msg),"%02x%02x%02x%02x%02x%02x ",
+ pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+ pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]);
+ sprintf(msg+strlen(msg),"%-4d", (int)pEntry->apidx);
+ sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid);
+ sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode);
+ sprintf(msg+strlen(msg),"%-4d", (int)pEntry->AuthState);
+ sprintf(msg+strlen(msg),"%-6d",RateIdToMbps[pAd->MacTab.Content[i].CurrTxRate]);
+ sprintf(msg+strlen(msg),"%-6d",0/*RateIdToMbps[pAd->MacTab.Content[i].HTPhyMode.word]*/); /* ToDo*/
+ sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.LastDataPacketTime*/); /* ToDo*/
+ sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalRxByteCount*/); /* ToDo*/
+ sprintf(msg+strlen(msg),"%-10d\n",0/*pAd->MacTab.Content[i].HSCounter.TotalTxByteCount*/); /* ToDo*/
+
+ }
+ }
+ /* for compatible with old API just do the printk to console*/
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s", msg));
+/* kfree(msg);*/
+ os_free_mem(NULL, msg);
+
+LabelOK:
+ if (pMacTab != NULL)
+ os_free_mem(NULL, pMacTab);
+}
+
+#ifdef INF_AR9
+#ifdef AR9_MAPI_SUPPORT
+#ifdef CONFIG_AP_SUPPORT
+VOID RTMPAR9IoctlGetMacTable(
+ IN PRTMP_ADAPTER pAd,
+ IN RTMP_IOCTL_INPUT_STRUCT *wrq)
+{
+ INT i;
+ char *msg;
+
+/* msg = kmalloc(sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN), MEM_ALLOC_FLAG);*/
+ os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN));
+ if (msg == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__));
+ return;
+ }
+ memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN );
+ sprintf(msg,"%s","\n");
+ sprintf(msg+strlen(msg),"%-14s%-4s%-4s%-4s%-4s%-6s%-6s%-10s%-10s%-10s\n",
+ "MAC", "AP", "AID", "PSM", "AUTH", "CTxR", "LTxR","LDT", "RxB", "TxB");
+
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i];
+ if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC))
+ {
+ if((strlen(msg)+MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN) )
+ break;
+ sprintf(msg+strlen(msg),"%02x%02x%02x%02x%02x%02x ",
+ pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+ pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]);
+ sprintf(msg+strlen(msg),"%-4d", (int)pEntry->apidx);
+ sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid);
+ sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode);
+ sprintf(msg+strlen(msg),"%-4d", (int)pEntry->AuthState);
+ sprintf(msg+strlen(msg),"%-6d",RateIdToMbps[pAd->MacTab.Content[i].CurrTxRate]);
+ sprintf(msg+strlen(msg),"%-6d",0/*RateIdToMbps[pAd->MacTab.Content[i].HTPhyMode.word]*/); /* ToDo*/
+ sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.LastDataPacketTime*/); /* ToDo*/
+ sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalRxByteCount*/); /* ToDo*/
+ sprintf(msg+strlen(msg),"%-10d\n",0/*pAd->MacTab.Content[i].HSCounter.TotalTxByteCount*/); /* ToDo*/
+
+ }
+ }
+ /* for compatible with old API just do the printk to console*/
+ wrq->u.data.length = strlen(msg);
+ if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length))
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("%s", msg));
+ }
+
+/* kfree(msg);*/
+ os_free_mem(NULL, msg);
+}
+
+VOID RTMPIoctlGetSTAT2(
+ IN PRTMP_ADAPTER pAd,
+ IN RTMP_IOCTL_INPUT_STRUCT *wrq)
+{
+ char *msg;
+ PMULTISSID_STRUCT pMbss;
+ INT apidx;
+
+
+/* msg = kmalloc(sizeof(CHAR)*(pAd->ApCfg.BssidNum*(14*128)), MEM_ALLOC_FLAG);*/
+ os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(pAd->ApCfg.BssidNum*(14*128)));
+ if (msg == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__));
+ return;
+ }
+ memset(msg, 0 ,pAd->ApCfg.BssidNum*(14*128));
+ sprintf(msg,"%s","\n");
+
+ for (apidx=0; apidx<pAd->ApCfg.BssidNum; apidx++)
+ {
+ pMbss=&pAd->ApCfg.MBSSID[apidx];
+
+ sprintf(msg+strlen(msg),"ra%d\n",apidx);
+ sprintf(msg+strlen(msg),"bytesTx = %ld\n",(pMbss->TransmittedByteCount));
+ sprintf(msg+strlen(msg),"bytesRx = %ld\n",(pMbss->ReceivedByteCount));
+ sprintf(msg+strlen(msg),"pktsTx = %ld\n",pMbss->TxCount);
+ sprintf(msg+strlen(msg),"pktsRx = %ld\n",pMbss->RxCount);
+ sprintf(msg+strlen(msg),"errorsTx = %ld\n",pMbss->TxErrorCount);
+ sprintf(msg+strlen(msg),"errorsRx = %ld\n",pMbss->RxErrorCount);
+ sprintf(msg+strlen(msg),"discardPktsTx = %ld\n",pMbss->TxDropCount);
+ sprintf(msg+strlen(msg),"discardPktsRx = %ld\n",pMbss->RxDropCount);
+ sprintf(msg+strlen(msg),"ucPktsTx = %ld\n",pMbss->ucPktsTx);
+ sprintf(msg+strlen(msg),"ucPktsRx = %ld\n",pMbss->ucPktsRx);
+ sprintf(msg+strlen(msg),"mcPktsTx = %ld\n",pMbss->mcPktsTx);
+ sprintf(msg+strlen(msg),"mcPktsRx = %ld\n",pMbss->mcPktsRx);
+ sprintf(msg+strlen(msg),"bcPktsTx = %ld\n",pMbss->bcPktsTx);
+ sprintf(msg+strlen(msg),"bcPktsRx = %ld\n",pMbss->bcPktsRx);
+
+ }
+
+ wrq->u.data.length = strlen(msg);
+ if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length))
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("%s", msg));
+ }
+
+/* kfree(msg);*/
+ os_free_mem(NULL, msg);
+}
+
+
+VOID RTMPIoctlGetRadioDynInfo(
+ IN PRTMP_ADAPTER pAd,
+ IN RTMP_IOCTL_INPUT_STRUCT *wrq)
+{
+ char *msg;
+ PMULTISSID_STRUCT pMbss;
+ INT status,bandwidth,ShortGI;
+
+
+/* msg = kmalloc(sizeof(CHAR)*(4096), MEM_ALLOC_FLAG);*/
+ os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(4096));
+ if (msg == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__));
+ return;
+ }
+ memset(msg, 0 ,4096);
+ sprintf(msg,"%s","\n");
+
+
+ pMbss=&pAd->ApCfg.MBSSID[0];
+ if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
+ status = 0;
+ else
+ status = 1;
+
+ if(pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)
+ bandwidth = 1;
+ else
+ bandwidth = 0;
+
+ if(pAd->CommonCfg.RegTransmitSetting.field.ShortGI == GI_800)
+ ShortGI = 1;
+ else
+ ShortGI = 0;
+
+
+ sprintf(msg+strlen(msg),"status = %d\n",status);
+ sprintf(msg+strlen(msg),"channelsInUse = %d\n",pAd->ChannelListNum);
+ sprintf(msg+strlen(msg),"channel = %d\n",pAd->CommonCfg.Channel);
+ sprintf(msg+strlen(msg),"chanWidth = %d\n",bandwidth);
+ sprintf(msg+strlen(msg),"guardIntvl = %d\n",ShortGI);
+ sprintf(msg+strlen(msg),"MCS = %d\n",pMbss->DesiredTransmitSetting.field.MCS);
+
+ wrq->u.data.length = strlen(msg);
+
+ if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length))
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("%s", msg));
+ }
+
+/* kfree(msg);*/
+ os_free_mem(NULL, msg);
+}
+#endif/*CONFIG_AP_SUPPORT*/
+#endif/*AR9_MAPI_SUPPORT*/
+#endif/* INF_AR9 */
+
+#ifdef DOT11_N_SUPPORT
+INT Set_BASetup_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR mac[6], tid;
+ PSTRING token;
+ STRING sepValue[] = ":", DASH = '-';
+ INT i;
+ MAC_TABLE_ENTRY *pEntry;
+
+/*
+ The BASetup inupt string format should be xx:xx:xx:xx:xx:xx-d,
+ =>The six 2 digit hex-decimal number previous are the Mac address,
+ =>The seventh decimal number is the tid value.
+*/
+ /*DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg));*/
+
+ if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.*/
+ return FALSE;
+
+ token = strchr(arg, DASH);
+ if ((token != NULL) && (strlen(token)>1))
+ {
+ tid = (UCHAR) simple_strtol((token+1), 0, 10);
+ /* tid is 0 ~ 7; Or kernel will crash in BAOriSessionSetUp() */
+ if (tid > (NUM_OF_TID-1))
+ return FALSE;
+
+ *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-%02x\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], tid));
+
+ pEntry = MacTableLookup(pAd, (PUCHAR) mac);
+
+ if (pEntry) {
+ DBGPRINT(RT_DEBUG_OFF, ("\nSetup BA Session: Tid = %d\n", tid));
+ BAOriSessionSetUp(pAd, pEntry, tid, 0, 100, TRUE);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+INT Set_BADecline_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG bBADecline;
+
+ bBADecline = simple_strtol(arg, 0, 10);
+
+ if (bBADecline == 0)
+ {
+ pAd->CommonCfg.bBADecline = FALSE;
+ }
+ else if (bBADecline == 1)
+ {
+ pAd->CommonCfg.bBADecline = TRUE;
+ }
+ else
+ {
+ return FALSE; /*Invalid argument*/
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_BADecline_Proc::(BADecline=%d)\n", pAd->CommonCfg.bBADecline));
+
+ return TRUE;
+}
+
+INT Set_BAOriTearDown_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR mac[6], tid;
+ PSTRING token;
+ STRING sepValue[] = ":", DASH = '-';
+ INT i;
+ MAC_TABLE_ENTRY *pEntry;
+
+ /*DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg));*/
+/*
+ The BAOriTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d,
+ =>The six 2 digit hex-decimal number previous are the Mac address,
+ =>The seventh decimal number is the tid value.
+*/
+ if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.*/
+ return FALSE;
+
+ token = strchr(arg, DASH);
+ if ((token != NULL) && (strlen(token)>1))
+ {
+ tid = simple_strtol((token+1), 0, 10);
+ /* tid will be 0 ~ 7; Or kernel will crash in BAOriSessionTearDown() */
+ if (tid > (NUM_OF_TID-1))
+ return FALSE;
+
+ *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-%02x",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], tid));
+
+ pEntry = MacTableLookup(pAd, (PUCHAR) mac);
+
+ if (pEntry) {
+ DBGPRINT(RT_DEBUG_OFF, ("\nTear down Ori BA Session: Tid = %d\n", tid));
+ BAOriSessionTearDown(pAd, pEntry->Aid, tid, FALSE, TRUE);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+INT Set_BARecTearDown_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR mac[6], tid;
+ PSTRING token;
+ STRING sepValue[] = ":", DASH = '-';
+ INT i;
+ MAC_TABLE_ENTRY *pEntry;
+
+ /*DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg));*/
+/*
+ The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d,
+ =>The six 2 digit hex-decimal number previous are the Mac address,
+ =>The seventh decimal number is the tid value.
+*/
+ if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.*/
+ return FALSE;
+
+ token = strchr(arg, DASH);
+ if ((token != NULL) && (strlen(token)>1))
+ {
+ tid = simple_strtol((token+1), 0, 10);
+ /* tid will be 0 ~ 7; Or kernel will crash in BARecSessionTearDown() */
+ if (tid > (NUM_OF_TID-1))
+ return FALSE;
+
+ *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-%02x",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], tid));
+
+ pEntry = MacTableLookup(pAd, (PUCHAR) mac);
+
+ if (pEntry) {
+ DBGPRINT(RT_DEBUG_OFF, ("\nTear down Rec BA Session: Tid = %d\n", tid));
+ BARecSessionTearDown(pAd, pEntry->Aid, tid, FALSE);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+INT Set_HtBw_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG HtBw;
+
+ HtBw = simple_strtol(arg, 0, 10);
+
+ if (HtBw == BW_40)
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
+ else if (HtBw == BW_20)
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ else
+ return FALSE; /*Invalid argument */
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBw_Proc::(HtBw=%d)\n", pAd->CommonCfg.RegTransmitSetting.field.BW));
+
+ return TRUE;
+}
+
+
+INT Set_HtMcs_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG HtMcs, Mcs_tmp, ValidMcs = 15;
+#ifdef CONFIG_AP_SUPPORT
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef DOT11N_SS3_SUPPORT
+ if (pAd->CommonCfg.TxStream >= 3)
+ ValidMcs = 23;
+#endif /* DOT11N_SS3_SUPPORT */
+
+ Mcs_tmp = simple_strtol(arg, 0, 10);
+
+ if (Mcs_tmp <= ValidMcs || Mcs_tmp == 32)
+ HtMcs = Mcs_tmp;
+ else
+ HtMcs = MCS_AUTO;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredTransmitSetting.field.MCS = HtMcs;
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(HtMcs=%d) for ra%d\n",
+ pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredTransmitSetting.field.MCS, pObj->ioctl_if));
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ SetCommonHT(pAd);
+
+ return TRUE;
+}
+
+INT Set_HtGi_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG HtGi;
+
+ HtGi = simple_strtol(arg, 0, 10);
+
+ if ( HtGi == GI_400)
+ pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400;
+ else if ( HtGi == GI_800 )
+ pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800;
+ else
+ return FALSE; /* Invalid argument */
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtGi_Proc::(ShortGI=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.ShortGI));
+
+ return TRUE;
+}
+
+
+INT Set_HtTxBASize_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR Size;
+
+ Size = simple_strtol(arg, 0, 10);
+
+ if (Size <=0 || Size >=64)
+ {
+ Size = 8;
+ }
+ pAd->CommonCfg.TxBASize = Size-1;
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_HtTxBASize ::(TxBASize= %d)\n", Size));
+
+ return TRUE;
+}
+
+INT Set_HtDisallowTKIP_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value == 1)
+ {
+ pAd->CommonCfg.HT_DisallowTKIP = TRUE;
+ }
+ else
+ {
+ pAd->CommonCfg.HT_DisallowTKIP = FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtDisallowTKIP_Proc ::%s\n",
+ (pAd->CommonCfg.HT_DisallowTKIP == TRUE) ? "enabled" : "disabled"));
+
+ return TRUE;
+}
+
+INT Set_HtOpMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value == HTMODE_GF)
+ pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF;
+ else if ( Value == HTMODE_MM )
+ pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM;
+ else
+ return FALSE; /*Invalid argument */
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtOpMode_Proc::(HtOpMode=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.HTMODE));
+
+ return TRUE;
+
+}
+
+INT Set_HtStbc_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value == STBC_USE)
+ pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE;
+ else if ( Value == STBC_NONE )
+ pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE;
+ else
+ return FALSE; /*Invalid argument */
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_Stbc_Proc::(HtStbc=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.STBC));
+
+ return TRUE;
+}
+
+INT Set_HtHtc_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->HTCEnable = FALSE;
+ else if ( Value ==1 )
+ pAd->HTCEnable = TRUE;
+ else
+ return FALSE; /*Invalid argument */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtHtc_Proc::(HtHtc=%d)\n",pAd->HTCEnable));
+
+ return TRUE;
+}
+
+INT Set_HtExtcha_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value == 0)
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+ else if ( Value ==1 )
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+ else
+ return FALSE; /*Invalid argument */
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtExtcha_Proc::(HtExtcha=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.EXTCHA));
+
+ return TRUE;
+}
+
+INT Set_HtMpduDensity_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value <=7)
+ pAd->CommonCfg.BACapability.field.MpduDensity = Value;
+ else
+ pAd->CommonCfg.BACapability.field.MpduDensity = 4;
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMpduDensity_Proc::(HtMpduDensity=%d)\n",pAd->CommonCfg.BACapability.field.MpduDensity));
+
+ return TRUE;
+}
+
+INT Set_HtBaWinSize_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+#ifdef CONFIG_AP_SUPPORT
+ /* Intel IOT*/
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ Value = 64;
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (Value >=1 && Value <= 64)
+ {
+ pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value;
+ pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value;
+ }
+ else
+ {
+ pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64;
+ pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64;
+ }
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBaWinSize_Proc::(HtBaWinSize=%d)\n",pAd->CommonCfg.BACapability.field.RxBAWinLimit));
+
+ return TRUE;
+}
+
+INT Set_HtRdg_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value == 0)
+ pAd->CommonCfg.bRdg = FALSE;
+ else if ( Value ==1 )
+ {
+ pAd->HTCEnable = TRUE;
+ pAd->CommonCfg.bRdg = TRUE;
+ }
+ else
+ return FALSE; /*Invalid argument*/
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtRdg_Proc::(HtRdg=%d)\n",pAd->CommonCfg.bRdg));
+
+ return TRUE;
+}
+
+INT Set_HtLinkAdapt_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->bLinkAdapt = FALSE;
+ else if ( Value ==1 )
+ {
+ pAd->HTCEnable = TRUE;
+ pAd->bLinkAdapt = TRUE;
+ }
+ else
+ return FALSE; /*Invalid argument*/
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtLinkAdapt_Proc::(HtLinkAdapt=%d)\n",pAd->bLinkAdapt));
+
+ return TRUE;
+}
+
+INT Set_HtAmsdu_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE;
+ else if ( Value == 1 )
+ pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE;
+ else
+ return FALSE; /*Invalid argument*/
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAmsdu_Proc::(HtAmsdu=%d)\n",pAd->CommonCfg.BACapability.field.AmsduEnable));
+
+ return TRUE;
+}
+
+INT Set_HtAutoBa_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.BACapability.field.AutoBA = FALSE;
+ pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE;
+ }
+ else if (Value == 1)
+ {
+ pAd->CommonCfg.BACapability.field.AutoBA = TRUE;
+ pAd->CommonCfg.BACapability.field.Policy = IMMED_BA;
+ }
+ else
+ return FALSE; /*Invalid argument*/
+
+ pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA;
+ pAd->CommonCfg.REGBACapability.field.Policy = pAd->CommonCfg.BACapability.field.Policy;
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAutoBa_Proc::(HtAutoBa=%d)\n",pAd->CommonCfg.BACapability.field.AutoBA));
+
+ return TRUE;
+
+}
+
+INT Set_HtProtect_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->CommonCfg.bHTProtect = FALSE;
+ else if (Value == 1)
+ pAd->CommonCfg.bHTProtect = TRUE;
+ else
+ return FALSE; /*Invalid argument*/
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtProtect_Proc::(HtProtect=%d)\n",pAd->CommonCfg.bHTProtect));
+
+ return TRUE;
+}
+
+INT Set_SendPSMPAction_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR mac[6], mode;
+ PSTRING token;
+ STRING sepValue[] = ":", DASH = '-';
+ INT i;
+ MAC_TABLE_ENTRY *pEntry;
+
+ /*DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg));*/
+/*
+ The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d,
+ =>The six 2 digit hex-decimal number previous are the Mac address,
+ =>The seventh decimal number is the mode value.
+*/
+ if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and mode value in decimal format.*/
+ return FALSE;
+
+ token = strchr(arg, DASH);
+ if ((token != NULL) && (strlen(token)>1))
+ {
+ mode = simple_strtol((token+1), 0, 10);
+ if (mode > MMPS_ENABLE)
+ return FALSE;
+
+ *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-%02x",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], mode));
+
+ pEntry = MacTableLookup(pAd, mac);
+
+ if (pEntry) {
+ DBGPRINT(RT_DEBUG_OFF, ("\nSendPSMPAction MIPS mode = %d\n", mode));
+ SendPSMPAction(pAd, pEntry->Aid, mode);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+
+}
+
+INT Set_HtMIMOPSmode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value <=3)
+ pAd->CommonCfg.BACapability.field.MMPSmode = Value;
+ else
+ pAd->CommonCfg.BACapability.field.MMPSmode = 3;
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMIMOPSmode_Proc::(MIMOPS mode=%d)\n",pAd->CommonCfg.BACapability.field.MMPSmode));
+
+ return TRUE;
+}
+
+#ifdef CONFIG_AP_SUPPORT
+/*
+ ==========================================================================
+ Description:
+ Set Tx Stream number
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_HtTxStream_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if ((Value <= 3) && (Value >= 1) && (Value <= pAd->Antenna.field.TxPath)) /* 3*3*/
+ pAd->CommonCfg.TxStream = Value;
+ else
+ pAd->CommonCfg.TxStream = pAd->Antenna.field.TxPath;
+
+ if ((pAd->MACVersion < RALINK_2883_VERSION) &&
+ (pAd->CommonCfg.TxStream > 2))
+ {
+ pAd->CommonCfg.TxStream = 2; /* only 2 TX streams for RT2860 series*/
+ }
+
+ SetCommonHT(pAd);
+
+ APStop(pAd);
+ APStartUp(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtTxStream_Proc::(Tx Stream=%d)\n",pAd->CommonCfg.TxStream));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set Rx Stream number
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_HtRxStream_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if ((Value <= 3) && (Value >= 1) && (Value <= pAd->Antenna.field.RxPath))
+ pAd->CommonCfg.RxStream = Value;
+ else
+ pAd->CommonCfg.RxStream = pAd->Antenna.field.RxPath;
+
+ if ((pAd->MACVersion < RALINK_2883_VERSION) &&
+ (pAd->CommonCfg.RxStream > 2)) /* 3*3*/
+ {
+ pAd->CommonCfg.RxStream = 2; /* only 2 RX streams for RT2860 series*/
+ }
+
+ SetCommonHT(pAd);
+
+ APStop(pAd);
+ APStartUp(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtRxStream_Proc::(Rx Stream=%d)\n",pAd->CommonCfg.RxStream));
+
+ return TRUE;
+}
+
+#ifdef DOT11_N_SUPPORT
+#ifdef GREENAP_SUPPORT
+INT Set_GreenAP_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ {
+ pAd->ApCfg.bGreenAPActive=FALSE;
+ pAd->ApCfg.bGreenAPEnable = FALSE;
+ }
+ else if (Value == 1)
+ pAd->ApCfg.bGreenAPEnable = TRUE;
+ else
+ return FALSE; /*Invalid argument*/
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_GreenAP_Proc::(bGreenAPEnable=%d)\n",pAd->ApCfg.bGreenAPEnable));
+
+ return TRUE;
+}
+#endif /* GREENAP_SUPPORT */
+#endif /* DOT11_N_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+INT Set_ForceShortGI_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->WIFItestbed.bShortGI = FALSE;
+ else if (Value == 1)
+ pAd->WIFItestbed.bShortGI = TRUE;
+ else
+ return FALSE; /*Invalid argument*/
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceShortGI_Proc::(ForceShortGI=%d)\n", pAd->WIFItestbed.bShortGI));
+
+ return TRUE;
+}
+
+
+
+INT Set_ForceGF_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->WIFItestbed.bGreenField = FALSE;
+ else if (Value == 1)
+ pAd->WIFItestbed.bGreenField = TRUE;
+ else
+ return FALSE; /*Invalid argument*/
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceGF_Proc::(ForceGF=%d)\n", pAd->WIFItestbed.bGreenField));
+
+ return TRUE;
+}
+
+INT Set_HtMimoPs_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->CommonCfg.bMIMOPSEnable = FALSE;
+ else if (Value == 1)
+ pAd->CommonCfg.bMIMOPSEnable = TRUE;
+ else
+ return FALSE; /*Invalid argument*/
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMimoPs_Proc::(HtMimoPs=%d)\n",pAd->CommonCfg.bMIMOPSEnable));
+
+ return TRUE;
+}
+
+
+#ifdef DOT11N_DRAFT3
+INT Set_HT_BssCoex_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING pParam)
+{
+ UCHAR bBssCoexEnable = simple_strtol(pParam, 0, 10);
+
+ pAd->CommonCfg.bBssCoexEnable = ((bBssCoexEnable == 1) ? TRUE: FALSE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set bBssCoexEnable=%d!\n", pAd->CommonCfg.bBssCoexEnable));
+
+ return TRUE;
+}
+
+
+INT Set_HT_BssCoexApCntThr_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING pParam)
+{
+ pAd->CommonCfg.BssCoexApCntThr = simple_strtol(pParam, 0, 10);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set BssCoexApCntThr=%d!\n", pAd->CommonCfg.BssCoexApCntThr));
+
+ return TRUE;
+}
+#endif /* DOT11N_DRAFT3 */
+
+#endif /* DOT11_N_SUPPORT */
+
+
+#ifdef DOT11_VHT_AC
+INT Set_VhtBw_Proc(
+ IN RTMP_ADAPTER *pAd,
+ IN PSTRING arg)
+{
+ ULONG vht_cw;
+ UCHAR cent_ch;
+ vht_cw = simple_strtol(arg, 0, 10);
+
+
+ if (vht_cw == VHT_BW_80)
+ pAd->CommonCfg.vht_bw = VHT_BW_80;
+ else
+ pAd->CommonCfg.vht_bw = VHT_BW_2040;
+
+#ifdef DOT11_VHT_AC
+ if (!WMODE_CAP_AC(pAd->CommonCfg.PhyMode))
+ goto direct_done;
+
+ SetCommonHT(pAd);
+ if(pAd->CommonCfg.BBPCurrentBW == BW_80)
+ cent_ch = pAd->CommonCfg.vht_cent_ch;
+ else
+ cent_ch = pAd->CommonCfg.CentralChannel;
+
+ AsicSwitchChannel(pAd, cent_ch, FALSE);
+ AsicLockChannel(pAd, cent_ch);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BW_%s, PrimaryChannel(%d), %s CentralChannel = %d, apply it immediately\n",
+ (pAd->CommonCfg.BBPCurrentBW == BW_80 ? "80":
+ (pAd->CommonCfg.BBPCurrentBW == BW_40 ? "40" :
+ "20")),
+ pAd->CommonCfg.Channel,
+ (pAd->CommonCfg.BBPCurrentBW == BW_80 ? "VHT" : "HT"), cent_ch));
+
+direct_done:
+#endif /* DOT11_VHT_AC */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_VhtBw_Proc::(VHT_BW=%d)\n", pAd->CommonCfg.vht_bw));
+
+ return TRUE;
+}
+
+
+INT Set_VhtStbc_Proc(
+ IN RTMP_ADAPTER *pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value == STBC_USE)
+ pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE;
+ else if ( Value == STBC_NONE )
+ pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE;
+ else
+ return FALSE; /*Invalid argument */
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_Stbc_Proc::(HtStbc=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.STBC));
+
+ return TRUE;
+}
+#endif /* DOT11_VHT_AC */
+
+
+
+INT Set_FixedTxMode_Proc(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+#ifdef CONFIG_AP_SUPPORT
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+#endif /* CONFIG_AP_SUPPORT */
+ INT fix_tx_mode = RT_CfgSetFixedTxPhyMode(arg);
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode;
+#endif /* CONFIG_AP_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():(FixedTxMode=%d)\n",
+ __FUNCTION__, fix_tx_mode));
+
+ return TRUE;
+}
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+INT Set_OpMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+#ifdef RTMP_MAC_USB
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
+#endif /* RTMP_MAC_USB */
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Can not switch operate mode on interface up !! \n"));
+ return FALSE;
+ }
+
+ if (Value == 0)
+ pAd->OpMode = OPMODE_STA;
+ else if (Value == 1)
+ pAd->OpMode = OPMODE_AP;
+ else
+ return FALSE; /*Invalid argument*/
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_OpMode_Proc::(OpMode=%s)\n", pAd->OpMode == 1 ? "AP Mode" : "STA Mode"));
+
+ return TRUE;
+}
+#endif /* CONFIG_APSTA_MIXED_SUPPORT */
+
+
+#ifdef DBG_CTRL_SUPPORT
+#ifdef INCLUDE_DEBUG_QUEUE
+/* ---------------------- DEBUG QUEUE ------------------------*/
+
+#define DBQ_LENGTH 512
+#define DBQ_DATA_LENGTH 8
+
+/* Define to include TX and RX HT Control field in log */
+/* #define DBQ_INCLUDE_HTC */
+
+typedef
+struct {
+ UCHAR type; /* type of data*/
+ ULONG timestamp; /* sec/usec timestamp from gettimeofday*/
+ UCHAR data[DBQ_DATA_LENGTH]; /* data*/
+} DBQUEUE_ENTRY;
+
+/* Type field definitions */
+#define DBQ_TYPE_EMPTY 0
+#define DBQ_TYPE_TXWI 0x70 /* TXWI*/
+#define DBQ_TYPE_TXHDR 0x72 /* TX Header*/
+#define DBQ_TYPE_TXFIFO 0x73 /* TX Stat FIFO*/
+#define DBQ_TYPE_RXWI 0x78 /* RXWI uses 0x78 to 0x7A for 5 longs*/
+#define DBQ_TYPE_RXHDR 0x7B /* RX Header*/
+#define DBQ_TYPE_TXQHTC 0x7c /* RX Qos+HT Control field*/
+#define DBQ_TYPE_RXQHTC 0x7d /* RX Qos+HT Control field */
+#define DBQ_TYPE_RALOG 0x7e /* RA Log */
+
+#define DBQ_INIT_SIG 0x4442484E /* 'DBIN' - dbqInit initialized flag*/
+#define DBQ_ENA_SIG 0x4442454E /* 'DBEN' - dbqEnable enabled flag*/
+
+static DBQUEUE_ENTRY dbQueue[DBQ_LENGTH];
+static ULONG dbqTail=0;
+static ULONG dbqEnable=0;
+static ULONG dbqInit=0;
+
+/* dbQueueInit - initialize Debug Queue variables and clear the queue*/
+void dbQueueInit(void)
+{
+ int i;
+
+ for (i=0; i<DBQ_LENGTH; i++)
+ dbQueue[i].type = DBQ_TYPE_EMPTY;
+ dbqTail = 0;
+ dbqInit = DBQ_INIT_SIG;
+}
+
+/* dbQueueEnqueue - enqueue data*/
+void dbQueueEnqueue(UCHAR type, UCHAR *data)
+{
+ DBQUEUE_ENTRY *oldTail;
+ struct timeval tval;
+
+ if (dbqEnable!=DBQ_ENA_SIG || data==NULL)
+ return;
+
+ if (dbqInit!=DBQ_INIT_SIG || dbqTail>=DBQ_LENGTH)
+ dbQueueInit();
+
+ oldTail = &dbQueue[dbqTail];
+
+ /* Advance tail and mark as empty*/
+ if (dbqTail >= DBQ_LENGTH-1)
+ dbqTail = 0;
+ else
+ dbqTail++;
+ dbQueue[dbqTail].type = DBQ_TYPE_EMPTY;
+
+ /* Enqueue data*/
+ oldTail->type = type;
+ do_gettimeofday(&tval);
+ oldTail->timestamp = tval.tv_sec*1000000L + tval.tv_usec;
+ memcpy(oldTail->data, data, DBQ_DATA_LENGTH);
+}
+
+void dbQueueEnqueueTxFrame(UCHAR *pTxWI, UCHAR *pHeader_802_11)
+{
+ dbQueueEnqueue(DBQ_TYPE_TXWI, pTxWI);
+
+ /* 802.11 Header */
+ if (pHeader_802_11 != NULL) {
+ dbQueueEnqueue(DBQ_TYPE_TXHDR, pHeader_802_11);
+#ifdef DBQ_INCLUDE_HTC
+ /* Qos+HT Control field */
+ if ((pHeader_802_11[0] & 0x08) && (pHeader_802_11[1] & 0x80))
+ dbQueueEnqueue(DBQ_TYPE_TXQHTC, pHeader_802_11+24);
+#endif /* DBQ_INCLUDE_HTC */
+ }
+}
+
+void dbQueueEnqueueRxFrame(UCHAR *pRxWI, UCHAR *pHeader_802_11, ULONG flags)
+{
+ /* Ignore Beacons if disabled */
+ if ((flags & DBF_DBQ_NO_BCN) && (pHeader_802_11[0] & 0xfc)==0x80)
+ return;
+
+ /* RXWI */
+ dbQueueEnqueue(DBQ_TYPE_RXWI, pRxWI);
+ if (flags & DBF_DBQ_RXWI_FULL) {
+ dbQueueEnqueue(DBQ_TYPE_RXWI+1, pRxWI+8);
+ dbQueueEnqueue(DBQ_TYPE_RXWI+2, pRxWI+16);
+ }
+
+ /* 802.11 Header */
+ dbQueueEnqueue(DBQ_TYPE_RXHDR, (UCHAR *)pHeader_802_11);
+
+#ifdef DBQ_INCLUDE_HTC
+ /* Qos+HT Control field */
+ if ((pHeader_802_11[0] & 0x08) &&
+ (pHeader_802_11[1] & 0x80))
+ dbQueueEnqueue(DBQ_TYPE_RXQHTC, pHeader_802_11+24);
+#endif /* DBQ_INCLUDE_HTC */
+}
+
+
+/* dbQueueDisplayPhy - Display PHY rate */
+static void dbQueueDisplayPHY(USHORT phyRate)
+{
+ static CHAR *mode[4] = {" C", "oM","mM", "gM"};
+
+ DBGPRINT(RT_DEBUG_OFF, ("%2s%02d %c%c%c%c",
+ //(phyRate>>8) & 0xFF, phyRate & 0xFF,
+ mode[(phyRate>>14) & 0x3], // Mode: c, o, m, g
+ phyRate & 0x7F, // MCS
+ (phyRate & 0x0100)? 'S': 'L', // Guard Int: S or L
+ (phyRate & 0x0080)? '4': '2', // BW: 4 or 2
+ (phyRate & 0x0200)? 'S': 's', // STBC: S or s
+ (phyRate & 0x2000)? 'I': ((phyRate & 0x800)? 'E': '_') // Beamforming: E or I or _
+ ) );
+}
+
+/* dbQueueDump - dump contents of debug queue*/
+static void dbQueueDump(
+ IN PRTMP_ADAPTER pAd,
+ BOOLEAN decode)
+{
+ DBQUEUE_ENTRY *oldTail;
+ int i, origMCS, succMCS;
+ ULONG lastTimestamp=0;
+ BOOLEAN showTimestamp;
+ USHORT phyRate;
+
+ if (dbqInit!=DBQ_INIT_SIG || dbqTail>=DBQ_LENGTH)
+ return;
+
+ oldTail = &dbQueue[dbqTail];
+
+ for (i=0; i<DBQ_LENGTH; i++) {
+ if (++oldTail >= &dbQueue[DBQ_LENGTH])
+ oldTail = dbQueue;
+
+ /* Skip empty entries*/
+ if (oldTail->type == DBQ_TYPE_EMPTY)
+ continue;
+
+ showTimestamp = FALSE;
+
+ switch (oldTail->type) {
+ case 0x70: /* TXWI - 2 longs, MSB to LSB */
+ case 0x78: /* RXWI - 2 longs, MSB to LSB */
+ showTimestamp = TRUE;
+
+ if (decode && oldTail->type==0x70) {
+ DBGPRINT(RT_DEBUG_OFF, ("\nTxWI ") );
+ dbQueueDisplayPHY(oldTail->data[3]*256 + oldTail->data[2]);
+ DBGPRINT(RT_DEBUG_OFF, ("%c s=%03X %02X %s-",
+ (oldTail->data[0] & 0x10)? 'A': '_', // AMPDU
+ (oldTail->data[7]*256 + oldTail->data[6]) & 0xFFF, // Size
+ oldTail->data[5], // WCID
+ (oldTail->data[4] & 0x01)? "AK": "NA" )); // ACK/NACK
+ }
+ else if (decode && oldTail->type==0x78) {
+ DBGPRINT(RT_DEBUG_OFF, ("\nRxWI ") );
+ dbQueueDisplayPHY(oldTail->data[7]*256 + oldTail->data[6]);
+ DBGPRINT(RT_DEBUG_OFF, (" s=%03X %02X %02X%01X-",
+ (oldTail->data[3]*256 + oldTail->data[2]) & 0xFFF, // Size
+ oldTail->data[0], // WCID
+ oldTail->data[5], oldTail->data[4]>>4 )); // Seq Number
+ }
+ else
+ DBGPRINT(RT_DEBUG_OFF, ("\n%cxWI %02X%02X %02X%02X-%02X%02X %02X%02X----",
+ oldTail->type==0x70? 'T': 'R',
+ oldTail->data[3], oldTail->data[2], oldTail->data[1], oldTail->data[0],
+ oldTail->data[7], oldTail->data[6], oldTail->data[5], oldTail->data[4]) );
+ break;
+
+ case 0x79: /* RXWI - next 2 longs, MSB to LSB */
+ if (decode) {
+ DBGPRINT(RT_DEBUG_OFF, ("Rx2 %2d %2d %2d S:%d %d %d ",
+ ConvertToRssi(pAd, (CHAR)oldTail->data[0], RSSI_0),
+ ConvertToRssi(pAd, (CHAR)oldTail->data[1], RSSI_1),
+ ConvertToRssi(pAd, (CHAR)oldTail->data[2], RSSI_2),
+ (oldTail->data[4]*3 + 8)/16,
+ (oldTail->data[5]*3 + 8)/16,
+ (oldTail->data[6]*3 + 8)/16) );
+ }
+ else
+ DBGPRINT(RT_DEBUG_OFF, ("Rx2 %02X%02X %02X%02X-%02X%02X %02X%02X ",
+ oldTail->data[3], oldTail->data[2], oldTail->data[1], oldTail->data[0],
+ oldTail->data[7], oldTail->data[6], oldTail->data[5], oldTail->data[4]) );
+ break;
+
+
+ case 0x7c: /* TX HTC+QoS, 6 bytes, MSB to LSB */
+ case 0x7d: /* RX HTC+QoS, 6 bytes, MSB to LSB */
+ DBGPRINT(RT_DEBUG_OFF, ("%cxHTC H:%02X%02X%02X%02X Q:%02X%02X ",
+ oldTail->type==0x7c? 'T': 'R',
+ oldTail->data[5], oldTail->data[4], oldTail->data[3], oldTail->data[2],
+ oldTail->data[1], oldTail->data[0]) );
+ break;
+
+ case 0x72: /* Tx 802.11 header, MSB to LSB, translate type/subtype*/
+ case 0x7b: /* Rx*/
+ {
+ UCHAR tCode;
+ struct _typeTableEntry {
+ UCHAR code; /* Type/subtype*/
+ CHAR str[4];
+ } *pTab;
+ static struct _typeTableEntry typeTable[] = {
+ {0x00, "mARq"}, {0x01, "mARp"}, {0x02, "mRRq"}, {0x03, "mRRp"},
+ {0x04, "mPRq"}, {0x05, "mPRp"}, {0x08, "mBcn"}, {0x09, "mATI"},
+ {0x0a, "mDis"}, {0x0b, "mAut"}, {0x0c, "mDAu"}, {0x0d, "mAct"},
+ {0x0e, "mANA"},
+ {0x17, "cCWr"}, {0x18, "cBAR"}, {0x19, "cBAc"}, {0x1a, "cPSP"},
+ {0x1b, "cRTS"}, {0x1c, "cCTS"}, {0x1d, "cACK"}, {0x1e, "cCFE"},
+ {0x1f, "cCEA"},
+ {0x20, "dDat"}, {0x21, "dDCA"}, {0x22, "dDCP"}, {0x23, "dDAP"},
+ {0x24, "dNul"}, {0x25, "dCFA"}, {0x26, "dCFP"}, {0x27, "dCAP"},
+ {0x28, "dQDa"}, {0x29, "dQCA"}, {0x2a, "dQCP"}, {0x2b, "dQAP"},
+ {0x2c, "dQNu"}, {0x2e, "dQNP"}, {0x2f, "dQNA"},
+ {0xFF, "RESV"}};
+
+ tCode = ((oldTail->data[0]<<2) & 0x30) | ((oldTail->data[0]>>4) & 0xF);
+ for (pTab=typeTable; pTab->code!=0xFF; pTab++) {
+ if (pTab->code == tCode)
+ break;
+ }
+
+ DBGPRINT(RT_DEBUG_OFF, ("%cxH %c%c%c%c [%02X%02X %02X%02X] \n",
+ oldTail->type==0x72? 'T': 'R',
+ pTab->str[0], pTab->str[1], pTab->str[2], pTab->str[3],
+ oldTail->data[3], oldTail->data[2], oldTail->data[1], oldTail->data[0]) );
+ }
+ break;
+
+ case 0x73: /* TX STAT FIFO*/
+ showTimestamp = TRUE;
+
+ /* origMCS is limited to 4 bits. Check for case of MCS16 to 23*/
+ origMCS = (oldTail->data[0]>>1) & 0xF;
+ succMCS = (oldTail->data[2] & 0x7F);
+ if (succMCS>origMCS && origMCS<8)
+ origMCS += 16;
+ phyRate = (oldTail->data[3]<<8) + oldTail->data[2];
+
+ DBGPRINT(RT_DEBUG_OFF, ("TxFI %02X%02X%02X%02X=%c%c%c%c%c M%02d/%02d%c%c",
+ oldTail->data[3], oldTail->data[2],
+ oldTail->data[1], oldTail->data[0],
+ (phyRate & 0x0100)? 'S': 'L', /* Guard Int: S or L */
+ (phyRate & 0x0080)? '4': '2', /* BW: 4 or 2 */
+ (phyRate & 0x0200)? 'S': 's', /* STBC: S or s */
+ (phyRate & 0x2000)? 'I': ((phyRate & 0x0800)? 'E': '_'), /* Beamforming: E or I or _ */
+ (oldTail->data[0] & 0x40)? 'A': '_', /* Aggregated: A or _ */
+ succMCS, origMCS, /* MCS: <Final>/<orig> */
+ succMCS==origMCS? ' ': '*', /* Retry: '*' if MCS doesn't match */
+ (oldTail->data[0] & 0x20)? ' ': 'F') ); /* Success/Fail _ or F */
+ break;
+ case 0x7E: /* RA Log info */
+ {
+ struct {USHORT phy; USHORT per; USHORT tp; USHORT bfPer;} *p = (void*)(oldTail->data);
+ DBGPRINT(RT_DEBUG_OFF, ("RALog %02X%02X %d %d %d ",
+ (p->phy>>8) & 0xFF, p->phy & 0xFF, p->per, p->tp, p->bfPer) );
+ }
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_OFF, ("%02X %02X%02X %02X%02X %02X%02X %02X%02X ", oldTail->type,
+ oldTail->data[0], oldTail->data[1], oldTail->data[2], oldTail->data[3],
+ oldTail->data[4], oldTail->data[5], oldTail->data[6], oldTail->data[7]) );
+ break;
+ }
+
+ if (showTimestamp)
+ {
+ ULONG t = oldTail->timestamp;
+ ULONG dt = oldTail->timestamp-lastTimestamp;
+
+ DBGPRINT(RT_DEBUG_OFF, ("%lu.%06lu ", t/1000000L, t % 1000000L) );
+
+ if (dt>999999L)
+ DBGPRINT(RT_DEBUG_OFF, ("+%lu.%06lu s\n", dt/1000000L, dt % 1000000L) );
+ else
+ DBGPRINT(RT_DEBUG_OFF, ("+%lu us\n", dt) );
+ lastTimestamp = oldTail->timestamp;
+ }
+ }
+}
+
+/*
+ Set_DebugQueue_Proc - Control DBQueue
+ iwpriv ra0 set DBQueue=dd.
+ dd: 0=>disable, 1=>enable, 2=>dump, 3=>clear, 4=>dump & decode
+*/
+INT Set_DebugQueue_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG argValue = simple_strtol(arg, 0, 10);
+
+ switch (argValue) {
+ case 0:
+ dbqEnable = 0;
+ break;
+ case 1:
+ dbqEnable = DBQ_ENA_SIG;
+ break;
+ case 2:
+ dbQueueDump(pAd, FALSE);
+ break;
+ case 3:
+ dbQueueInit();
+ break;
+ case 4:
+ dbQueueDump(pAd, TRUE);
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+#endif /* INCLUDE_DEBUG_QUEUE */
+#endif /* DBG_CTRL_SUPPORT */
+
+#ifdef STREAM_MODE_SUPPORT
+/*
+ ========================================================================
+ Routine Description:
+ Set the enable/disable the stream mode
+
+ Arguments:
+ 1: enable for 1SS
+ 2: enable for 2SS
+ 3: enable for 1SS and 2SS
+ 0: disable
+
+ Notes:
+ Currently only support 1SS
+ ========================================================================
+*/
+INT Set_StreamMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UINT32 streamWord, reg, regAddr;
+
+ if (pAd->chipCap.FlgHwStreamMode == FALSE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("chip not supported feature\n"));
+ return FALSE;
+ }
+
+ pAd->CommonCfg.StreamMode = (simple_strtol(arg, 0, 10) & 0x3);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():StreamMode=%d\n", __FUNCTION__, pAd->CommonCfg.StreamMode));
+
+ streamWord = StreamModeRegVal(pAd);
+ for (regAddr = TX_CHAIN_ADDR0_H; regAddr <= TX_CHAIN_ADDR3_H; regAddr += 8)
+ {
+ RTMP_IO_READ32(pAd, regAddr, &reg);
+ reg &= (~0x000F0000);
+ RTMP_IO_WRITE32(pAd, regAddr, streamWord | reg);
+ }
+
+ return TRUE;
+}
+
+
+INT Set_StreamModeMac_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ return FALSE;
+}
+
+
+INT Set_StreamModeMCS_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.StreamModeMCS = simple_strtol(arg, 0, 16);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():StreamModeMCS=%02X\n",
+ __FUNCTION__, pAd->CommonCfg.StreamModeMCS));
+
+ return TRUE;
+}
+#endif /* STREAM_MODE_SUPPORT */
+
+
+#ifdef PRE_ANT_SWITCH
+/*
+ Set_PreAntSwitch_Proc - enable/disable Preamble Antenna Switch
+ usage: iwpriv ra0 set PreAntSwitch=[0 | 1]
+*/
+INT Set_PreAntSwitch_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.PreAntSwitch = simple_strtol(arg, 0, 10)!=0;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():(PreAntSwitch=%d)\n",
+ __FUNCTION__, pAd->CommonCfg.PreAntSwitch));
+ return TRUE;
+}
+
+
+/*
+ Set_PreAntSwitchRSSI_Proc - set Preamble Antenna Switch RSSI threshold
+ usage: iwpriv ra0 set PreAntSwitchRSSI=<RSSI threshold in dBm>
+*/
+INT Set_PreAntSwitchRSSI_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.PreAntSwitchRSSI = simple_strtol(arg, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():(PreAntSwitchRSSI=%d)\n",
+ __FUNCTION__, pAd->CommonCfg.PreAntSwitchRSSI));
+ return TRUE;
+}
+
+/*
+ Set_PreAntSwitchTimeout_Proc - set Preamble Antenna Switch Timeout threshold
+ usage: iwpriv ra0 set PreAntSwitchTimeout=<timeout in seconds, 0=>disabled>
+*/
+INT Set_PreAntSwitchTimeout_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.PreAntSwitchTimeout = simple_strtol(arg, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():(PreAntSwitchTimeout=%d)\n",
+ __FUNCTION__, pAd->CommonCfg.PreAntSwitchTimeout));
+ return TRUE;
+}
+#endif /* PRE_ANT_SWITCH */
+
+
+
+
+#ifdef CFO_TRACK
+/*
+ Set_CFOTrack_Proc - enable/disable CFOTrack
+ usage: iwpriv ra0 set CFOTrack=[0..8]
+*/
+INT Set_CFOTrack_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.CFOTrack = simple_strtol(arg, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():(CFOTrack=%d)\n",
+ __FUNCTION__, pAd->CommonCfg.CFOTrack));
+ return TRUE;
+}
+#endif /* CFO_TRACK */
+
+
+#ifdef DBG_CTRL_SUPPORT
+INT Set_DebugFlags_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->CommonCfg.DebugFlags = simple_strtol(arg, 0, 16);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_DebugFlags_Proc::(DebugFlags=%02lX)\n", pAd->CommonCfg.DebugFlags));
+ return TRUE;
+}
+#endif /* DBG_CTRL_SUPPORT */
+
+
+
+
+
+
+INT Set_LongRetryLimit_Proc(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PSTRING arg)
+{
+ TX_RTY_CFG_STRUC tx_rty_cfg;
+ UCHAR LongRetryLimit = (UCHAR)simple_strtol(arg, 0, 10);
+
+ RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+ tx_rty_cfg.field.LongRtyLimit = LongRetryLimit;
+ RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("IF Set_LongRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word));
+ return TRUE;
+}
+
+INT Set_ShortRetryLimit_Proc(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PSTRING arg)
+{
+ TX_RTY_CFG_STRUC tx_rty_cfg;
+ UCHAR ShortRetryLimit = (UCHAR)simple_strtol(arg, 0, 10);
+
+ RTMP_IO_READ32(pAdapter, TX_RTY_CFG, &tx_rty_cfg.word);
+ tx_rty_cfg.field.ShortRtyLimit = ShortRetryLimit;
+ RTMP_IO_WRITE32(pAdapter, TX_RTY_CFG, tx_rty_cfg.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ShortRetryLimit_Proc::(tx_rty_cfg=0x%x)\n", tx_rty_cfg.word));
+ return TRUE;
+}
+
+INT Set_AutoFallBack_Proc(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PSTRING arg)
+{
+ return RT_CfgSetAutoFallBack(pAdapter, arg);
+}
+
+
+
+PSTRING RTMPGetRalinkAuthModeStr(
+ IN NDIS_802_11_AUTHENTICATION_MODE authMode)
+{
+ switch(authMode)
+ {
+ case Ndis802_11AuthModeOpen:
+ return "OPEN";
+ case Ndis802_11AuthModeWPAPSK:
+ return "WPAPSK";
+ case Ndis802_11AuthModeShared:
+ return "SHARED";
+ case Ndis802_11AuthModeAutoSwitch:
+ return "WEPAUTO";
+ case Ndis802_11AuthModeWPA:
+ return "WPA";
+ case Ndis802_11AuthModeWPA2:
+ return "WPA2";
+ case Ndis802_11AuthModeWPA2PSK:
+ return "WPA2PSK";
+ case Ndis802_11AuthModeWPA1PSKWPA2PSK:
+ return "WPAPSKWPA2PSK";
+ case Ndis802_11AuthModeWPA1WPA2:
+ return "WPA1WPA2";
+ case Ndis802_11AuthModeWPANone:
+ return "WPANONE";
+ default:
+ return "UNKNOW";
+ }
+}
+
+PSTRING RTMPGetRalinkEncryModeStr(
+ IN USHORT encryMode)
+{
+ switch(encryMode)
+ {
+ case Ndis802_11WEPDisabled:
+ return "NONE";
+ case Ndis802_11WEPEnabled:
+ return "WEP";
+ case Ndis802_11Encryption2Enabled:
+ return "TKIP";
+ case Ndis802_11Encryption3Enabled:
+ return "AES";
+ case Ndis802_11Encryption4Enabled:
+ return "TKIPAES";
+ default:
+ return "UNKNOW";
+ }
+}
+
+
+INT Show_SSID_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ UCHAR ssid_str[33];
+
+
+ NdisZeroMemory(&ssid_str[0], 33);
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+ NdisMoveMemory(&ssid_str[0],
+ pAd->ApCfg.MBSSID[pObj->ioctl_if].Ssid,
+ pAd->ApCfg.MBSSID[pObj->ioctl_if].SsidLen);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ snprintf(pBuf, BufLen, "\t%s", ssid_str);
+ return 0;
+}
+
+INT Show_WirelessMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ switch(pAd->CommonCfg.PhyMode)
+ {
+ case (WMODE_B | WMODE_G):
+ snprintf(pBuf, BufLen, "\t11B/G");
+ break;
+ case (WMODE_B):
+ snprintf(pBuf, BufLen, "\t11B");
+ break;
+ case (WMODE_A):
+ snprintf(pBuf, BufLen, "\t11A");
+ break;
+ case (WMODE_A | WMODE_B | WMODE_G):
+ snprintf(pBuf, BufLen, "\t11A/B/G");
+ break;
+ case (WMODE_G):
+ snprintf(pBuf, BufLen, "\t11G");
+ break;
+#ifdef DOT11_N_SUPPORT
+ case (WMODE_A | WMODE_B | WMODE_G | WMODE_GN | WMODE_AN):
+ snprintf(pBuf, BufLen, "\t11A/B/G/N");
+ break;
+ case (WMODE_GN):
+ snprintf(pBuf, BufLen, "\t11N only with 2.4G");
+ break;
+ case (WMODE_G | WMODE_GN):
+ snprintf(pBuf, BufLen, "\t11G/N");
+ break;
+ case (WMODE_A | WMODE_AN):
+ snprintf(pBuf, BufLen, "\t11A/N");
+ break;
+ case (WMODE_B | WMODE_G | WMODE_GN):
+ snprintf(pBuf, BufLen, "\t11B/G/N");
+ break;
+ case (WMODE_A | WMODE_G | WMODE_GN | WMODE_AN):
+ snprintf(pBuf, BufLen, "\t11A/G/N");
+ break;
+ case (WMODE_AN):
+ snprintf(pBuf, BufLen, "\t11N only with 5G");
+ break;
+#endif /* DOT11_N_SUPPORT */
+ default:
+ snprintf(pBuf, BufLen, "\tUnknow Value(%d)", pAd->CommonCfg.PhyMode);
+ break;
+ }
+
+ return 0;
+}
+
+
+INT Show_TxBurst_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.bEnableTxBurst ? "TRUE":"FALSE");
+ return 0;
+}
+
+INT Show_TxPreamble_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ switch(pAd->CommonCfg.TxPreamble)
+ {
+ case Rt802_11PreambleShort:
+ snprintf(pBuf, BufLen, "\tShort");
+ break;
+ case Rt802_11PreambleLong:
+ snprintf(pBuf, BufLen, "\tLong");
+ break;
+ case Rt802_11PreambleAuto:
+ snprintf(pBuf, BufLen, "\tAuto");
+ break;
+ default:
+ snprintf(pBuf, BufLen, "\tUnknown Value(%lu)", pAd->CommonCfg.TxPreamble);
+ break;
+ }
+
+ return 0;
+}
+
+INT Show_TxPower_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%lu", pAd->CommonCfg.TxPowerPercentage);
+ return 0;
+}
+
+INT Show_Channel_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%d", pAd->CommonCfg.Channel);
+ return 0;
+}
+
+INT Show_BGProtection_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ switch(pAd->CommonCfg.UseBGProtection)
+ {
+ case 1: /*Always On*/
+ snprintf(pBuf, BufLen, "\tON");
+ break;
+ case 2: /*Always OFF*/
+ snprintf(pBuf, BufLen, "\tOFF");
+ break;
+ case 0: /*AUTO*/
+ snprintf(pBuf, BufLen, "\tAuto");
+ break;
+ default:
+ snprintf(pBuf, BufLen, "\tUnknow Value(%lu)", pAd->CommonCfg.UseBGProtection);
+ break;
+ }
+ return 0;
+}
+
+INT Show_RTSThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%u", pAd->CommonCfg.RtsThreshold);
+ return 0;
+}
+
+INT Show_FragThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%u", pAd->CommonCfg.FragmentThreshold);
+ return 0;
+}
+
+#ifdef DOT11_N_SUPPORT
+INT Show_HtBw_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
+ {
+ snprintf(pBuf, BufLen, "\t40 MHz");
+ }
+ else
+ {
+ snprintf(pBuf, BufLen, "\t20 MHz");
+ }
+ return 0;
+}
+
+INT Show_HtMcs_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+#ifdef CONFIG_AP_SUPPORT
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ snprintf(pBuf, BufLen, "\t%u", pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredTransmitSetting.field.MCS);
+#endif /* CONFIG_AP_SUPPORT */
+
+ return 0;
+}
+
+INT Show_HtGi_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ switch(pAd->CommonCfg.RegTransmitSetting.field.ShortGI)
+ {
+ case GI_400:
+ snprintf(pBuf, BufLen, "\tGI_400");
+ break;
+ case GI_800:
+ snprintf(pBuf, BufLen, "\tGI_800");
+ break;
+ default:
+ snprintf(pBuf, BufLen, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.ShortGI);
+ break;
+ }
+ return 0;
+}
+
+INT Show_HtOpMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ switch(pAd->CommonCfg.RegTransmitSetting.field.HTMODE)
+ {
+ case HTMODE_GF:
+ snprintf(pBuf, BufLen, "\tGF");
+ break;
+ case HTMODE_MM:
+ snprintf(pBuf, BufLen, "\tMM");
+ break;
+ default:
+ snprintf(pBuf, BufLen, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.HTMODE);
+ break;
+ }
+ return 0;
+}
+
+INT Show_HtExtcha_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ switch(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA)
+ {
+ case EXTCHA_BELOW:
+ snprintf(pBuf, BufLen, "\tBelow");
+ break;
+ case EXTCHA_ABOVE:
+ snprintf(pBuf, BufLen, "\tAbove");
+ break;
+ default:
+ snprintf(pBuf, BufLen, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.EXTCHA);
+ break;
+ }
+ return 0;
+}
+
+
+INT Show_HtMpduDensity_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%u", pAd->CommonCfg.BACapability.field.MpduDensity);
+ return 0;
+}
+
+INT Show_HtBaWinSize_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%u", pAd->CommonCfg.BACapability.field.RxBAWinLimit);
+ return 0;
+}
+
+INT Show_HtRdg_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.bRdg ? "TRUE":"FALSE");
+ return 0;
+}
+
+INT Show_HtAmsdu_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.BACapability.field.AmsduEnable ? "TRUE":"FALSE");
+ return 0;
+}
+
+INT Show_HtAutoBa_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.BACapability.field.AutoBA ? "TRUE":"FALSE");
+ return 0;
+}
+#endif /* DOT11_N_SUPPORT */
+
+INT Show_CountryRegion_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%d", pAd->CommonCfg.CountryRegion);
+ return 0;
+}
+
+INT Show_CountryRegionABand_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%d", pAd->CommonCfg.CountryRegionForABand);
+ return 0;
+}
+
+INT Show_CountryCode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.CountryCode);
+ return 0;
+}
+
+#ifdef AGGREGATION_SUPPORT
+INT Show_PktAggregate_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.bAggregationCapable ? "TRUE":"FALSE");
+ return 0;
+}
+#endif /* AGGREGATION_SUPPORT */
+
+#ifdef WMM_SUPPORT
+INT Show_WmmCapable_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+#ifdef CONFIG_AP_SUPPORT
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ snprintf(pBuf, BufLen, "\t%s", pAd->ApCfg.MBSSID[pObj->ioctl_if].bWmmCapable ? "TRUE":"FALSE");
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ return 0;
+}
+#endif /* WMM_SUPPORT */
+
+INT Show_IEEE80211H_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.bIEEE80211H ? "TRUE":"FALSE");
+ return 0;
+}
+
+
+INT Show_AuthMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeOpen;
+#ifdef CONFIG_AP_SUPPORT
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ AuthMode = pAd->ApCfg.MBSSID[pObj->ioctl_if].AuthMode;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ if ((AuthMode >= Ndis802_11AuthModeOpen) &&
+ (AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK))
+ snprintf(pBuf, BufLen, "\t%s", RTMPGetRalinkAuthModeStr(AuthMode));
+#ifdef WAPI_SUPPORT
+ else if (AuthMode == Ndis802_11AuthModeWAICERT)
+ snprintf(pBuf, BufLen, "\t%s", "WAI_CERT");
+ else if (AuthMode == Ndis802_11AuthModeWAIPSK)
+ snprintf(pBuf, BufLen, "\t%s", "WAI_PSK");
+#endif /* WAPI_SUPPORT */
+ else
+ snprintf(pBuf, BufLen, "\tUnknow Value(%d)", AuthMode);
+
+ return 0;
+}
+
+INT Show_EncrypType_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ NDIS_802_11_WEP_STATUS WepStatus = Ndis802_11WEPDisabled;
+#ifdef CONFIG_AP_SUPPORT
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ WepStatus = pAd->ApCfg.MBSSID[pObj->ioctl_if].WepStatus;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ if ((WepStatus >= Ndis802_11WEPEnabled) &&
+ (WepStatus <= Ndis802_11Encryption4KeyAbsent))
+ snprintf(pBuf, BufLen, "\t%s", RTMPGetRalinkEncryModeStr(WepStatus));
+#ifdef WAPI_SUPPORT
+ else if (WepStatus == Ndis802_11EncryptionSMS4Enabled)
+ snprintf(pBuf, BufLen, "\t%s", "WPI_SMS4");
+#endif /* WAPI_SUPPORT */
+ else
+ snprintf(pBuf, BufLen, "\tUnknow Value(%d)", WepStatus);
+
+ return 0;
+}
+
+INT Show_DefaultKeyID_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ UCHAR DefaultKeyId = 0;
+#ifdef CONFIG_AP_SUPPORT
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ DefaultKeyId = pAd->ApCfg.MBSSID[pObj->ioctl_if].DefaultKeyId;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ snprintf(pBuf, BufLen, "\t%d", DefaultKeyId);
+
+ return 0;
+}
+
+INT Show_WepKey_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN INT KeyIdx,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ UCHAR Key[16] = {0}, KeyLength = 0;
+ INT index = BSS0;
+#ifdef CONFIG_AP_SUPPORT
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ index = pObj->ioctl_if;
+#endif /* CONFIG_AP_SUPPORT */
+
+ KeyLength = pAd->SharedKey[index][KeyIdx].KeyLen;
+ NdisMoveMemory(Key, pAd->SharedKey[index][KeyIdx].Key, KeyLength);
+
+ /*check key string is ASCII or not*/
+ if (RTMPCheckStrPrintAble((PCHAR)Key, KeyLength))
+ sprintf(pBuf, "\t%s", Key);
+ else
+ {
+ int idx;
+ sprintf(pBuf, "\t");
+ for (idx = 0; idx < KeyLength; idx++)
+ sprintf(pBuf+strlen(pBuf), "%02X", Key[idx]);
+ }
+ return 0;
+}
+
+INT Show_Key1_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ Show_WepKey_Proc(pAd, 0, pBuf, BufLen);
+ return 0;
+}
+
+INT Show_Key2_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ Show_WepKey_Proc(pAd, 1, pBuf, BufLen);
+ return 0;
+}
+
+INT Show_Key3_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ Show_WepKey_Proc(pAd, 2, pBuf, BufLen);
+ return 0;
+}
+
+INT Show_Key4_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ Show_WepKey_Proc(pAd, 3, pBuf, BufLen);
+ return 0;
+}
+
+INT Show_PMK_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ INT idx;
+ UCHAR PMK[32] = {0};
+
+#ifdef CONFIG_AP_SUPPORT
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ NdisMoveMemory(PMK, pAd->ApCfg.MBSSID[pObj->ioctl_if].PMK, 32);
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ sprintf(pBuf, "\tPMK = ");
+ for (idx = 0; idx < 32; idx++)
+ sprintf(pBuf+strlen(pBuf), "%02X", PMK[idx]);
+
+ return 0;
+}
+
+
+INT Show_STA_RAInfo_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ sprintf(pBuf, "\n");
+#ifdef PRE_ANT_SWITCH
+ sprintf(pBuf+strlen(pBuf), "PreAntSwitch: %d\n", pAd->CommonCfg.PreAntSwitch);
+ sprintf(pBuf+strlen(pBuf), "PreAntSwitchRSSI: %d\n", pAd->CommonCfg.PreAntSwitchRSSI);
+#endif /* PRE_ANT_SWITCH */
+
+
+#ifdef NEW_RATE_ADAPT_SUPPORT
+ sprintf(pBuf+strlen(pBuf), "LowTrafficThrd: %d\n", pAd->CommonCfg.lowTrafficThrd);
+ sprintf(pBuf+strlen(pBuf), "TrainUpRule: %d\n", pAd->CommonCfg.TrainUpRule);
+ sprintf(pBuf+strlen(pBuf), "TrainUpRuleRSSI: %d\n", pAd->CommonCfg.TrainUpRuleRSSI);
+ sprintf(pBuf+strlen(pBuf), "TrainUpLowThrd: %d\n", pAd->CommonCfg.TrainUpLowThrd);
+ sprintf(pBuf+strlen(pBuf), "TrainUpHighThrd: %d\n", pAd->CommonCfg.TrainUpHighThrd);
+#endif // NEW_RATE_ADAPT_SUPPORT //
+
+#ifdef STREAM_MODE_SUPPORT
+ sprintf(pBuf+strlen(pBuf), "StreamMode: %d\n", pAd->CommonCfg.StreamMode);
+ sprintf(pBuf+strlen(pBuf), "StreamModeMCS: 0x%04x\n", pAd->CommonCfg.StreamModeMCS);
+#endif // STREAM_MODE_SUPPORT //
+#ifdef TXBF_SUPPORT
+ sprintf(pBuf+strlen(pBuf), "ITxBfEn: %d\n", pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn);
+ sprintf(pBuf+strlen(pBuf), "ITxBfTimeout: %ld\n", pAd->CommonCfg.ITxBfTimeout);
+ sprintf(pBuf+strlen(pBuf), "ETxBfTimeout: %ld\n", pAd->CommonCfg.ETxBfTimeout);
+ sprintf(pBuf+strlen(pBuf), "ETxBfEnCond: %ld\n", pAd->CommonCfg.ETxBfEnCond);
+ sprintf(pBuf+strlen(pBuf), "ETxBfNoncompress: %d\n", pAd->CommonCfg.ETxBfNoncompress);
+ sprintf(pBuf+strlen(pBuf), "ETxBfIncapable: %d\n", pAd->CommonCfg.ETxBfIncapable);
+#endif // TXBF_SUPPORT //
+
+#ifdef DBG_CTRL_SUPPORT
+ sprintf(pBuf+strlen(pBuf), "DebugFlags: 0x%lx\n", pAd->CommonCfg.DebugFlags);
+#endif /* DBG_CTRL_SUPPORT */
+ return 0;
+}
+
+
+INT Show_MacTable_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ INT i;
+ UINT32 RegValue;
+ ULONG DataRate=0;
+
+ printk("\n");
+ RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
+ printk("BackOff Slot : %s slot time, BKOFF_SLOT_CFG(0x1104) = 0x%08x\n",
+ OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED) ? "short" : "long",
+ RegValue);
+
+#ifdef DOT11_N_SUPPORT
+ printk("HT Operating Mode : %d\n", pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode);
+ printk("\n");
+#endif /* DOT11_N_SUPPORT */
+
+ printk("\n%-19s%-4s%-4s%-4s%-4s%-8s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s%-7s%-7s\n",
+ "MAC", "AID", "BSS", "PSM", "WMM", "MIMOPS", "RSSI0", "RSSI1",
+ "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC", "Idle", "Rate");
+
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i];
+
+ if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry))
+ && (pEntry->Sst == SST_ASSOC))
+ {
+ DataRate=0;
+ getRate(pEntry->HTPhyMode, &DataRate);
+
+
+ printk("%02X:%02X:%02X:%02X:%02X:%02X ", PRINT_MAC(pEntry->Addr));
+ printk("%-4d", (int)pEntry->Aid);
+ printk("%-4d", (int)pEntry->apidx);
+ printk("%-4d", (int)pEntry->PsMode);
+ printk("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE));
+#ifdef DOT11_N_SUPPORT
+ printk("%-8d", (int)pEntry->MmpsMode);
+#endif /* DOT11_N_SUPPORT */
+ printk("%-7d", pEntry->RssiSample.AvgRssi0);
+ printk("%-7d", pEntry->RssiSample.AvgRssi1);
+ printk("%-7d", pEntry->RssiSample.AvgRssi2);
+ printk("%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE));
+ printk("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW));
+#ifdef DOT11_VHT_AC
+ if (pEntry->HTPhyMode.field.MODE == MODE_VHT)
+ printk("%dS-M%d", ((pEntry->HTPhyMode.field.MCS>>4) + 1), (pEntry->HTPhyMode.field.MCS & 0xf));
+ else
+#endif /* DOT11_VHT_AC */
+ printk("%-6d", pEntry->HTPhyMode.field.MCS);
+ printk("%-6d", pEntry->HTPhyMode.field.ShortGI);
+ printk("%-6d", pEntry->HTPhyMode.field.STBC);
+ printk("%-7d", (int)(pEntry->StaIdleTimeout - pEntry->NoDataIdleCount));
+ printk("%-7d", (int)DataRate);
+ printk("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount,
+ (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0);
+
+ printk("\t\t\t\t%-10s", get_phymode_str(pEntry->MaxHTPhyMode.field.MODE));
+ printk("%-6s", get_bw_str(pEntry->MaxHTPhyMode.field.BW));
+#ifdef DOT11_VHT_AC
+ if (pEntry->MaxHTPhyMode.field.MODE == MODE_VHT)
+ printk("%dS-M%d", ((pEntry->MaxHTPhyMode.field.MCS>>4) + 1), (pEntry->MaxHTPhyMode.field.MCS & 0xf));
+ else
+#endif /* DOT11_VHT_AC */
+ printk("%-6d", pEntry->MaxHTPhyMode.field.MCS);
+ printk("%-6d", pEntry->MaxHTPhyMode.field.ShortGI);
+ printk("%-6d\n", pEntry->MaxHTPhyMode.field.STBC);
+
+ printk("\n");
+ }
+ }
+
+ return TRUE;
+}
+
+
+INT show_devinfo_proc(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ UCHAR *pstr;
+
+
+ DBGPRINT(RT_DEBUG_OFF, ("Device MAC\n"));
+ if (pAd->OpMode == OPMODE_AP)
+ pstr = "AP";
+ else if (pAd->OpMode == OPMODE_STA)
+ pstr = "STA";
+ else
+ pstr = "Unknown";
+ DBGPRINT(RT_DEBUG_OFF, ("Operation Mode: %s\n", pstr));
+
+ pstr = wmode_2_str(pAd->CommonCfg.PhyMode);
+ if (pstr) {
+ DBGPRINT(RT_DEBUG_OFF, ("WirelessMode: %s(%d)\n", pstr, pAd->CommonCfg.PhyMode));
+ os_free_mem(pAd, pstr);
+ }
+
+ DBGPRINT(RT_DEBUG_OFF, ("Channel: %d\n", pAd->CommonCfg.Channel));
+ DBGPRINT(RT_DEBUG_OFF, ("\tCentralChannel: %d\n", pAd->CommonCfg.CentralChannel));
+#ifdef DOT11_VHT_AC
+ if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode))
+ DBGPRINT(RT_DEBUG_OFF, ("\tVHT CentralChannel: %d\n", pAd->CommonCfg.vht_cent_ch));
+#endif /* DOT11_VHT_AC */
+ DBGPRINT(RT_DEBUG_OFF, ("\tRF Channel: %d\n", pAd->LatchRfRegs.Channel));
+
+ DBGPRINT(RT_DEBUG_OFF, ("Bandwidth\n"));
+ pstr = (pAd->CommonCfg.RegTransmitSetting.field.BW) ? "20/40" : "20";
+ DBGPRINT(RT_DEBUG_OFF, ("\tHT-BW: %s\n", pstr));
+#ifdef DOT11_VHT_AC
+ if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode))
+ {
+ if (pAd->CommonCfg.vht_bw)
+ pstr = "80";
+ DBGPRINT(RT_DEBUG_OFF, ("\tVHT-BW: %s\n", pstr));
+ }
+#endif /* DOT11_VHT_AC */
+
+#ifdef RT65xx
+ if (IS_RT65XX(pAd))
+ {
+ dump_bw_info(pAd);
+ }
+#endif /* RT65xx */
+
+ DBGPRINT(RT_DEBUG_OFF, ("Security\n"));
+
+ DBGPRINT(RT_DEBUG_OFF, ("MAC Ver: %s\n", MAC_VERSION));
+ DBGPRINT(RT_DEBUG_OFF, ("BBP Ver: %s\n", BBP_VERSION));
+ DBGPRINT(RT_DEBUG_OFF, ("RF Ver: %s\n", RF_VERSION));
+
+ return TRUE;
+}
+
+
+#ifdef WSC_STA_SUPPORT
+INT Show_WpsManufacturer_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ sprintf(pBuf, "\tManufacturer = %s", pAd->StaCfg.WscControl.RegData.SelfInfo.Manufacturer);
+ return 0;
+}
+
+INT Show_WpsModelName_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ sprintf(pBuf, "\tModelName = %s", pAd->StaCfg.WscControl.RegData.SelfInfo.ModelName);
+ return 0;
+}
+
+INT Show_WpsDeviceName_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ sprintf(pBuf, "\tDeviceName = %s", pAd->StaCfg.WscControl.RegData.SelfInfo.DeviceName);
+ return 0;
+}
+
+INT Show_WpsModelNumber_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ sprintf(pBuf, "\tModelNumber = %s", pAd->StaCfg.WscControl.RegData.SelfInfo.ModelNumber);
+ return 0;
+}
+
+INT Show_WpsSerialNumber_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ sprintf(pBuf, "\tSerialNumber = %s", pAd->StaCfg.WscControl.RegData.SelfInfo.SerialNumber);
+ return 0;
+}
+
+INT Show_WpsUuid_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ UCHAR *bin = pAd->StaCfg.WscControl.RegData.SelfInfo.Uuid;
+
+ sprintf(pBuf, "\tUuid = %02x%02x%02x%02x-%02x%02x-%02x%02x-"
+ "%02x%02x-%02x%02x%02x%02x%02x%02x",
+ bin[0], bin[1], bin[2], bin[3],
+ bin[4], bin[5], bin[6], bin[7],
+ bin[8], bin[9], bin[10], bin[11],
+ bin[12], bin[13], bin[14], bin[15]);
+
+ return 0;
+}
+#endif /* WSC_STA_SUPPORT */
+
+
+#ifdef SINGLE_SKU
+INT Show_ModuleTxpower_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PSTRING pBuf,
+ IN ULONG BufLen)
+{
+ snprintf(pBuf, BufLen, "\tModuleTxpower = %d", pAd->CommonCfg.ModuleTxpower);
+ return 0;
+}
+#endif /* SINGLE_SKU */
+
+#ifdef APCLI_SUPPORT
+ INT RTMPIoctlConnStatus(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+
+ INT i=0;
+ POS_COOKIE pObj;
+ UCHAR ifIndex;
+ BOOLEAN bConnect=FALSE;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==>RTMPIoctlConnStatus\n"));
+
+ if (pObj->ioctl_if_type != INT_APCLI)
+ return FALSE;
+
+ ifIndex = pObj->ioctl_if;
+
+
+ DBGPRINT(RT_DEBUG_OFF, ("=============================================================\n"));
+ if((pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState == APCLI_CTRL_CONNECTED)
+ && (pAd->ApCfg.ApCliTab[ifIndex].SsidLen != 0))
+ {
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i];
+
+ if ( IS_ENTRY_APCLI(pEntry)
+ && (pEntry->Sst == SST_ASSOC)
+ && (pEntry->PortSecured == WPA_802_1X_PORT_SECURED))
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("ApCli%d Connected AP : %02X:%02X:%02X:%02X:%02X:%02X SSID:%s\n",ifIndex,
+ pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+ pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5],
+ pAd->ApCfg.ApCliTab[ifIndex].Ssid));
+ bConnect=TRUE;
+ }
+ }
+
+ if (!bConnect)
+ DBGPRINT(RT_DEBUG_OFF, ("ApCli%d Connected AP : Disconnect\n",ifIndex));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("ApCli%d Connected AP : Disconnect\n",ifIndex));
+ }
+ DBGPRINT(RT_DEBUG_OFF, ("=============================================================\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlConnStatus\n"));
+ return TRUE;
+}
+#endif/*APCLI_SUPPORT*/
+
+void getRate(HTTRANSMIT_SETTING HTSetting, ULONG* fLastTxRxRate)
+
+{
+ INT MCSMappingRateTable[] =
+ {2, 4, 11, 22, /* CCK*/
+ 12, 18, 24, 36, 48, 72, 96, 108, /* OFDM*/
+ 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, /* 20MHz, 800ns GI, MCS: 0 ~ 15*/
+ 39, 78, 117, 156, 234, 312, 351, 390, /* 20MHz, 800ns GI, MCS: 16 ~ 23*/
+ 27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, /* 40MHz, 800ns GI, MCS: 0 ~ 15*/
+ 81, 162, 243, 324, 486, 648, 729, 810, /* 40MHz, 800ns GI, MCS: 16 ~ 23*/
+ 14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, /* 20MHz, 400ns GI, MCS: 0 ~ 15*/
+ 43, 87, 130, 173, 260, 317, 390, 433, /* 20MHz, 400ns GI, MCS: 16 ~ 23*/
+ 30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, /* 40MHz, 400ns GI, MCS: 0 ~ 15*/
+ 90, 180, 270, 360, 540, 720, 810, 900};
+
+ int rate_count = sizeof(MCSMappingRateTable)/sizeof(int);
+ int rate_index = 0;
+ int value = 0;
+
+#ifdef DOT11_N_SUPPORT
+ if (HTSetting.field.MODE >= MODE_HTMIX)
+ {
+/* rate_index = 12 + ((UCHAR)ht_setting.field.BW *16) + ((UCHAR)ht_setting.field.ShortGI *32) + ((UCHAR)ht_setting.field.MCS);*/
+ rate_index = 12 + ((UCHAR)HTSetting.field.BW *24) + ((UCHAR)HTSetting.field.ShortGI *48) + ((UCHAR)HTSetting.field.MCS);
+ }
+ else
+#endif /* DOT11_N_SUPPORT */
+ if (HTSetting.field.MODE == MODE_OFDM)
+ rate_index = (UCHAR)(HTSetting.field.MCS) + 4;
+ else if (HTSetting.field.MODE == MODE_CCK)
+ rate_index = (UCHAR)(HTSetting.field.MCS);
+
+ if (rate_index < 0)
+ rate_index = 0;
+
+ if (rate_index >= rate_count)
+ rate_index = rate_count-1;
+
+ value = (MCSMappingRateTable[rate_index] * 5)/10;
+ *fLastTxRxRate=(ULONG)value;
+ return;
+}
+
+
+#ifdef TXBF_SUPPORT
+
+/*
+ Set_ReadITxBf_Proc - Read Implicit BF profile and display it
+ iwpriv ra0 set ReadITxBf=<profile number>
+*/
+INT Set_ReadITxBf_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int profileNum = simple_strtol(arg, 0, 10);
+ int scIndex, i, maxCarriers;
+
+ Read_TxBfProfile(pAd, &profData, profileNum, TRUE);
+
+ /* Display profile. Note: each column is displayed as a row. This shortens the display */
+ DBGPRINT(RT_DEBUG_OFF, ("---ITxBF Profile: %d - %dx%d, %dMHz\n",
+ profileNum, profData.rows, profData.columns, profData.fortyMHz? 40: 20));
+
+ maxCarriers = profData.fortyMHz? PROFILE_MAX_CARRIERS_40: PROFILE_MAX_CARRIERS_20;
+
+ for (scIndex=0; scIndex<maxCarriers; scIndex++) {
+ for (i=0; i<profData.rows; i++) {
+ DBGPRINT(RT_DEBUG_OFF, ("%d %d ", Unpack_IBFValue(profData.data[scIndex], 2*i+1), Unpack_IBFValue(profData.data[scIndex], 2*i)));
+ }
+ DBGPRINT(RT_DEBUG_OFF, ("\n"));
+
+ if (profData.columns>1) {
+ for (i=0; i<profData.rows; i++) {
+ DBGPRINT(RT_DEBUG_OFF, ("%d %d ", Unpack_IBFValue(profData.data[scIndex], 2*i+7), Unpack_IBFValue(profData.data[scIndex], 2*i+6)));
+ }
+ DBGPRINT(RT_DEBUG_OFF, ("\n"));
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*
+ Set_ReadETxBf_Proc - Read Explicit BF profile and display it
+ usage: iwpriv ra0 set ReadETxBf=<profile number>
+*/
+INT Set_ReadETxBf_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int profileNum = simple_strtol(arg, 0, 10);
+ int scIndex, i, maxCarriers;
+
+ Read_TxBfProfile(pAd, &profData, profileNum, FALSE);
+
+ /* Dump ETxBF profile values. Note: each column is displayed as a row. This shortens the display */
+ DBGPRINT(RT_DEBUG_OFF, ("---ETxBF Profile: %d - %dx%d, %dMHz, grp=%d\n",
+ profileNum, profData.rows, profData.columns, profData.fortyMHz? 40: 20, profData.grouping));
+
+ maxCarriers = profData.fortyMHz? PROFILE_MAX_CARRIERS_40: PROFILE_MAX_CARRIERS_20;
+
+ for (scIndex=0; scIndex<maxCarriers; scIndex++) {
+ for (i=0; i<profData.rows; i++) {
+ DBGPRINT(RT_DEBUG_OFF, ("%d %d\t", (CHAR)(profData.data[scIndex][6*i]), (CHAR)(profData.data[scIndex][6*i+1]) ));
+ }
+ DBGPRINT(RT_DEBUG_OFF, ("\n"));
+
+ if (profData.columns>1) {
+ for (i=0; i<profData.rows; i++) {
+ DBGPRINT(RT_DEBUG_OFF, ("%d %d ", (CHAR)(profData.data[scIndex][6*i+2]), (CHAR)(profData.data[scIndex][6*i+3]) ));
+ }
+ DBGPRINT(RT_DEBUG_OFF, ("\n"));
+ }
+
+ if (profData.columns>2) {
+ for (i=0; i<profData.rows; i++) {
+ DBGPRINT(RT_DEBUG_OFF, ("%d %d ", (CHAR)(profData.data[scIndex][6*i+4]), (CHAR)(profData.data[scIndex][6*i+5]) ));
+ }
+ DBGPRINT(RT_DEBUG_OFF, ("\n"));
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*
+ Set_WriteITxBf_Proc - Write Implicit BF matrix
+ usage: iwpriv ra0 set WriteITxBf=<profile number>
+ Assumes profData contains a valid Implicit Profile
+*/
+INT Set_WriteITxBf_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int profileNum = simple_strtol(arg, 0, 10);
+
+ if (!profData.impProfile)
+ return FALSE;
+
+ Write_TxBfProfile(pAd, &profData, profileNum);
+
+ return TRUE;
+}
+
+
+/*
+ Set_WriteETxBf_Proc - Write Explicit BF matrix
+ usage: iwpriv ra0 set WriteETxBf=<profile number>
+ Assumes profData contains a valid Explicit Profile
+*/
+INT Set_WriteETxBf_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int profileNum = simple_strtol(arg, 0, 10);
+
+ if (profData.impProfile)
+ return FALSE;
+
+ Write_TxBfProfile(pAd, &profData, profileNum);
+
+ return TRUE;
+}
+
+
+/*
+ Set_StatITxBf_Proc - Compute power of each chain in Implicit BF matrix
+ usage: iwpriv ra0 set StatITxBf=<profile number>
+*/
+INT Set_StatITxBf_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int scIndex, maxCarriers, i;
+ unsigned long col1Power[3] = {0,0,0}, col2Power[3] = {0,0,0};
+ int profileNum = simple_strtol(arg, 0, 10);
+ PROFILE_DATA *pProfData;
+
+ pProfData = (PROFILE_DATA *)kmalloc(sizeof(PROFILE_DATA), MEM_ALLOC_FLAG);
+ if (pProfData == NULL)
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("Set_StatITxBf_Proc: kmalloc failed\n"));
+ return FALSE;
+ }
+
+ Read_TxBfProfile(pAd, pProfData, profileNum, TRUE);
+
+ maxCarriers = pProfData->fortyMHz? PROFILE_MAX_CARRIERS_40: PROFILE_MAX_CARRIERS_20;
+
+ for (scIndex=0; scIndex<maxCarriers; scIndex++) {
+ for (i=0; i<pProfData->rows; i++) {
+ int ival = Unpack_IBFValue(pProfData->data[scIndex], 2*i+1);
+ int qval = Unpack_IBFValue(pProfData->data[scIndex], 2*i);
+ col1Power[i] += ival*ival+qval*qval;
+
+ if (pProfData->columns==2) {
+ ival = Unpack_IBFValue(pProfData->data[scIndex], 2*i+7);
+ qval = Unpack_IBFValue(pProfData->data[scIndex], 2*i+6);
+ col2Power[i] += ival*ival+qval*qval;
+ }
+ }
+ }
+
+ /* Remove implied scale factor of 2^-16. Convert to thousandths */
+ for (i=0; i<pProfData->rows; i++) {
+ col1Power[i] >>= 12;
+ col1Power[i] = ((col1Power[i]*1000)/maxCarriers)>>4;
+ col2Power[i] >>= 12;
+ col2Power[i] = ((col2Power[i]*1000)/maxCarriers)>>4;
+ }
+
+ /* Display stats */
+ DBGPRINT(RT_DEBUG_OFF, ("ITxBF Stats:\n %dx1=[0.%03lu 0.%03lu, 0.%03lu]\n",
+ pProfData->rows, col1Power[0], col1Power[1], col1Power[2]));
+ if (pProfData->columns==2) {
+ DBGPRINT(RT_DEBUG_OFF, (" %dx2=[0.%03lu 0.%03lu, 0.%03lu]\n",
+ pProfData->rows, (col1Power[0]+col2Power[0])/2, (col1Power[1]+col2Power[1])/2,
+ (col1Power[2]+col2Power[2])/2) );
+ }
+
+ kfree(pProfData);
+
+ return TRUE;
+}
+
+/*
+ Set_StatETxBf_Proc - Compute power of each chain in Explicit BF matrix
+ usage: iwpriv ra0 set StatETxBf=<profile number>
+*/
+INT Set_StatETxBf_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int scIndex, maxCarriers, i;
+ unsigned long col1Power[3] = {0,0,0}, col2Power[3] = {0,0,0}, col3Power[3] = {0,0,0};
+ int profileNum = simple_strtol(arg, 0, 10);
+ PROFILE_DATA *pProfData;
+
+ pProfData = (PROFILE_DATA *)kmalloc(sizeof(PROFILE_DATA), MEM_ALLOC_FLAG);
+ if (pProfData == NULL)
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("Set_StatETxBf_Proc: kmalloc failed\n"));
+ return FALSE;
+ }
+
+ Read_TxBfProfile(pAd, pProfData, profileNum, FALSE);
+
+ maxCarriers = pProfData->fortyMHz? PROFILE_MAX_CARRIERS_40: PROFILE_MAX_CARRIERS_20;
+
+ for (scIndex=0; scIndex<maxCarriers; scIndex++) {
+ for (i=0; i<pProfData->rows; i++) {
+ int ival = (CHAR)(pProfData->data[scIndex][6*i]);
+ int qval = (CHAR)(pProfData->data[scIndex][6*i+1]);
+ col1Power[i] += ival*ival+qval*qval;
+
+ if (pProfData->columns>1) {
+ ival = (CHAR)(pProfData->data[scIndex][6*i+2]);
+ qval = (CHAR)(pProfData->data[scIndex][6*i+3]);
+ col2Power[i] += ival*ival+qval*qval;
+ }
+
+ if (pProfData->columns>2) {
+ ival = (CHAR)(pProfData->data[scIndex][6*i+4]);
+ qval = (CHAR)(pProfData->data[scIndex][6*i+5]);
+ col3Power[i] += ival*ival+qval*qval;
+ }
+ }
+ }
+
+ /* Remove implied scale factor of 2^-14. Convert to thousandths */
+ for (i=0; i<pProfData->rows; i++) {
+ col1Power[i] >>= 10;
+ col1Power[i] = ((col1Power[i]*1000)/maxCarriers)>>4;
+ col2Power[i] >>= 10;
+ col2Power[i] = ((col2Power[i]*1000)/maxCarriers)>>4;
+ col3Power[i] >>= 10;
+ col3Power[i] = ((col3Power[i]*1000)/maxCarriers)>>4;
+ }
+
+ /* Display stats */
+ DBGPRINT(RT_DEBUG_OFF, ("ETxBF Stats:\n %dx1=[0.%03lu 0.%03lu, 0.%03lu]\n",
+ pProfData->rows, col1Power[0], col1Power[1], col1Power[2]));
+ if (pProfData->columns==2) {
+ DBGPRINT(RT_DEBUG_OFF, (" %dx2=[0.%03lu 0.%03lu, 0.%03lu]\n",
+ pProfData->rows, (col1Power[0]+col2Power[0])/2,
+ (col1Power[1]+col2Power[1])/2, (col1Power[2]+col2Power[2])/2) );
+ }
+ if (pProfData->columns==3) {
+ DBGPRINT(RT_DEBUG_OFF, (" %dx3=[0.%03lu 0.%03lu, 0.%03lu]\n",
+ pProfData->rows, (col1Power[0]+col2Power[0]+col3Power[0])/3,
+ (col1Power[1]+col2Power[1]+col3Power[1])/3,
+ (col1Power[2]+col2Power[2]+col3Power[2])/3) );
+ }
+
+ kfree(pProfData);
+
+ return TRUE;
+}
+
+
+/*
+ Set_TxBfTag_Proc - Display BF Profile Tags
+ usage: "iwpriv ra0 set TxBfTag=n"
+ n: 0=>all,
+ 1=>Explicit,
+ 2=>Implicit,
+ 3=>dump Power table
+*/
+INT Set_TxBfTag_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int argVal = simple_strtol(arg, 0, 10);
+ int profileNum;
+
+ if (argVal==0 || argVal==1) {
+ /* Display Explicit tagfield */
+ DBGPRINT(RT_DEBUG_OFF, ("---Explicit TxBfTag:\n"));
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 4);
+ for (profileNum=0; profileNum<4; profileNum++)
+ displayTagfield(pAd, profileNum, FALSE);
+ }
+
+ if (argVal==0 || argVal==2) {
+ /* Display Implicit tagfield */
+ DBGPRINT(RT_DEBUG_OFF, ("---Implicit TxBfTag:\n"));
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 0);
+ for (profileNum=0; profileNum<4; profileNum++)
+ displayTagfield(pAd, profileNum, TRUE);
+ }
+
+ if (argVal==3) {
+ int i;
+ /* 4. Dump power table */
+ for (i = 0; i < (14 + 12 + 16 + 7); i++)
+ DBGPRINT(RT_DEBUG_OFF, ("%d: Ch%2d=[%d, %d %d]\n", i,
+ pAd->TxPower[i].Channel, pAd->TxPower[i].Power,
+ pAd->TxPower[i].Power2, pAd->TxPower[i].Power3));
+ }
+
+ return TRUE;
+}
+
+
+/*
+ Set_InvTxBfTag_Proc - Invalidate BF Profile Tags
+ usage: "iwpriv ra0 set InvTxBfTag=n"
+ Reset Valid bit and zero out MAC address of each profile. The next profile will be stored in profile 0
+*/
+INT Set_InvTxBfTag_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int profileNum;
+ UCHAR row[EXP_MAX_BYTES];
+ UCHAR r163Value = 0;
+
+ /* Disable Profile Updates during access */
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R163, &r163Value);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R163, r163Value & ~0x88);
+
+ /* Invalidate Implicit tags */
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 0);
+ for (profileNum=0; profileNum<4; profileNum++) {
+ Read_TagField(pAd, row, profileNum);
+ row[0] &= 0x7F;
+ row[1] = row[2] = row[3] = row[4] = row[5] = row[6] = 0xAA;
+ Write_TagField(pAd, row, profileNum);
+ }
+
+ /* Invalidate Explicit tags */
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 4);
+ for (profileNum=0; profileNum<4; profileNum++) {
+ Read_TagField(pAd, row, profileNum);
+ row[0] &= 0x7F;
+ row[1] = row[2] = row[3] = row[4] = row[5] = row[6] = 0x55;
+ Write_TagField(pAd, row, profileNum);
+ }
+
+ /* Restore Profile Updates */
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R163, r163Value);
+
+ return TRUE;
+}
+
+
+/*
+ Set_ITxBfTimeout_Proc - Set ITxBF timeout value
+ usage: iwpriv ra0 set ITxBfTimeout=<decimal timeout in units of 25 microsecs>
+*/
+INT Set_ITxBfTimeout_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG t = simple_strtol(arg, 0, 10);
+
+ if (t > 65535) {
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_ITxBfTimeout_Proc: value > 65535!\n"));
+ return FALSE;
+ }
+
+ pAd->CommonCfg.ITxBfTimeout = t;
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 0x02);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R180, 0);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R182, pAd->CommonCfg.ITxBfTimeout & 0xFF);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R180, 1);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R182, (pAd->CommonCfg.ITxBfTimeout>>8) & 0xFF);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_ITxBfTimeout_Proc::(ITxBfTimeout=%d)\n", (int)pAd->CommonCfg.ITxBfTimeout));
+ return TRUE;
+}
+
+
+/*
+ Set_ETxBfTimeout_Proc - Set ITxBF timeout value
+ usage: iwpriv ra0 set ETxBfTimeout=<decimal timeout in units of 25 microsecs>
+*/
+INT Set_ETxBfTimeout_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG t = simple_strtol(arg, 0, 10);
+
+ if (t > 65535) {
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_ETxBfTimeout_Proc: value > 65535!\n"));
+ return FALSE;
+ }
+
+ pAd->CommonCfg.ETxBfTimeout = t;
+ RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_3, pAd->CommonCfg.ETxBfTimeout);
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_ETxBfTimeout_Proc::(ETxBfTimeout=%d)\n", (int)pAd->CommonCfg.ETxBfTimeout));
+ return TRUE;
+}
+
+
+/*
+ Set_ETxBfCodebook_Proc - Set ETxBf Codebook
+ usage: iwpriv ra0 set ETxBfCodebook=0 to 3
+*/
+INT Set_ETxBfCodebook_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ TX_TXBF_CFG_0_STRUC regValue;
+ ULONG t = simple_strtol(arg, 0, 10);
+
+ if (t > 3) {
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_ETxBfCodebook_Proc: value > 3!\n"));
+ return FALSE;
+ }
+
+ RTMP_IO_READ32(pAd, TX_TXBF_CFG_0, &regValue.word);
+ regValue.field.EtxbfFbkCode = t;
+ RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_0, regValue.word);
+ return TRUE;
+}
+
+
+/*
+ Set_ETxBfCoefficient_Proc - Set ETxBf Coefficient
+ usage: iwpriv ra0 set ETxBfCoefficient=0 to 3
+*/
+INT Set_ETxBfCoefficient_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ TX_TXBF_CFG_0_STRUC regValue;
+ ULONG t = simple_strtol(arg, 0, 10);
+
+ if (t > 3) {
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_ETxBfCoefficient_Proc: value > 3!\n"));
+ return FALSE;
+ }
+
+ RTMP_IO_READ32(pAd, TX_TXBF_CFG_0, &regValue.word);
+ regValue.field.EtxbfFbkCoef = t;
+ RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_0, regValue.word);
+ return TRUE;
+}
+
+
+/*
+ Set_ETxBfGrouping_Proc - Set ETxBf Grouping
+ usage: iwpriv ra0 set ETxBfGrouping=0 to 2
+*/
+INT Set_ETxBfGrouping_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ TX_TXBF_CFG_0_STRUC regValue;
+ ULONG t = simple_strtol(arg, 0, 10);
+
+ if (t > 2) {
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_ETxBfGrouping_Proc: value > 2!\n"));
+ return FALSE;
+ }
+
+ RTMP_IO_READ32(pAd, TX_TXBF_CFG_0, &regValue.word);
+ regValue.field.EtxbfFbkNg = t;
+ RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_0, regValue.word);
+ return TRUE;
+}
+
+
+/*
+ Set_ETxBfNoncompress_Proc - Set ETxBf Noncompress option
+ usage: iwpriv ra0 set ETxBfNoncompress=0 or 1
+*/
+INT Set_ETxBfNoncompress_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG t = simple_strtol(arg, 0, 10);
+
+ if (t > 1) {
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_ETxBfNoncompress_Proc: value > 1!\n"));
+ return FALSE;
+ }
+
+ pAd->CommonCfg.ETxBfNoncompress = t;
+ return TRUE;
+}
+
+
+/*
+ Set_ETxBfIncapable_Proc - Set ETxBf Incapable option
+ usage: iwpriv ra0 set ETxBfIncapable=0 or 1
+*/
+INT Set_ETxBfIncapable_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG t = simple_strtol(arg, 0, 10);
+
+ if (t > 1)
+ return FALSE;
+
+ pAd->CommonCfg.ETxBfIncapable = t;
+ setETxBFCap(pAd, &pAd->CommonCfg.HtCapability.TxBFCap);
+
+ return TRUE;
+}
+
+
+/*
+ Set_ITxBfDivCal_Proc - Calculate ITxBf Divider Calibration parameters
+ usage: iwpriv ra0 set ITxBfDivCal=dd
+ 0=>display calibration parameters
+ 1=>update EEPROM values
+ 2=>update BBP R176
+ 10=>display calibration parameters and dump capture data
+ 11=>Skip divider calibration, just capture and dump capture data
+*/
+INT Set_ITxBfDivCal_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int calFunction;
+
+ calFunction = simple_strtol(arg, 0, 10);
+
+ return ITxBFDividerCalibration(pAd, calFunction, 0, NULL);
+}
+
+
+/*
+ Set_ITxBfLNACal_Proc - Calculate ITxBf LNA Calibration parameters
+ usage: iwpriv ra0 set ITxBfLnaCal=dd
+ 0=>display calibration parameters
+ 1=>update EEPROM values
+ 2=>update BBP R174
+ 10=>display calibration parameters and dump capture data
+*/
+INT Set_ITxBfLnaCal_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR channel = pAd->CommonCfg.Channel;
+ int calFunction;
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ channel = pAd->ate.Channel;
+#endif /* RALINK_ATE */
+
+ calFunction = simple_strtol(arg, 0, 10);
+
+ return ITxBFLNACalibration(pAd, calFunction, 0, channel<=14);
+}
+
+
+/*
+ Set_ITxBfCal_Proc - Calculate ITxBf Calibration parameters
+ usage: "iwpriv ra0 set ITxBfCal=[0 | 1]"
+ 0=>calculate values, 1=>update BBP and EEPROM
+*/
+INT Set_ITxBfCal_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ int calFunction = simple_strtol(arg, 0, 10);
+ int calParams[2];
+ int ret;
+ UCHAR channel = pAd->CommonCfg.Channel;
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ channel = pAd->ate.Channel;
+#endif /* RALINK_ATE */
+
+ ret = iCalcCalibration(pAd, calParams, 0);
+ if (ret < 0) {
+ if (ret == -3)
+ DBGPRINT(RT_DEBUG_OFF, ("Set_ITxBfCal_Proc: kmalloc failed\n"));
+ else if (ret == -2)
+ DBGPRINT(RT_DEBUG_OFF, ("Set_ITxBfCal_Proc: MAC Address mismatch\n"));
+ else
+ DBGPRINT(RT_DEBUG_OFF, ("Set_ITxBfCal_Proc: Invalid profiles\n"));
+ return FALSE;
+ }
+
+ /* Display result */
+ DBGPRINT((calFunction==0? RT_DEBUG_OFF: RT_DEBUG_WARN),
+ ("ITxBfCal Result = [0x%02x 0x%02x]\n", calParams[0], calParams[1]));
+
+#ifdef RALINK_ATE
+ pAd->ate.calParams[0] = (UCHAR)calParams[0];
+ pAd->ate.calParams[1] = (UCHAR)calParams[1];
+
+ /* Double check */
+ DBGPRINT((calFunction==0? RT_DEBUG_OFF: RT_DEBUG_WARN),
+ ("ITxBfCal Result in ATE = [0x%02x 0x%02x]\n", pAd->ate.calParams[0], pAd->ate.calParams[1]));
+#endif /* RALINK_ATE */
+
+ /* Update BBP R176 and EEPROM for Ant 0 and 2 */
+ if (calFunction == 1) {
+ UCHAR r27Value = 0, r173Value = 0;
+ ITXBF_PHASE_PARAMS phaseParams;
+ UCHAR divPhase[2] = {0}, phaseValues[2] = {0};
+
+ /* Read R173 to see if Phase compensation is already enabled */
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R173, &r173Value);
+
+ /* Select Ant 0 */
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &r27Value);
+ r27Value &= ~0x60;
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, r27Value);
+
+ /* Update R176 */
+ if (r173Value & 0x08) {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R176, &phaseValues[0]);
+ phaseValues[0] += calParams[0];
+ }
+ else
+ phaseValues[0] = calParams[0];
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R176, phaseValues[0]);
+
+ /* Select Ant 2 */
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, r27Value | 0x40);
+
+ /* Update R176 */
+ if (r173Value & 0x08) {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R176, &phaseValues[1]);
+ phaseValues[1] += calParams[1];
+ }
+ else
+ phaseValues[1] = calParams[1];
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R176, phaseValues[1]);
+
+ /* Enable TX Phase Compensation */
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R173, r173Value | 0x08);
+
+ /* Remove Divider phase */
+ ITxBFDividerCalibration(pAd, 3, 0, divPhase);
+ phaseValues[0] -= divPhase[0];
+ phaseValues[1] -= divPhase[1];
+
+ /* Update EEPROM */
+
+ ITxBFGetEEPROM(pAd, &phaseParams, 0, 0);
+
+ /* Only allow calibration on specific channels */
+ if (channel == 1) {
+ phaseParams.gBeg[0] = phaseValues[0];
+ phaseParams.gBeg[1] = phaseValues[1];
+ }
+ else if (channel == 14) {
+ phaseParams.gEnd[0] = phaseValues[0];
+ phaseParams.gEnd[1] = phaseValues[1];
+ }
+ else if (channel == 36) {
+ phaseParams.aLowBeg[0] = phaseValues[0];
+ phaseParams.aLowBeg[1] = phaseValues[1];
+ }
+ else if (channel == 64) {
+ phaseParams.aLowEnd[0] = phaseValues[0];
+ phaseParams.aLowEnd[1] = phaseValues[1];
+ }
+ else if (channel == 100) {
+ phaseParams.aMidBeg[0] = phaseValues[0];
+ phaseParams.aMidBeg[1] = phaseValues[1];
+ }
+ else if (channel == 128) {
+ phaseParams.aMidEnd[0] = phaseValues[0];
+ phaseParams.aMidEnd[1] = phaseValues[1];
+ }
+ else if (channel == 132) {
+ phaseParams.aHighBeg[0] = phaseValues[0];
+ phaseParams.aHighBeg[1] = phaseValues[1];
+ }
+ else if (channel == 165) {
+ phaseParams.aHighEnd[0] = phaseValues[0];
+ phaseParams.aHighEnd[1] = phaseValues[1];
+ }
+ else {
+ DBGPRINT(RT_DEBUG_OFF,
+ ("Invalid channel: %d\nMust calibrate channel 1, 14, 36, 64, 100, 128, 132 or 165", channel) );
+ return FALSE;
+ }
+ ITxBFSetEEPROM(pAd, &phaseParams, 0, 0);
+
+ DBGPRINT(RT_DEBUG_WARN, ("Set_ITxBfCal_Proc: Calibration Parameters updated\n"));
+ }
+
+ return TRUE;
+}
+
+
+/*
+ Set_ETxBfEnCond_Proc - enable/disable ETxBF
+ usage: iwpriv ra0 set ETxBfEnCond=dd
+ 0=>disable, 1=>enable
+ Note: After use this command, need to re-run apStartup()/LinkUp() operations to sync all status.
+ If ETxBfIncapable!=0 then we don't need to reassociate.
+*/
+INT Set_ETxBfEnCond_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR i, enableETxBf;
+ MAC_TABLE_ENTRY *pEntry;
+ UINT8 byteValue;
+
+ enableETxBf = simple_strtol(arg, 0, 10);
+
+ if (enableETxBf > 1)
+ return FALSE;
+
+ pAd->CommonCfg.ETxBfEnCond = enableETxBf && (pAd->Antenna.field.TxPath > 1);
+ pAd->CommonCfg.RegTransmitSetting.field.TxBF = enableETxBf==0? 0: 1;
+
+ setETxBFCap(pAd, &pAd->CommonCfg.HtCapability.TxBFCap);
+ rtmp_asic_set_bf(pAd);
+
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ pEntry = &pAd->MacTab.Content[i];
+ if (!IS_ENTRY_NONE(pEntry))
+ {
+ pEntry->eTxBfEnCond = clientSupportsETxBF(pAd, &pEntry->HTCapability.TxBFCap)? enableETxBf: 0;
+ pEntry->bfState = READY_FOR_SNDG0;
+ }
+ }
+
+
+ if (pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn || enableETxBf)
+ {
+ RT30xxReadRFRegister(pAd, RF_R39, (PUCHAR)&byteValue);
+ byteValue |= 0x40;
+ RT30xxWriteRFRegister(pAd, RF_R39, (UCHAR)byteValue);
+
+ RT30xxReadRFRegister(pAd, RF_R49, (PUCHAR)&byteValue);
+ byteValue |= 0x20;
+ RT30xxWriteRFRegister(pAd, RF_R49, (UCHAR)byteValue);
+ }
+ else
+ {
+ /* depends on Gary Tsao's comments. we shall disable it */
+ if (pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn == 0)
+ {
+ RT30xxReadRFRegister(pAd, RF_R39, (PUCHAR)&byteValue);
+ byteValue &= (~0x40);
+ RT30xxWriteRFRegister(pAd, RF_R39, (UCHAR)byteValue);
+
+ RT30xxReadRFRegister(pAd, RF_R49, (PUCHAR)&byteValue);
+ byteValue &= (~0x20);
+ RT30xxWriteRFRegister(pAd, RF_R49, (UCHAR)byteValue);
+ }
+ }
+
+
+ return TRUE;
+}
+
+INT Set_NoSndgCntThrd_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR i;
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++){
+ pAd->MacTab.Content[i].noSndgCntThrd = simple_strtol(arg, 0, 10);
+ }
+ return TRUE;
+}
+
+INT Set_NdpSndgStreams_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR i;
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++){
+ pAd->MacTab.Content[i].ndpSndgStreams = simple_strtol(arg, 0, 10);
+ }
+ return TRUE;
+}
+
+
+INT Set_Trigger_Sounding_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR macAddr[MAC_ADDR_LEN];
+ CHAR *value;
+ INT i;
+ MAC_TABLE_ENTRY *pEntry = NULL;
+
+ /* Mac address acceptable format 01:02:03:04:05:06 length 17 */
+ if(strlen(arg) != 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++], 1);
+ }
+
+ /*DBGPRINT(RT_DEBUG_TRACE, ("TriggerSounding=%02x:%02x:%02x:%02x:%02x:%02x\n",*/
+ /* macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5], macAddr[6]) );*/
+ pEntry = MacTableLookup(pAd, macAddr);
+ if (pEntry==NULL)
+ return FALSE;
+
+ Trigger_Sounding_Packet(pAd, SNDG_TYPE_SOUNDING, 0, pEntry->sndgMcs, pEntry);
+
+ return TRUE;
+}
+
+/*
+ Set_ITxBfEn_Proc - enable/disable ITxBF
+ usage: iwpriv ra0 set ITxBfEn=dd
+ 0=>disable, 1=>enable
+*/
+INT Set_ITxBfEn_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR i;
+ UCHAR enableITxBF;
+ BOOLEAN bCalibrated;
+ UINT8 byteValue;
+
+ enableITxBF = simple_strtol(arg, 0, 10);
+
+ if (enableITxBF > 1)
+ return FALSE;
+
+ bCalibrated = rtmp_chk_itxbf_calibration(pAd);
+ DBGPRINT(RT_DEBUG_TRACE, ("Set ITxBfEn=%d, calibration of ITxBF=%d, so enableITxBF=%d!\n",
+ enableITxBF , bCalibrated, (enableITxBF & bCalibrated)));
+
+ enableITxBF &= bCalibrated;
+
+ pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn = enableITxBF && (pAd->Antenna.field.TxPath > 1);
+
+ rtmp_asic_set_bf(pAd);
+
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ MAC_TABLE_ENTRY *pMacEntry = &pAd->MacTab.Content[i];
+ if ((!IS_ENTRY_NONE(pMacEntry)) && (pAd->Antenna.field.TxPath> 1))
+ pMacEntry->iTxBfEn = enableITxBF;
+ }
+
+ if (enableITxBF || pAd->CommonCfg.ETxBfEnCond)
+ {
+ RT30xxReadRFRegister(pAd, RF_R39, (PUCHAR)&byteValue);
+ byteValue |= 0x40;
+ RT30xxWriteRFRegister(pAd, RF_R39, (UCHAR)byteValue);
+
+ RT30xxReadRFRegister(pAd, RF_R49, (PUCHAR)&byteValue);
+ byteValue |= 0x20;
+ RT30xxWriteRFRegister(pAd, RF_R49, (UCHAR)byteValue);
+ }
+
+ /* If enabling ITxBF then set LNA compensation, do a Divider Calibration and update BBP registers */
+ if (enableITxBF) {
+ ITxBFLoadLNAComp(pAd);
+ ITxBFDividerCalibration(pAd, 2, 0, NULL);
+ }
+ else
+ {
+ /* depends on Gary Tsao's comments. */
+ if (pAd->CommonCfg.ETxBfEnCond == 0)
+ {
+ RT30xxReadRFRegister(pAd, RF_R39, (PUCHAR)&byteValue);
+ byteValue &= (~0x40);
+ RT30xxWriteRFRegister(pAd, RF_R39, (UCHAR)byteValue);
+
+ RT30xxReadRFRegister(pAd, RF_R49, (PUCHAR)&byteValue);
+ byteValue &= (~0x20);
+ RT30xxWriteRFRegister(pAd, RF_R49, (UCHAR)byteValue);
+ }
+
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R173, 0);
+
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R27, &byteValue);
+ byteValue &= ~0x60;
+ for ( i = 0; i < 3; i++)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, (byteValue & (i << 5)));
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R174, 0);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R176, 0);
+ }
+ }
+ return TRUE;
+}
+#endif /* TXBF_SUPPORT */
+
+
+#ifdef DOT11_N_SUPPORT
+void assoc_ht_info_debugshow(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN UCHAR ht_cap_len,
+ IN HT_CAPABILITY_IE *pHTCapability)
+{
+ HT_CAP_INFO *pHTCap;
+ HT_CAP_PARM *pHTCapParm;
+ EXT_HT_CAP_INFO *pExtHT;
+#ifdef TXBF_SUPPORT
+ HT_BF_CAP *pBFCap;
+#endif /* TXBF_SUPPORT */
+
+
+ if (pHTCapability && (ht_cap_len > 0))
+ {
+ pHTCap = &pHTCapability->HtCapInfo;
+ pHTCapParm = &pHTCapability->HtCapParm;
+ pExtHT = &pHTCapability->ExtHtCapInfo;
+#ifdef TXBF_SUPPORT
+ pBFCap = &pHTCapability->TxBFCap;
+#endif /* TXBF_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Peer - 11n HT Info\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("\tHT Cap Info: \n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\t AdvCode(%d), BW(%d), MIMOPS(%d), GF(%d), ShortGI_20(%d), ShortGI_40(%d)\n",
+ pHTCap->AdvCoding, pHTCap->ChannelWidth, pHTCap->MimoPs, pHTCap->GF,
+ pHTCap->ShortGIfor20, pHTCap->ShortGIfor40));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\t TxSTBC(%d), RxSTBC(%d), DelayedBA(%d), A-MSDU(%d), CCK_40(%d)\n",
+ pHTCap->TxSTBC, pHTCap->RxSTBC, pHTCap->DelayedBA, pHTCap->AMsduSize, pHTCap->CCKmodein40));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\t PSMP(%d), Forty_Mhz_Intolerant(%d), L-SIG(%d)\n",
+ pHTCap->PSMP, pHTCap->Forty_Mhz_Intolerant, pHTCap->LSIGTxopProSup));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("\tHT Parm Info: \n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\t MaxRx A-MPDU Factor(%d), MPDU Density(%d)\n",
+ pHTCapParm->MaxRAmpduFactor, pHTCapParm->MpduDensity));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("\tHT MCS set: \n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\t RxMCS(%02x %02x %02x %02x %02x) MaxRxMbps(%d) TxMCSSetDef(%02x)\n",
+ pHTCapability->MCSSet[0], pHTCapability->MCSSet[1], pHTCapability->MCSSet[2],
+ pHTCapability->MCSSet[3], pHTCapability->MCSSet[4],
+ (pHTCapability->MCSSet[11]<<8) + pHTCapability->MCSSet[10],
+ pHTCapability->MCSSet[12]));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("\tExt HT Cap Info: \n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\t PCO(%d), TransTime(%d), MCSFeedback(%d), +HTC(%d), RDG(%d)\n",
+ pExtHT->Pco, pExtHT->TranTime, pExtHT->MCSFeedback, pExtHT->PlusHTC, pExtHT->RDGSupport));
+
+#ifdef TXBF_SUPPORT
+ DBGPRINT(RT_DEBUG_TRACE, ("\tTX BF Cap: \n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\t ImpRxCap(%d), RXStagSnd(%d), TXStagSnd(%d), RxNDP(%d), TxNDP(%d) ImpTxCap(%d)\n",
+ pBFCap->TxBFRecCapable, pBFCap->RxSoundCapable, pBFCap->TxSoundCapable,
+ pBFCap->RxNDPCapable, pBFCap->TxNDPCapable, pBFCap->ImpTxBFCapable));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\t Calibration(%d), ExpCSICapable(%d), ExpComSteerCapable(%d), ExpCSIFbk(%d), ExpNoComBF(%d) ExpComBF(%d)\n",
+ pBFCap->Calibration, pBFCap->ExpCSICapable, pBFCap->ExpComSteerCapable,
+ pBFCap->ExpCSIFbk, pBFCap->ExpNoComBF, pBFCap->ExpComBF));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\t MinGrouping(%d), CSIBFAntSup(%d), NoComSteerBFAntSup(%d), ComSteerBFAntSup(%d), CSIRowBFSup(%d) ChanEstimation(%d)\n",
+ pBFCap->MinGrouping, pBFCap->CSIBFAntSup, pBFCap->NoComSteerBFAntSup,
+ pBFCap->ComSteerBFAntSup, pBFCap->CSIRowBFSup, pBFCap->ChanEstimation));
+#endif /* TXBF_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("\nPeer - MODE=%d, BW=%d, MCS=%d, ShortGI=%d, MaxRxFactor=%d, MpduDensity=%d, MIMOPS=%d, AMSDU=%d\n",
+ pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.BW,
+ pEntry->HTPhyMode.field.MCS, pEntry->HTPhyMode.field.ShortGI,
+ pEntry->MaxRAmpduFactor, pEntry->MpduDensity,
+ pEntry->MmpsMode, pEntry->AMsduSize));
+
+#ifdef DOT11N_DRAFT3
+ DBGPRINT(RT_DEBUG_TRACE, ("\tExt Cap Info: \n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\tBss2040CoexistMgmt=%d\n", pEntry->BSS2040CoexistenceMgmtSupport));
+#endif /* DOT11N_DRAFT3 */
+ }
+}
+
+
+INT Set_BurstMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value == 1)
+ {
+ pAd->CommonCfg.bRalinkBurstMode= TRUE;
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE);
+ AsicEnableRalinkBurstMode(pAd);
+ }
+ else
+ {
+ pAd->CommonCfg.bRalinkBurstMode = FALSE;
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE);
+ AsicDisableRalinkBurstMode(pAd);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_BurstMode_Proc ::%s\n",
+ (pAd->CommonCfg.bRalinkBurstMode == TRUE) ? "enabled" : "disabled"));
+
+ return TRUE;
+}
+#endif /* DOT11_N_SUPPORT */
+
+
+#ifdef DOT11_VHT_AC
+VOID assoc_vht_info_debugshow(
+ IN RTMP_ADAPTER *pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN VHT_CAP_IE *vht_cap,
+ IN VHT_OP_IE *vht_op)
+{
+ VHT_CAP_INFO *cap_info;
+ VHT_MCS_SET *mcs_set;
+ VHT_OP_INFO *op_info;
+ VHT_MCS_MAP *mcs_map;
+
+
+ if (!WMODE_CAP_AC(pAd->CommonCfg.PhyMode))
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Peer - 11AC VHT Info\n"));
+ if (vht_cap)
+ {
+ cap_info = &vht_cap->vht_cap;
+ mcs_set = &vht_cap->mcs_set;
+
+ hex_dump("peer vht_cap raw data", (UCHAR *)cap_info, sizeof(VHT_CAP_INFO));
+ hex_dump("peer vht_mcs raw data", (UCHAR *)mcs_set, sizeof(VHT_MCS_SET));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("\tVHT Cap Info: \n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\tMaxMpduLen(%d), BW(%d), SGI_80M(%d), TxSTBC(%d), RxSTBC(%d), +HTC-VHT(%d)\n",
+ cap_info->max_mpdu_len, cap_info->ch_width, cap_info->sgi_80M, cap_info->tx_stbc,
+ cap_info->rx_stbc, cap_info->htc_vht_cap));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\tMaxAmpduExp(%d), VhtLinkAdapt(%d), RxAntConsist(%d), TxAntConsist(%d)\n",
+ cap_info->max_ampdu_exp, cap_info->vht_link_adapt, cap_info->rx_ant_consistency, cap_info->tx_ant_consistency));
+ mcs_map = &mcs_set->rx_mcs_map;
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\tRxMcsSet: HighRate(%d), RxMCSMap(%d,%d,%d,%d,%d,%d,%d)\n",
+ mcs_set->rx_high_rate, mcs_map->mcs_ss1, mcs_map->mcs_ss2, mcs_map->mcs_ss3,
+ mcs_map->mcs_ss4, mcs_map->mcs_ss5, mcs_map->mcs_ss6, mcs_map->mcs_ss7));
+ mcs_map = &mcs_set->tx_mcs_map;
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\tTxMcsSet: HighRate(%d), TxMcsMap(%d,%d,%d,%d,%d,%d,%d)\n",
+ mcs_set->tx_high_rate, mcs_map->mcs_ss1, mcs_map->mcs_ss2, mcs_map->mcs_ss3,
+ mcs_map->mcs_ss4, mcs_map->mcs_ss5, mcs_map->mcs_ss6, mcs_map->mcs_ss7));
+ }
+
+ if (vht_op)
+ {
+ op_info = &vht_op->vht_op_info;
+ mcs_map = &vht_op->basic_mcs_set;
+ DBGPRINT(RT_DEBUG_TRACE, ("\tHT OP Info: \n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\tChannel Width(%d), CenteralFreq1(%d), CenteralFreq2(%d)\n",
+ op_info->ch_width, op_info->center_freq_1, op_info->center_freq_2));
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\tBasicMCSSet(SS1:%d, SS2:%d, SS3:%d, SS4:%d, SS5:%d, SS6:%d, SS7:%d)\n",
+ mcs_map->mcs_ss1, mcs_map->mcs_ss2, mcs_map->mcs_ss3,
+ mcs_map->mcs_ss4, mcs_map->mcs_ss5, mcs_map->mcs_ss6,
+ mcs_map->mcs_ss7));
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("\n"));
+
+}
+#endif /* DOT11_VHT_AC */
+
+
+INT Set_RateAdaptInterval(
+ IN RTMP_ADAPTER *pAd,
+ IN PSTRING arg)
+{
+ UINT32 ra_time, ra_qtime;
+ PSTRING token;
+ char sep = ':';
+ ULONG irqFlags;
+
+/*
+ The ra_interval inupt string format should be d:d, in units of ms.
+ =>The first decimal number indicates the rate adaptation checking period,
+ =>The second decimal number indicates the rate adaptation quick response checking period.
+*/
+ DBGPRINT(RT_DEBUG_TRACE,("%s():%s\n", __FUNCTION__, arg));
+
+ token = strchr(arg, sep);
+ if (token != NULL)
+ {
+ *token = '\0';
+
+ if (strlen(arg) && strlen(token+1))
+ {
+ ra_time = simple_strtol(arg, 0, 10);
+ ra_qtime = simple_strtol(token+1, 0, 10);
+ DBGPRINT(RT_DEBUG_OFF, ("%s():Set RateAdaptation TimeInterval as(%d:%d) ms\n",
+ __FUNCTION__, ra_time, ra_qtime));
+
+ RTMP_IRQ_LOCK(&pAd->irq_lock, irqFlags);
+ pAd->ra_interval = ra_time;
+ pAd->ra_fast_interval = ra_qtime;
+#ifdef CONFIG_AP_SUPPORT
+ if (pAd->ApCfg.ApQuickResponeForRateUpTimerRunning == TRUE)
+ {
+ BOOLEAN Cancelled;
+
+ RTMPCancelTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, &Cancelled);
+ pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = FALSE;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqFlags);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+
+}
+
+
+INT Set_VcoPeriod_Proc(
+ IN RTMP_ADAPTER *pAd,
+ IN PSTRING arg)
+{
+ pAd->chipCap.VcoPeriod = simple_strtol(arg, 0, 10);
+
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("VCO Period = %d seconds\n", pAd->chipCap.VcoPeriod));
+ return TRUE;
+}
+
+#ifdef SINGLE_SKU
+INT Set_ModuleTxpower_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UINT16 Value;
+
+ if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Do NOT accept this command after interface is up.\n"));
+ return FALSE;
+ }
+
+ Value = (UINT16)simple_strtol(arg, 0, 10);
+ pAd->CommonCfg.ModuleTxpower = Value;
+ DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ModuleTxpower_Proc::(ModuleTxpower=%d)\n", pAd->CommonCfg.ModuleTxpower));
+ return TRUE;
+}
+#endif /* SINGLE_SKU */
+
+
+#ifdef FPGA_MODE
+INT set_tx_kickcnt(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ pAd->tx_kick_cnt = (INT)simple_strtol(arg, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():tx_kick_cnt=%d\n", __FUNCTION__, pAd->tx_kick_cnt));
+
+ return TRUE;
+}
+
+
+INT set_data_phy_mode(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ pAd->data_phy = (INT)simple_strtol(arg, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): data_phy=%d\n", __FUNCTION__, pAd->data_phy));
+
+ return TRUE;
+}
+
+
+INT set_data_bw(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ pAd->data_bw = (UCHAR)simple_strtol(arg, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): data_bw=%d\n", __FUNCTION__, pAd->data_bw));
+
+ return TRUE;
+}
+
+
+INT set_data_mcs(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ UCHAR mcs = (UCHAR)simple_strtol(arg, 0, 10);
+
+ pAd->data_mcs = ((mcs / 10) <<4) | (mcs % 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): data_mcs=%d\n", __FUNCTION__, pAd->data_mcs));
+
+ return TRUE;
+}
+
+
+INT set_data_gi(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ pAd->data_gi = (UCHAR)simple_strtol(arg, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): data_gi=%d\n", __FUNCTION__, pAd->data_gi));
+
+ return TRUE;
+}
+
+
+INT set_data_basize(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ pAd->data_basize = (UCHAR)simple_strtol(arg, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): data_basize=%d\n", __FUNCTION__, pAd->data_basize));
+
+ return TRUE;
+}
+
+
+INT set_fpga_mode(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ ULONG fpga_on;
+
+ fpga_on = simple_strtol(arg, 0, 10);
+
+ if (fpga_on & 2)
+ {
+ pAd->data_phy = MODE_VHT;
+ pAd->data_bw = BW_80;
+ pAd->data_gi = 1;
+ pAd->data_mcs = 7;
+ pAd->data_basize = 31;
+#ifdef CONFIG_AP_SUPPORT
+ pAd->ApCfg.MBSSID[0].bAutoTxRateSwitch = FALSE;
+#endif /* CONFIG_AP_SUPPORT */
+ } else {
+#ifdef CONFIG_AP_SUPPORT
+ pAd->ApCfg.MBSSID[0].bAutoTxRateSwitch = TRUE;
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+ if (fpga_on & 4)
+ pAd->data_mcs = (1 <<4) | 7;
+
+ pAd->fpga_on = fpga_on;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): fpga_on=%d\n", __FUNCTION__, pAd->fpga_on));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): data_phy=%d\n", __FUNCTION__, pAd->data_phy));
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): data_bw=%d\n", __FUNCTION__, pAd->data_bw));
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): data_mcs=%d\n", __FUNCTION__, pAd->data_mcs));
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): data_gi=%d\n", __FUNCTION__, pAd->data_gi));
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): data_basize=%d\n", __FUNCTION__, pAd->data_basize));
+
+#ifdef CONFIG_AP_SUPPORT
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): bAutoTxRateSwitch=%d\n",
+ __FUNCTION__,
+ pAd->ApCfg.MBSSID[0].bAutoTxRateSwitch));
+#endif /* CONFIG_AP_SUPPORT */
+
+ return TRUE;
+}
+
+#endif /* FPGA_MODE */
+
+#ifdef WFA_VHT_PF
+INT set_force_amsdu(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ pAd->force_amsdu = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): force_amsdu=%d\n",
+ __FUNCTION__, pAd->force_amsdu));
+ return TRUE;
+}
+#endif /* WFA_VHT_PF */
+
+#ifdef RLT_RF
+INT set_rf(RTMP_ADAPTER *pAd, PSTRING arg)
+{
+ INT bank_id = 0, rf_id = 0, rv = 0;
+ UCHAR rf_val = 0;
+
+ if (arg)
+ {
+ rv = sscanf(arg, "%d-%d-%x", &(bank_id), &(rf_id), &(rf_val));
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():rv = %d, bank_id = %d, rf_id = %d, rf_val = 0x%02x\n", __FUNCTION__, rv, bank_id, rf_id, rf_val));
+ if (rv == 3)
+ {
+ rlt_rf_write(pAd, (UCHAR)bank_id, (UCHAR)rf_id, (UCHAR)rf_val);
+
+ rlt_rf_read(pAd, bank_id, rf_id, &rf_val);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():%d %03d 0x%02X\n", __FUNCTION__, bank_id, rf_id, rf_val));
+ }
+ else if (rv == 2)
+ {
+ rlt_rf_read(pAd, bank_id, rf_id, &rf_val);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():%d %03d 0x%02X\n", __FUNCTION__, bank_id, rf_id, rf_val));
+ }
+ }
+
+ return TRUE;
+}
+#endif /* RLT_RF */
+
+static struct {
+ PSTRING name;
+ INT (*show_proc)(PRTMP_ADAPTER pAdapter, PSTRING arg, ULONG BufLen);
+} *PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC, RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC[] = {
+#ifdef DBG
+ {"SSID", Show_SSID_Proc},
+ {"WirelessMode", Show_WirelessMode_Proc},
+ {"TxBurst", Show_TxBurst_Proc},
+ {"TxPreamble", Show_TxPreamble_Proc},
+ {"TxPower", Show_TxPower_Proc},
+ {"Channel", Show_Channel_Proc},
+ {"BGProtection", Show_BGProtection_Proc},
+ {"RTSThreshold", Show_RTSThreshold_Proc},
+ {"FragThreshold", Show_FragThreshold_Proc},
+#ifdef DOT11_N_SUPPORT
+ {"HtBw", Show_HtBw_Proc},
+ {"HtMcs", Show_HtMcs_Proc},
+ {"HtGi", Show_HtGi_Proc},
+ {"HtOpMode", Show_HtOpMode_Proc},
+ {"HtExtcha", Show_HtExtcha_Proc},
+ {"HtMpduDensity", Show_HtMpduDensity_Proc},
+ {"HtBaWinSize", Show_HtBaWinSize_Proc},
+ {"HtRdg", Show_HtRdg_Proc},
+ {"HtAmsdu", Show_HtAmsdu_Proc},
+ {"HtAutoBa", Show_HtAutoBa_Proc},
+#endif /* DOT11_N_SUPPORT */
+ {"CountryRegion", Show_CountryRegion_Proc},
+ {"CountryRegionABand", Show_CountryRegionABand_Proc},
+ {"CountryCode", Show_CountryCode_Proc},
+#ifdef AGGREGATION_SUPPORT
+ {"PktAggregate", Show_PktAggregate_Proc},
+#endif
+
+#ifdef WMM_SUPPORT
+ {"WmmCapable", Show_WmmCapable_Proc},
+#endif
+ {"IEEE80211H", Show_IEEE80211H_Proc},
+ {"AuthMode", Show_AuthMode_Proc},
+ {"EncrypType", Show_EncrypType_Proc},
+ {"DefaultKeyID", Show_DefaultKeyID_Proc},
+ {"Key1", Show_Key1_Proc},
+ {"Key2", Show_Key2_Proc},
+ {"Key3", Show_Key3_Proc},
+ {"Key4", Show_Key4_Proc},
+ {"PMK", Show_PMK_Proc},
+#ifdef SINGLE_SKU
+ {"ModuleTxpower", Show_ModuleTxpower_Proc},
+#endif /* SINGLE_SKU */
+#endif /* DBG */
+ {"rainfo", Show_STA_RAInfo_Proc},
+ {NULL, NULL}
+};
+
+
+INT RTMPShowCfgValue(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING pName,
+ IN PSTRING pBuf,
+ IN UINT32 MaxLen)
+{
+ INT Status = 0;
+
+ for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++)
+ {
+ if (!strcmp(pName, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name))
+ {
+ if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->show_proc(pAd, pBuf, MaxLen))
+ Status = -EINVAL;
+ break; /*Exit for loop.*/
+ }
+ }
+
+ if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name == NULL)
+ {
+ snprintf(pBuf, MaxLen, "\n");
+ for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++)
+ {
+ if ((strlen(pBuf) + strlen(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name)) >= MaxLen)
+ break;
+ sprintf(pBuf, "%s%s\n", pBuf, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name);
+ }
+ }
+
+ return Status;
+}
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_mac_usb.c b/cleopatre/devkit/mt7601udrv/common/cmm_mac_usb.c
new file mode 100644
index 0000000000..0ffd51a2bd
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_mac_usb.c
@@ -0,0 +1,2159 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************/
+
+
+#ifdef RTMP_MAC_USB
+
+
+#include "rt_config.h"
+
+
+static NDIS_STATUS RTMPAllocUsbBulkBufStruct(
+ IN RTMP_ADAPTER *pAd,
+ IN PURB *ppUrb,
+ IN PVOID *ppXBuffer,
+ IN INT bufLen,
+ IN ra_dma_addr_t *pDmaAddr,
+ IN PSTRING pBufName)
+{
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+
+ *ppUrb = RTUSB_ALLOC_URB(0);
+ if (*ppUrb == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("<-- ERROR in Alloc urb struct for %s !\n", pBufName));
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ *ppXBuffer = RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, bufLen, pDmaAddr);
+ if (*ppXBuffer == NULL) {
+ DBGPRINT(RT_DEBUG_ERROR, ("<-- ERROR in Alloc Bulk buffer for %s!\n", pBufName));
+ return NDIS_STATUS_RESOURCES;
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+static NDIS_STATUS RTMPFreeUsbBulkBufStruct(
+ IN RTMP_ADAPTER *pAd,
+ IN PURB *ppUrb,
+ IN PUCHAR *ppXBuffer,
+ IN INT bufLen,
+ IN ra_dma_addr_t data_dma)
+{
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ if (NULL != *ppUrb) {
+ RTUSB_UNLINK_URB(*ppUrb);
+ RTUSB_FREE_URB(*ppUrb);
+ *ppUrb = NULL;
+ }
+
+ if (NULL != *ppXBuffer) {
+ RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, bufLen, *ppXBuffer, data_dma);
+ *ppXBuffer = NULL;
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+#ifdef RESOURCE_PRE_ALLOC
+VOID RTMPResetTxRxRingMemory(
+ IN RTMP_ADAPTER * pAd)
+{
+ UINT index, i, acidx;
+ PTX_CONTEXT pNullContext = &pAd->NullContext[0];
+ PTX_CONTEXT pPsPollContext = &pAd->PsPollContext;
+ PCMD_RSP_CONTEXT pCmdRspEventContext = &pAd->CmdRspEventContext;
+ unsigned int IrqFlags;
+
+ /* Free TxSwQueue Packet*/
+ for (index = 0; index < NUM_OF_TX_RING; index++)
+ {
+ PQUEUE_ENTRY pEntry;
+ PNDIS_PACKET pPacket;
+ PQUEUE_HEADER pQueue;
+
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+ pQueue = &pAd->TxSwQueue[index];
+ while (pQueue->Head)
+ {
+ pEntry = RemoveHeadQueue(pQueue);
+ pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ }
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+ }
+
+ /* unlink all urbs for the RECEIVE buffer queue.*/
+ for(i=0; i<(RX_RING_SIZE); i++)
+ {
+ PRX_CONTEXT pRxContext = &(pAd->RxContext[i]);
+ if (pRxContext->pUrb)
+ RTUSB_UNLINK_URB(pRxContext->pUrb);
+ }
+
+ if (pCmdRspEventContext->pUrb)
+ RTUSB_UNLINK_URB(pCmdRspEventContext->pUrb);
+
+ /* unlink PsPoll urb resource*/
+ if (pPsPollContext && pPsPollContext->pUrb)
+ RTUSB_UNLINK_URB(pPsPollContext->pUrb);
+
+ /* Free NULL frame urb resource*/
+ if (pNullContext && pNullContext->pUrb)
+ RTUSB_UNLINK_URB(pNullContext->pUrb);
+
+
+ /* Free mgmt frame resource*/
+ for(i = 0; i < MGMT_RING_SIZE; i++)
+ {
+ PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[i].AllocVa;
+ if (pMLMEContext)
+ {
+ if (NULL != pMLMEContext->pUrb)
+ {
+ RTUSB_UNLINK_URB(pMLMEContext->pUrb);
+ RTUSB_FREE_URB(pMLMEContext->pUrb);
+ pMLMEContext->pUrb = NULL;
+ }
+ }
+
+ if (NULL != pAd->MgmtRing.Cell[i].pNdisPacket)
+ {
+ RELEASE_NDIS_PACKET(pAd, pAd->MgmtRing.Cell[i].pNdisPacket, NDIS_STATUS_FAILURE);
+ pAd->MgmtRing.Cell[i].pNdisPacket = NULL;
+ if (pMLMEContext)
+ pMLMEContext->TransferBuffer = NULL;
+ }
+
+ }
+
+
+ /* Free Tx frame resource*/
+ for (acidx = 0; acidx < NUM_OF_TX_RING; acidx++)
+ {
+ PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]);
+ if (pHTTXContext && pHTTXContext->pUrb)
+ RTUSB_UNLINK_URB(pHTTXContext->pUrb);
+ }
+
+ for(i=0; i<6; i++)
+ {
+ NdisFreeSpinLock(&pAd->BulkOutLock[i]);
+ }
+
+ NdisFreeSpinLock(&pAd->BulkInLock);
+ NdisFreeSpinLock(&pAd->CmdRspLock);
+ NdisFreeSpinLock(&pAd->MLMEBulkOutLock);
+
+ NdisFreeSpinLock(&pAd->CmdQLock);
+#ifdef RALINK_ATE
+ NdisFreeSpinLock(&pAd->GenericLock);
+#endif /* RALINK_ATE */
+ /* Clear all pending bulk-out request flags.*/
+ RTUSB_CLEAR_BULK_FLAG(pAd, 0xffffffff);
+
+ for (i = 0; i < NUM_OF_TX_RING; i++)
+ {
+ NdisFreeSpinLock(&pAd->TxContextQueueLock[i]);
+ }
+
+/*
+ NdisFreeSpinLock(&pAd->MacTabLock);
+ for(i=0; i<MAX_LEN_OF_BA_REC_TABLE; i++)
+ {
+ NdisFreeSpinLock(&pAd->BATable.BARecEntry[i].RxReRingLock);
+ }
+*/
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Calls USB_InterfaceStop and frees memory allocated for the URBs
+ calls NdisMDeregisterDevice and frees the memory
+ allocated in VNetInitialize for the Adapter Object
+
+Arguments:
+ *pAd the raxx interface data pointer
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID RTMPFreeTxRxRingMemory(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT i, acidx;
+ PTX_CONTEXT pNullContext = &pAd->NullContext[0];
+ PTX_CONTEXT pPsPollContext = &pAd->PsPollContext;
+ PCMD_RSP_CONTEXT pCmdRspEventContext = &pAd->CmdRspEventContext;
+
+ DBGPRINT(RT_DEBUG_ERROR, ("---> RTMPFreeTxRxRingMemory\n"));
+
+ /* Free all resources for the RECEIVE buffer queue.*/
+ for(i=0; i<(RX_RING_SIZE); i++)
+ {
+ PRX_CONTEXT pRxContext = &(pAd->RxContext[i]);
+ if (pRxContext)
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pRxContext->pUrb,
+ (PUCHAR *)&pRxContext->TransferBuffer,
+ MAX_RXBULK_SIZE,
+ pRxContext->data_dma);
+ }
+
+ /* Command Response */
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pCmdRspEventContext->pUrb,
+ (PUCHAR *)&pCmdRspEventContext->CmdRspBuffer,
+ CMD_RSP_BULK_SIZE,
+ pCmdRspEventContext->data_dma);
+
+
+
+ /* Free PsPoll frame resource*/
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pPsPollContext->pUrb,
+ (PUCHAR *)&pPsPollContext->TransferBuffer,
+ sizeof(TX_BUFFER),
+ pPsPollContext->data_dma);
+
+ /* Free NULL frame resource*/
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pNullContext->pUrb,
+ (PUCHAR *)&pNullContext->TransferBuffer,
+ sizeof(TX_BUFFER),
+ pNullContext->data_dma);
+
+ /* Free mgmt frame resource*/
+ for(i = 0; i < MGMT_RING_SIZE; i++)
+ {
+ PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[i].AllocVa;
+ if (pMLMEContext)
+ {
+ if (NULL != pMLMEContext->pUrb)
+ {
+ RTUSB_UNLINK_URB(pMLMEContext->pUrb);
+ RTUSB_FREE_URB(pMLMEContext->pUrb);
+ pMLMEContext->pUrb = NULL;
+ }
+ }
+
+ if (NULL != pAd->MgmtRing.Cell[i].pNdisPacket)
+ {
+ RELEASE_NDIS_PACKET(pAd, pAd->MgmtRing.Cell[i].pNdisPacket, NDIS_STATUS_FAILURE);
+ pAd->MgmtRing.Cell[i].pNdisPacket = NULL;
+ if (pMLMEContext)
+ pMLMEContext->TransferBuffer = NULL;
+ }
+ }
+
+ if (pAd->MgmtDescRing.AllocVa)
+ os_free_mem(pAd, pAd->MgmtDescRing.AllocVa);
+
+
+ /* Free Tx frame resource*/
+ for (acidx = 0; acidx < NUM_OF_TX_RING; acidx++)
+ {
+ PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]);
+ if (pHTTXContext)
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pHTTXContext->pUrb,
+ (PUCHAR *)&pHTTXContext->TransferBuffer,
+ sizeof(HTTX_BUFFER),
+ pHTTXContext->data_dma);
+ }
+
+ if (pAd->FragFrame.pFragPacket)
+ RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS);
+
+
+ DBGPRINT(RT_DEBUG_ERROR, ("<--- RTMPFreeTxRxRingMemory\n"));
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Initialize receive data structures.
+
+Arguments:
+ pAd Pointer to our adapter
+
+Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_RESOURCES
+
+Note:
+ Initialize all receive releated private buffer, include those define
+ in RTMP_ADAPTER structure and all private data structures. The major
+ work is to allocate buffer for each packet and chain buffer to
+ NDIS packet descriptor.
+========================================================================
+*/
+NDIS_STATUS NICInitRecv(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR i;
+ PCMD_RSP_CONTEXT pCmdRspEventContext = &pAd->CmdRspEventContext;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitRecv\n"));
+
+
+ pAd->PendingRx = 0;
+ pAd->NextRxBulkInReadIndex = 0; /* Next Rx Read index*/
+ pAd->NextRxBulkInIndex = 0 ; /*RX_RING_SIZE -1; Rx Bulk pointer*/
+ pAd->NextRxBulkInPosition = 0;
+
+ for (i = 0; i < (RX_RING_SIZE); i++)
+ {
+ PRX_CONTEXT pRxContext = &(pAd->RxContext[i]);
+
+ ASSERT((pRxContext->TransferBuffer != NULL));
+ ASSERT((pRxContext->pUrb != NULL));
+
+ NdisZeroMemory(pRxContext->TransferBuffer, MAX_RXBULK_SIZE);
+
+ pRxContext->pAd = pAd;
+ pRxContext->pIrp = NULL;
+ pRxContext->InUse = FALSE;
+ pRxContext->IRPPending = FALSE;
+ pRxContext->Readable = FALSE;
+ pRxContext->bRxHandling = FALSE;
+ pRxContext->BulkInOffset = 0;
+ }
+
+ pCmdRspEventContext->pAd = pAd;
+ pCmdRspEventContext->InUse = FALSE;
+ pCmdRspEventContext->Readable = FALSE;
+ NdisZeroMemory(pCmdRspEventContext->CmdRspBuffer, CMD_RSP_BULK_SIZE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitRecv()\n"));
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Initialize transmit data structures.
+
+Arguments:
+ pAd Pointer to our adapter
+
+Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_RESOURCES
+
+Note:
+========================================================================
+*/
+NDIS_STATUS NICInitTransmit(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR i, acidx;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PTX_CONTEXT pNullContext = &(pAd->NullContext[0]);
+ PTX_CONTEXT pPsPollContext = &(pAd->PsPollContext);
+ PTX_CONTEXT pMLMEContext = NULL;
+ PVOID RingBaseVa;
+ RTMP_MGMT_RING *pMgmtRing;
+ PVOID pTransferBuffer;
+ PURB pUrb;
+ ra_dma_addr_t data_dma;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTransmit\n"));
+
+
+ /* Init 4 set of Tx parameters*/
+ for(acidx = 0; acidx < NUM_OF_TX_RING; acidx++)
+ {
+ /* Initialize all Transmit releated queues*/
+ InitializeQueueHeader(&pAd->TxSwQueue[acidx]);
+
+ /* Next Local tx ring pointer waiting for buck out*/
+ pAd->NextBulkOutIndex[acidx] = acidx;
+ pAd->BulkOutPending[acidx] = FALSE; /* Buck Out control flag */
+ }
+
+
+ do
+ {
+
+ /* TX_RING_SIZE, 4 ACs*/
+
+ for(acidx=0; acidx<NUM_OF_TX_RING; acidx++)
+ {
+ PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]);
+
+ pTransferBuffer = pHTTXContext->TransferBuffer;
+ pUrb = pHTTXContext->pUrb;
+ data_dma = pHTTXContext->data_dma;
+
+ ASSERT( (pTransferBuffer != NULL));
+ ASSERT( (pUrb != NULL));
+
+ NdisZeroMemory(pHTTXContext, sizeof(HT_TX_CONTEXT));
+ pHTTXContext->TransferBuffer = pTransferBuffer;
+ pHTTXContext->pUrb = pUrb;
+ pHTTXContext->data_dma = data_dma;
+
+ NdisZeroMemory(pHTTXContext->TransferBuffer->Aggregation, 4);
+
+ pHTTXContext->pAd = pAd;
+ pHTTXContext->BulkOutPipeId = acidx;
+ pHTTXContext->bRingEmpty = TRUE;
+ pHTTXContext->bCopySavePad = FALSE;
+
+ pAd->BulkOutPending[acidx] = FALSE;
+ }
+
+
+
+ /* MGMT_RING_SIZE*/
+
+ NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize);
+ RingBaseVa = pAd->MgmtDescRing.AllocVa;
+
+ /* Initialize MGMT Ring and associated buffer memory*/
+ pMgmtRing = &pAd->MgmtRing;
+ for (i = 0; i < MGMT_RING_SIZE; i++)
+ {
+ /* link the pre-allocated Mgmt buffer to MgmtRing.Cell*/
+ pMgmtRing->Cell[i].AllocSize = sizeof(TX_CONTEXT);
+ pMgmtRing->Cell[i].AllocVa = RingBaseVa;
+ pMgmtRing->Cell[i].pNdisPacket = NULL;
+ pMgmtRing->Cell[i].pNextNdisPacket = NULL;
+
+ /*Allocate URB for MLMEContext*/
+ pMLMEContext = (PTX_CONTEXT) pAd->MgmtRing.Cell[i].AllocVa;
+ pMLMEContext->pUrb = RTUSB_ALLOC_URB(0);
+ if (pMLMEContext->pUrb == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("<-- ERROR in Alloc TX MLMEContext[%d] urb!! \n", i));
+ Status = NDIS_STATUS_RESOURCES;
+ goto err;
+ }
+ pMLMEContext->pAd = pAd;
+ pMLMEContext->SelfIdx = i;
+
+ /* Offset to next ring descriptor address*/
+ RingBaseVa = (PUCHAR) RingBaseVa + sizeof(TX_CONTEXT);
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", i));
+
+ /*pAd->MgmtRing.TxSwFreeIdx = (MGMT_RING_SIZE - 1);*/
+ pAd->MgmtRing.TxSwFreeIdx = MGMT_RING_SIZE;
+ pAd->MgmtRing.TxCpuIdx = 0;
+ pAd->MgmtRing.TxDmaIdx = 0;
+
+
+
+ /* NullContext*/
+
+ pTransferBuffer = pNullContext->TransferBuffer;
+ pUrb = pNullContext->pUrb;
+ data_dma = pNullContext->data_dma;
+
+ NdisZeroMemory(pNullContext, sizeof(TX_CONTEXT));
+ pNullContext->TransferBuffer = pTransferBuffer;
+ pNullContext->pUrb = pUrb;
+ pNullContext->data_dma = data_dma;
+ pNullContext->pAd = pAd;
+
+
+
+ /* PsPollContext*/
+
+ pTransferBuffer = pPsPollContext->TransferBuffer;
+ pUrb = pPsPollContext->pUrb;
+ data_dma = pPsPollContext->data_dma;
+ NdisZeroMemory(pPsPollContext, sizeof(TX_CONTEXT));
+ pPsPollContext->TransferBuffer = pTransferBuffer;
+ pPsPollContext->pUrb = pUrb;
+ pPsPollContext->data_dma = data_dma;
+ pPsPollContext->pAd = pAd;
+ pPsPollContext->LastOne = TRUE;
+
+ } while (FALSE);
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTransmit(Status=%d)\n", Status));
+
+ return Status;
+
+ /* --------------------------- ERROR HANDLE --------------------------- */
+err:
+ if (pAd->MgmtDescRing.AllocVa)
+ {
+ pMgmtRing = &pAd->MgmtRing;
+ for(i = 0; i < MGMT_RING_SIZE; i++)
+ {
+ pMLMEContext = (PTX_CONTEXT) pAd->MgmtRing.Cell[i].AllocVa;
+ if (pMLMEContext)
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pMLMEContext->pUrb,
+ (PUCHAR *)&pMLMEContext->TransferBuffer,
+ sizeof(TX_BUFFER),
+ pMLMEContext->data_dma);
+ }
+ os_free_mem(pAd, pAd->MgmtDescRing.AllocVa);
+ pAd->MgmtDescRing.AllocVa = NULL;
+ }
+
+ /* Here we didn't have any pre-allocated memory need to free.*/
+
+ return Status;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Allocate DMA memory blocks for send, receive.
+
+Arguments:
+ pAd Pointer to our adapter
+
+Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_RESOURCES
+
+Note:
+========================================================================
+*/
+NDIS_STATUS RTMPAllocTxRxRingMemory(
+ IN PRTMP_ADAPTER pAd)
+{
+ NDIS_STATUS Status = NDIS_STATUS_FAILURE;
+ PTX_CONTEXT pNullContext = &(pAd->NullContext);
+ PTX_CONTEXT pPsPollContext = &(pAd->PsPollContext);
+ PCMD_RSP_CONTEXT pCmdRspEventContext = &(pAd->CmdRspEventContext);
+ INT i, acidx;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n"));
+
+ do
+ {
+
+ /* Init send data structures and related parameters*/
+
+
+ /* TX_RING_SIZE, 4 ACs*/
+
+ for(acidx=0; acidx<NUM_OF_TX_RING; acidx++)
+ {
+ PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]);
+
+ NdisZeroMemory(pHTTXContext, sizeof(HT_TX_CONTEXT));
+ /*Allocate URB and bulk buffer*/
+ Status = RTMPAllocUsbBulkBufStruct(pAd,
+ &pHTTXContext->pUrb,
+ (PVOID *)&pHTTXContext->TransferBuffer,
+ sizeof(HTTX_BUFFER),
+ &pHTTXContext->data_dma,
+ "HTTxContext");
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err;
+ }
+
+
+
+ /* MGMT_RING_SIZE*/
+
+ /* Allocate MGMT ring descriptor's memory*/
+ pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * sizeof(TX_CONTEXT);
+ os_alloc_mem(pAd, (PUCHAR *)(&pAd->MgmtDescRing.AllocVa), pAd->MgmtDescRing.AllocSize);
+ if (pAd->MgmtDescRing.AllocVa == NULL)
+ {
+ DBGPRINT_ERR(("Failed to allocate a big buffer for MgmtDescRing!\n"));
+ Status = NDIS_STATUS_RESOURCES;
+ goto err;
+ }
+
+
+
+ /* NullContext*/
+
+ NdisZeroMemory(pNullContext, sizeof(TX_CONTEXT));
+ /*Allocate URB*/
+ Status = RTMPAllocUsbBulkBufStruct(pAd,
+ &pNullContext->pUrb,
+ (PVOID *)&pNullContext->TransferBuffer,
+ sizeof(TX_BUFFER),
+ &pNullContext->data_dma,
+ "TxNullContext");
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err;
+
+
+ /* PsPollContext*/
+
+ NdisZeroMemory(pPsPollContext, sizeof(TX_CONTEXT));
+ /*Allocate URB*/
+ Status = RTMPAllocUsbBulkBufStruct(pAd,
+ &pPsPollContext->pUrb,
+ (PVOID *)&pPsPollContext->TransferBuffer,
+ sizeof(TX_BUFFER),
+ &pPsPollContext->data_dma,
+ "TxPsPollContext");
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err;
+
+
+
+ /* Init receive data structures and related parameters*/
+ for (i = 0; i < (RX_RING_SIZE); i++)
+ {
+ PRX_CONTEXT pRxContext = &(pAd->RxContext[i]);
+
+ /*Allocate URB*/
+ Status = RTMPAllocUsbBulkBufStruct(pAd,
+ &pRxContext->pUrb,
+ (PVOID *)&pRxContext->TransferBuffer,
+ MAX_RXBULK_SIZE,
+ &pRxContext->data_dma,
+ "RxContext");
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err;
+
+ }
+
+ /* Init command response event related parameters */
+ Status = RTMPAllocUsbBulkBufStruct(pAd,
+ &pCmdRspEventContext->pUrb,
+ (PVOID *)&pCmdRspEventContext->CmdRspBuffer,
+ CMD_RSP_BULK_SIZE,
+ &pCmdRspEventContext->data_dma,
+ "CmdRspEventContext");
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err;
+
+
+ NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME));
+ pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
+
+ if (pAd->FragFrame.pFragPacket == NULL)
+ {
+ Status = NDIS_STATUS_RESOURCES;
+ }
+ } while (FALSE);
+
+ DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status));
+ return Status;
+
+err:
+ Status = NDIS_STATUS_RESOURCES;
+ RTMPFreeTxRxRingMemory(pAd);
+
+ return Status;
+}
+
+
+NDIS_STATUS RTMPInitTxRxRingMemory
+ (IN RTMP_ADAPTER *pAd)
+{
+ INT num;
+ NDIS_STATUS Status;
+
+ /* Init the CmdQ and CmdQLock*/
+ NdisAllocateSpinLock(pAd, &pAd->CmdQLock);
+ NdisAcquireSpinLock(&pAd->CmdQLock);
+ RTInitializeCmdQ(&pAd->CmdQ);
+ NdisReleaseSpinLock(&pAd->CmdQLock);
+
+
+ NdisAllocateSpinLock(pAd, &pAd->MLMEBulkOutLock);
+ NdisAllocateSpinLock(pAd, &pAd->BulkInLock);
+ NdisAllocateSpinLock(pAd, &pAd->CmdRspLock);
+ for(num =0 ; num < 6; num++)
+ {
+ NdisAllocateSpinLock(pAd, &pAd->BulkOutLock[num]);
+ }
+
+
+ for (num = 0; num < NUM_OF_TX_RING; num++)
+ {
+ NdisAllocateSpinLock(pAd, &pAd->TxContextQueueLock[num]);
+ }
+
+#ifdef RALINK_ATE
+ NdisAllocateSpinLock(pAd, &pAd->GenericLock);
+#endif /* RALINK_ATE */
+
+ NICInitRecv(pAd);
+
+
+ Status = NICInitTransmit(pAd);
+
+ return Status;
+
+}
+
+
+#else
+
+/*
+========================================================================
+Routine Description:
+ Initialize receive data structures.
+
+Arguments:
+ pAd Pointer to our adapter
+
+Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_RESOURCES
+
+Note:
+ Initialize all receive releated private buffer, include those define
+ in RTMP_ADAPTER structure and all private data structures. The mahor
+ work is to allocate buffer for each packet and chain buffer to
+ NDIS packet descriptor.
+========================================================================
+*/
+NDIS_STATUS NICInitRecv(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR i;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+ PCMD_RSP_CONTEXT pCmdRspEventContext = &pAd->CmdRspEventContext;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitRecv\n"));
+ pObj = pObj;
+
+ /*InterlockedExchange(&pAd->PendingRx, 0);*/
+ pAd->PendingRx = 0;
+ pAd->NextRxBulkInReadIndex = 0; /* Next Rx Read index*/
+ pAd->NextRxBulkInIndex = 0 ; /*RX_RING_SIZE -1; Rx Bulk pointer*/
+ pAd->NextRxBulkInPosition = 0;
+
+ for (i = 0; i < (RX_RING_SIZE); i++)
+ {
+ PRX_CONTEXT pRxContext = &(pAd->RxContext[i]);
+
+ /*Allocate URB*/
+ pRxContext->pUrb = RTUSB_ALLOC_URB(0);
+ if (pRxContext->pUrb == NULL)
+ {
+ Status = NDIS_STATUS_RESOURCES;
+ goto out1;
+ }
+
+ /* Allocate transfer buffer*/
+ pRxContext->TransferBuffer = RTUSB_URB_ALLOC_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE, &pRxContext->data_dma);
+ if (pRxContext->TransferBuffer == NULL)
+ {
+ Status = NDIS_STATUS_RESOURCES;
+ goto out1;
+ }
+
+ NdisZeroMemory(pRxContext->TransferBuffer, MAX_RXBULK_SIZE);
+
+ pRxContext->pAd = pAd;
+ pRxContext->pIrp = NULL;
+ pRxContext->InUse = FALSE;
+ pRxContext->IRPPending = FALSE;
+ pRxContext->Readable = FALSE;
+ /*pRxContext->ReorderInUse = FALSE;*/
+ pRxContext->bRxHandling = FALSE;
+ pRxContext->BulkInOffset = 0;
+ }
+
+ pCmdRspEventContext->pAd = pAd;
+ pCmdRspEventContext->InUse = FALSE;
+ pCmdRspEventContext->Readable = FALSE;
+ NdisZeroMemory(pCmdRspEventContext->TransferBuffer, CMD_RSP_BULK_SIZE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitRecv(Status=%d)\n", Status));
+ return Status;
+
+out1:
+ for (i = 0; i < (RX_RING_SIZE); i++)
+ {
+ PRX_CONTEXT pRxContext = &(pAd->RxContext[i]);
+
+ if (NULL != pRxContext->TransferBuffer)
+ {
+ RTUSB_URB_FREE_BUFFER(pObj->pUsb_Dev, MAX_RXBULK_SIZE,
+ pRxContext->TransferBuffer, pRxContext->data_dma);
+ pRxContext->TransferBuffer = NULL;
+ }
+
+ if (NULL != pRxContext->pUrb)
+ {
+ RTUSB_UNLINK_URB(pRxContext->pUrb);
+ RTUSB_FREE_URB(pRxContext->pUrb);
+ pRxContext->pUrb = NULL;
+ }
+ }
+
+ return Status;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Initialize transmit data structures.
+
+Arguments:
+ pAd Pointer to our adapter
+
+Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_RESOURCES
+
+Note:
+========================================================================
+*/
+NDIS_STATUS NICInitTransmit(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR i, acidx;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PTX_CONTEXT pNullContext = &(pAd->NullContext[0]);
+ PTX_CONTEXT pPsPollContext = &(pAd->PsPollContext);
+ PTX_CONTEXT pMLMEContext = NULL;
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+ PVOID RingBaseVa;
+ RTMP_MGMT_RING *pMgmtRing;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitTransmit\n"));
+ pObj = pObj;
+
+ /* Init 4 set of Tx parameters*/
+ for(acidx = 0; acidx < NUM_OF_TX_RING; acidx++)
+ {
+ /* Initialize all Transmit releated queues*/
+ InitializeQueueHeader(&pAd->TxSwQueue[acidx]);
+
+ /* Next Local tx ring pointer waiting for buck out*/
+ pAd->NextBulkOutIndex[acidx] = acidx;
+ pAd->BulkOutPending[acidx] = FALSE; /* Buck Out control flag */
+ }
+
+
+ do
+ {
+
+ /* TX_RING_SIZE, 4 ACs*/
+
+ for(acidx=0; acidx<NUM_OF_TX_RING; acidx++)
+ {
+ PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]);
+
+ NdisZeroMemory(pHTTXContext, sizeof(HT_TX_CONTEXT));
+ /*Allocate URB*/
+ Status = RTMPAllocUsbBulkBufStruct(pAd,
+ &pHTTXContext->pUrb,
+ (PVOID *)&pHTTXContext->TransferBuffer,
+ sizeof(HTTX_BUFFER),
+ &pHTTXContext->data_dma,
+ "HTTxContext");
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err;
+
+ NdisZeroMemory(pHTTXContext->TransferBuffer->Aggregation, 4);
+ pHTTXContext->pAd = pAd;
+ pHTTXContext->pIrp = NULL;
+ pHTTXContext->IRPPending = FALSE;
+ pHTTXContext->NextBulkOutPosition = 0;
+ pHTTXContext->ENextBulkOutPosition = 0;
+ pHTTXContext->CurWritePosition = 0;
+ pHTTXContext->CurWriteRealPos = 0;
+ pHTTXContext->BulkOutSize = 0;
+ pHTTXContext->BulkOutPipeId = acidx;
+ pHTTXContext->bRingEmpty = TRUE;
+ pHTTXContext->bCopySavePad = FALSE;
+ pAd->BulkOutPending[acidx] = FALSE;
+ }
+
+
+
+ /* MGMT Ring*/
+
+
+ /* Allocate MGMT ring descriptor's memory*/
+ pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * sizeof(TX_CONTEXT);
+ os_alloc_mem(pAd, (PUCHAR *)(&pAd->MgmtDescRing.AllocVa), pAd->MgmtDescRing.AllocSize);
+ if (pAd->MgmtDescRing.AllocVa == NULL)
+ {
+ DBGPRINT_ERR(("Failed to allocate a big buffer for MgmtDescRing!\n"));
+ Status = NDIS_STATUS_RESOURCES;
+ goto err;
+ }
+ NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize);
+ RingBaseVa = pAd->MgmtDescRing.AllocVa;
+
+ /* Initialize MGMT Ring and associated buffer memory*/
+ pMgmtRing = &pAd->MgmtRing;
+ for (i = 0; i < MGMT_RING_SIZE; i++)
+ {
+ /* link the pre-allocated Mgmt buffer to MgmtRing.Cell*/
+ pMgmtRing->Cell[i].AllocSize = sizeof(TX_CONTEXT);
+ pMgmtRing->Cell[i].AllocVa = RingBaseVa;
+ pMgmtRing->Cell[i].pNdisPacket = NULL;
+ pMgmtRing->Cell[i].pNextNdisPacket = NULL;
+
+ /*Allocate URB for MLMEContext*/
+ pMLMEContext = (PTX_CONTEXT) pAd->MgmtRing.Cell[i].AllocVa;
+ pMLMEContext->pUrb = RTUSB_ALLOC_URB(0);
+ if (pMLMEContext->pUrb == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("<-- ERROR in Alloc TX MLMEContext[%d] urb!! \n", i));
+ Status = NDIS_STATUS_RESOURCES;
+ goto err;
+ }
+ pMLMEContext->pAd = pAd;
+ pMLMEContext->pIrp = NULL;
+ pMLMEContext->TransferBuffer = NULL;
+ pMLMEContext->InUse = FALSE;
+ pMLMEContext->IRPPending = FALSE;
+ pMLMEContext->bWaitingBulkOut = FALSE;
+ pMLMEContext->BulkOutSize = 0;
+ pMLMEContext->SelfIdx = i;
+
+ /* Offset to next ring descriptor address*/
+ RingBaseVa = (PUCHAR) RingBaseVa + sizeof(TX_CONTEXT);
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", i));
+
+ /*pAd->MgmtRing.TxSwFreeIdx = (MGMT_RING_SIZE - 1);*/
+ pAd->MgmtRing.TxSwFreeIdx = MGMT_RING_SIZE;
+ pAd->MgmtRing.TxCpuIdx = 0;
+ pAd->MgmtRing.TxDmaIdx = 0;
+
+
+ /* NullContext URB and usb buffer*/
+
+ NdisZeroMemory(pNullContext, sizeof(TX_CONTEXT));
+ Status = RTMPAllocUsbBulkBufStruct(pAd,
+ &pNullContext->pUrb,
+ (PVOID *)&pNullContext->TransferBuffer,
+ sizeof(TX_BUFFER),
+ &pNullContext->data_dma,
+ "TxNullContext");
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err;
+
+ pNullContext->pAd = pAd;
+ pNullContext->pIrp = NULL;
+ pNullContext->InUse = FALSE;
+ pNullContext->IRPPending = FALSE;
+
+
+ /* PsPollContext URB and usb buffer*/
+
+ Status = RTMPAllocUsbBulkBufStruct(pAd,
+ &pPsPollContext->pUrb,
+ (PVOID *)&pPsPollContext->TransferBuffer,
+ sizeof(TX_BUFFER),
+ &pPsPollContext->data_dma,
+ "TxPsPollContext");
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err;
+
+ pPsPollContext->pAd = pAd;
+ pPsPollContext->pIrp = NULL;
+ pPsPollContext->InUse = FALSE;
+ pPsPollContext->IRPPending = FALSE;
+ pPsPollContext->bAggregatible = FALSE;
+ pPsPollContext->LastOne = TRUE;
+
+ }while (FALSE);
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitTransmit(Status=%d)\n", Status));
+
+ return Status;
+
+
+ /* --------------------------- ERROR HANDLE --------------------------- */
+err:
+ /* Free PsPoll frame resource*/
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pPsPollContext->pUrb,
+ (PUCHAR *)&pPsPollContext->TransferBuffer,
+ sizeof(TX_BUFFER),
+ pPsPollContext->data_dma);
+
+ /* Free NULL frame resource*/
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pNullContext->pUrb,
+ (PUCHAR *)&pNullContext->TransferBuffer,
+ sizeof(TX_BUFFER),
+ pNullContext->data_dma);
+
+ /* MGMT Ring*/
+ if (pAd->MgmtDescRing.AllocVa)
+ {
+ pMgmtRing = &pAd->MgmtRing;
+ for(i=0; i<MGMT_RING_SIZE; i++)
+ {
+ pMLMEContext = (PTX_CONTEXT) pAd->MgmtRing.Cell[i].AllocVa;
+ if (pMLMEContext)
+ {
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pMLMEContext->pUrb,
+ (PUCHAR *)&pMLMEContext->TransferBuffer,
+ sizeof(TX_BUFFER),
+ pMLMEContext->data_dma);
+ }
+ }
+ os_free_mem(pAd, pAd->MgmtDescRing.AllocVa);
+ pAd->MgmtDescRing.AllocVa = NULL;
+ }
+
+
+ /* Tx Ring*/
+ for (acidx = 0; acidx < 4; acidx++)
+ {
+ PHT_TX_CONTEXT pHTTxContext = &(pAd->TxContext[acidx]);
+ if (pHTTxContext)
+ {
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pHTTxContext->pUrb,
+ (PUCHAR *)&pHTTxContext->TransferBuffer,
+ sizeof(HTTX_BUFFER),
+ pHTTxContext->data_dma);
+ }
+ }
+
+ /* Here we didn't have any pre-allocated memory need to free.*/
+
+ return Status;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Allocate DMA memory blocks for send, receive.
+
+Arguments:
+ pAd Pointer to our adapter
+
+Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_RESOURCES
+
+Note:
+========================================================================
+*/
+NDIS_STATUS RTMPAllocTxRxRingMemory(
+ IN PRTMP_ADAPTER pAd)
+{
+/* COUNTER_802_11 pCounter = &pAd->WlanCounters;*/
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ INT num;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n"));
+
+
+ do
+ {
+ /* Init the CmdQ and CmdQLock*/
+ NdisAllocateSpinLock(pAd, &pAd->CmdQLock);
+ NdisAcquireSpinLock(&pAd->CmdQLock);
+ RTInitializeCmdQ(&pAd->CmdQ);
+ NdisReleaseSpinLock(&pAd->CmdQLock);
+
+
+ NdisAllocateSpinLock(pAd, &pAd->MLMEBulkOutLock);
+ NdisAllocateSpinLock(pAd, &pAd->BulkInLock);
+ NdisAllocateSpinLock(pAd, &pAd->CmdRspLock);
+ for(num =0 ; num < 6; num++)
+ {
+ NdisAllocateSpinLock(pAd, &pAd->BulkOutLock[num]);
+ }
+
+ for (num = 0; num < NUM_OF_TX_RING; num++)
+ {
+ NdisAllocateSpinLock(pAd, &pAd->TxContextQueueLock[num]);
+ }
+
+#ifdef RALINK_ATE
+ NdisAllocateSpinLock(pAd, &pAd->GenericLock);
+#endif /* RALINK_ATE */
+
+
+
+ /* Init send data structures and related parameters*/
+
+ Status = NICInitTransmit(pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ break;
+
+
+ /* Init receive data structures and related parameters*/
+
+ Status = NICInitRecv(pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ break;
+
+ NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME));
+ pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
+
+ if (pAd->FragFrame.pFragPacket == NULL)
+ {
+ Status = NDIS_STATUS_RESOURCES;
+ }
+ } while (FALSE);
+
+ DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status));
+ return Status;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Calls USB_InterfaceStop and frees memory allocated for the URBs
+ calls NdisMDeregisterDevice and frees the memory
+ allocated in VNetInitialize for the Adapter Object
+
+Arguments:
+ *pAd the raxx interface data pointer
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID RTMPFreeTxRxRingMemory(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT i, acidx;
+ PTX_CONTEXT pNullContext = &pAd->NullContext;
+ PTX_CONTEXT pPsPollContext = &pAd->PsPollContext;
+ PCMD_RSP_CONTEXT pCmdRspEventContext = &(pAd->CmdRspEventContext);
+
+
+ DBGPRINT(RT_DEBUG_ERROR, ("---> RTMPFreeTxRxRingMemory\n"));
+
+
+ /* Free all resources for the RxRing buffer queue.*/
+ for(i=0; i<(RX_RING_SIZE); i++)
+ {
+ PRX_CONTEXT pRxContext = &(pAd->RxContext[i]);
+ if (pRxContext)
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pRxContext->pUrb,
+ (PUCHAR *)&pRxContext->TransferBuffer,
+ MAX_RXBULK_SIZE,
+ pRxContext->data_dma);
+ }
+
+ if (pCmdRspEventContext)
+ {
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pCmdRspEventContext->pUrb,
+ (PUCHAR *)&pCmdRspEventContext->TransferBuffer,
+ CMD_RSP_BULK_SIZE,
+ pCmdRspEventContext->data_dma);
+ }
+
+ /* Free PsPoll frame resource*/
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pPsPollContext->pUrb,
+ (PUCHAR *)&pPsPollContext->TransferBuffer,
+ sizeof(TX_BUFFER),
+ pPsPollContext->data_dma);
+
+ /* Free NULL frame resource*/
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pNullContext->pUrb,
+ (PUCHAR *)&pNullContext->TransferBuffer,
+ sizeof(TX_BUFFER),
+ pNullContext->data_dma);
+
+ /* Free mgmt frame resource*/
+ for(i = 0; i < MGMT_RING_SIZE; i++)
+ {
+ PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[i].AllocVa;
+ if (pMLMEContext)
+ {
+ if (NULL != pMLMEContext->pUrb)
+ {
+ RTUSB_UNLINK_URB(pMLMEContext->pUrb);
+ RTUSB_FREE_URB(pMLMEContext->pUrb);
+ pMLMEContext->pUrb = NULL;
+ }
+ }
+
+ if (NULL != pAd->MgmtRing.Cell[i].pNdisPacket)
+ {
+ RELEASE_NDIS_PACKET(pAd, pAd->MgmtRing.Cell[i].pNdisPacket, NDIS_STATUS_FAILURE);
+ pAd->MgmtRing.Cell[i].pNdisPacket = NULL;
+ if (pMLMEContext)
+ pMLMEContext->TransferBuffer = NULL;
+ }
+
+ }
+ if (pAd->MgmtDescRing.AllocVa)
+ os_free_mem(pAd, pAd->MgmtDescRing.AllocVa);
+
+
+ /* Free Tx frame resource*/
+ for (acidx = 0; acidx < 4; acidx++)
+ {
+ PHT_TX_CONTEXT pHTTXContext = &(pAd->TxContext[acidx]);
+ if (pHTTXContext)
+ RTMPFreeUsbBulkBufStruct(pAd,
+ &pHTTXContext->pUrb,
+ (PUCHAR *)&pHTTXContext->TransferBuffer,
+ sizeof(HTTX_BUFFER),
+ pHTTXContext->data_dma);
+ }
+
+ /* Free fragement frame buffer*/
+ if (pAd->FragFrame.pFragPacket)
+ RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS);
+
+
+ /* Free spinlocks*/
+ for(i=0; i<6; i++)
+ {
+ NdisFreeSpinLock(&pAd->BulkOutLock[i]);
+ }
+
+ NdisFreeSpinLock(&pAd->BulkInLock);
+ NdisFreeSpinLock(&pAd->CmdRspLock);
+ NdisFreeSpinLock(&pAd->MLMEBulkOutLock);
+
+ NdisFreeSpinLock(&pAd->CmdQLock);
+#ifdef RALINK_ATE
+ NdisFreeSpinLock(&pAd->GenericLock);
+#endif /* RALINK_ATE */
+
+ /* Clear all pending bulk-out request flags.*/
+ RTUSB_CLEAR_BULK_FLAG(pAd, 0xffffffff);
+
+ for (i = 0; i < NUM_OF_TX_RING; i++)
+ {
+ NdisFreeSpinLock(&pAd->TxContextQueueLock[i]);
+ }
+
+ DBGPRINT(RT_DEBUG_ERROR, ("<--- RTMPFreeTxRxRingMemory\n"));
+}
+
+#endif /* RESOURCE_PRE_ALLOC */
+
+
+/*
+========================================================================
+Routine Description:
+ Write WLAN MAC address to USB 2870.
+
+Arguments:
+ pAd Pointer to our adapter
+
+Return Value:
+ NDIS_STATUS_SUCCESS
+
+Note:
+========================================================================
+*/
+NDIS_STATUS RTUSBWriteHWMACAddress(
+ IN PRTMP_ADAPTER pAd)
+{
+ MAC_DW0_STRUC StaMacReg0;
+ MAC_DW1_STRUC StaMacReg1;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ LARGE_INTEGER NOW;
+
+
+ /* initialize the random number generator*/
+ RTMP_GetCurrentSystemTime(&NOW);
+
+ /* Write New MAC address to MAC_CSR2 & MAC_CSR3 & let ASIC know our new MAC*/
+ StaMacReg0.field.Byte0 = pAd->CurrentAddress[0];
+ StaMacReg0.field.Byte1 = pAd->CurrentAddress[1];
+ StaMacReg0.field.Byte2 = pAd->CurrentAddress[2];
+ StaMacReg0.field.Byte3 = pAd->CurrentAddress[3];
+ StaMacReg1.field.Byte4 = pAd->CurrentAddress[4];
+ StaMacReg1.field.Byte5 = pAd->CurrentAddress[5];
+ StaMacReg1.field.U2MeMask = 0xff;
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("Local MAC = %02x:%02x:%02x:%02x:%02x:%02x\n",
+ pAd->CurrentAddress[0], pAd->CurrentAddress[1], pAd->CurrentAddress[2],
+ pAd->CurrentAddress[3], pAd->CurrentAddress[4], pAd->CurrentAddress[5]));
+
+ RTUSBWriteMACRegister(pAd, MAC_ADDR_DW0, StaMacReg0.word, FALSE);
+ RTUSBWriteMACRegister(pAd, MAC_ADDR_DW1, StaMacReg1.word, FALSE);
+#ifdef HDR_TRANS_SUPPORT
+ RTUSBWriteMACRegister(pAd, HT_MAC_ADDR_DW0, StaMacReg0.word, FALSE);
+ StaMacReg1.word &= 0xff00ffff;
+ StaMacReg1.word |= 0x00410000;
+ RTUSBWriteMACRegister(pAd, HT_MAC_ADDR_DW1, StaMacReg1.word, FALSE);
+#endif /* HDR_TRANS_SUPPORT */
+ return Status;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Disable DMA.
+
+Arguments:
+ *pAd the raxx interface data pointer
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID RT28XXDMADisable(
+ IN RTMP_ADAPTER *pAd)
+{
+ /* no use*/
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Enable DMA.
+
+Arguments:
+ *pAd the raxx interface data pointer
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID RT28XXDMAEnable(
+ IN RTMP_ADAPTER *pAd)
+{
+ WPDMA_GLO_CFG_STRUC GloCfg;
+ USB_DMA_CFG_STRUC UsbCfg;
+
+
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
+
+ if (AsicWaitPDMAIdle(pAd, 200, 1000) == FALSE) {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+ }
+
+/*
+ // USB not support WPDMA
+ RTMPusecDelay(50);
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
+ GloCfg.field.EnTXWriteBackDDONE = 1;
+ GloCfg.field.EnableRxDMA = 1;
+ GloCfg.field.EnableTxDMA = 1;
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
+*/
+
+
+}
+
+/********************************************************************
+ *
+ * 2870 Beacon Update Related functions.
+ *
+ ********************************************************************/
+
+/*
+========================================================================
+Routine Description:
+ Write Beacon buffer to Asic.
+
+Arguments:
+ *pAd the raxx interface data pointer
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID RT28xx_UpdateBeaconToAsic(
+ IN RTMP_ADAPTER *pAd,
+ IN INT apidx,
+ IN ULONG FrameLen,
+ IN ULONG UpdatePos)
+{
+ PUCHAR pBeaconFrame = NULL;
+ UCHAR *ptr;
+ UINT i, padding;
+ BEACON_SYNC_STRUCT *pBeaconSync = pAd->CommonCfg.pBeaconSync;
+ UINT32 longValue;
+/* USHORT shortValue;*/
+ BOOLEAN bBcnReq = FALSE;
+ UCHAR bcn_idx = 0;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+#ifdef CONFIG_AP_SUPPORT
+ if ((apidx < pAd->ApCfg.BssidNum) && (apidx < MAX_MBSSID_NUM(pAd)))
+ {
+ bcn_idx = pAd->ApCfg.MBSSID[apidx].BcnBufIdx;
+ pBeaconFrame = (PUCHAR) pAd->ApCfg.MBSSID[apidx].BeaconBuf;
+ bBcnReq = BeaconTransmitRequired(pAd, apidx, &pAd->ApCfg.MBSSID[apidx]);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pBeaconFrame == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("pBeaconFrame is NULL!\n"));
+ return;
+ }
+
+ if (pBeaconSync == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("pBeaconSync is NULL!\n"));
+ return;
+ }
+
+ if (bBcnReq == FALSE)
+ {
+ /* when the ra interface is down, do not send its beacon frame */
+ /* clear all zero */
+ for(i=0; i < TXWISize; i+=4) {
+ RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00, 4);
+ }
+
+ pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
+ NdisZeroMemory(pBeaconSync->BeaconTxWI[bcn_idx], TXWISize);
+ }
+ else
+ {
+ ptr = (PUCHAR)&pAd->BeaconTxWI;
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange(pAd, ptr, TYPE_TXWI);
+#endif
+ if (NdisEqualMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWISize) == FALSE)
+ { /* If BeaconTxWI changed, we need to rewrite the TxWI for the Beacon frames.*/
+ pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << bcn_idx)));
+ NdisMoveMemory(pBeaconSync->BeaconTxWI[bcn_idx], &pAd->BeaconTxWI, TXWISize);
+ }
+
+ if ((pBeaconSync->BeaconBitMap & (1 << bcn_idx)) != (1 << bcn_idx))
+ {
+ for (i=0; i < TXWISize; i+=4)
+ {
+ longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
+ RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[bcn_idx] + i, longValue, 4);
+ ptr += 4;
+ }
+ }
+
+ ptr = pBeaconSync->BeaconBuf[bcn_idx];
+ padding = (FrameLen & 0x01);
+ NdisZeroMemory((PUCHAR)(pBeaconFrame + FrameLen), padding);
+ FrameLen += padding;
+ for (i = 0 ; i < FrameLen /*HW_BEACON_OFFSET*/; i += 2)
+ {
+ if (NdisEqualMemory(ptr, pBeaconFrame, 2) == FALSE)
+ {
+ NdisMoveMemory(ptr, pBeaconFrame, 2);
+ longValue = *ptr + (*(ptr+1)<<8);
+ RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[bcn_idx] + TXWISize + i, longValue, 2);
+ }
+ ptr +=2;
+ pBeaconFrame += 2;
+ }
+
+
+ pBeaconSync->BeaconBitMap |= (1 << bcn_idx);
+
+ /* For AP interface, set the DtimBitOn so that we can send Bcast/Mcast frame out after this beacon frame.*/
+#ifdef CONFIG_AP_SUPPORT
+ {
+ ptr = (PUCHAR) (pAd->ApCfg.MBSSID[apidx].BeaconBuf + pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon);
+ if ((*(ptr + 4)) & 0x01)
+ pBeaconSync->DtimBitOn |= (1 << apidx);
+ else
+ pBeaconSync->DtimBitOn &= ~(1 << apidx);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+}
+
+}
+
+
+VOID RTUSBBssBeaconStop(
+ IN RTMP_ADAPTER *pAd)
+{
+ BEACON_SYNC_STRUCT *pBeaconSync;
+ int i, offset;
+ BOOLEAN Cancelled = TRUE;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+ pBeaconSync = pAd->CommonCfg.pBeaconSync;
+ if (pBeaconSync && pBeaconSync->EnableBeacon)
+ {
+ INT NumOfBcn = 0;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ NumOfBcn = pAd->ApCfg.BssidNum + MAX_MESH_NUM;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
+
+ for(i=0; i<NumOfBcn; i++)
+ {
+ NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
+ NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWISize);
+
+ for (offset=0; offset<HW_BEACON_OFFSET; offset+=4)
+ RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[i] + offset, 0x00, 4);
+
+ pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
+ pBeaconSync->TimIELocationInBeacon[i] = 0;
+ }
+ pBeaconSync->BeaconBitMap = 0;
+ pBeaconSync->DtimBitOn = 0;
+ }
+}
+
+
+VOID RTUSBBssBeaconStart(
+ IN RTMP_ADAPTER *pAd)
+{
+ int apidx;
+ BEACON_SYNC_STRUCT *pBeaconSync;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+/* LARGE_INTEGER tsfTime, deltaTime;*/
+
+ pBeaconSync = pAd->CommonCfg.pBeaconSync;
+ if (pBeaconSync && pBeaconSync->EnableBeacon)
+ {
+ INT NumOfBcn = 0;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ NumOfBcn = pAd->ApCfg.BssidNum + MAX_MESH_NUM;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ for(apidx=0; apidx<NumOfBcn; apidx++)
+ {
+ UCHAR CapabilityInfoLocationInBeacon = 0;
+ UCHAR TimIELocationInBeacon = 0;
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ {
+ CapabilityInfoLocationInBeacon = pAd->ApCfg.MBSSID[apidx].CapabilityInfoLocationInBeacon;
+ TimIELocationInBeacon = pAd->ApCfg.MBSSID[apidx].TimIELocationInBeacon;
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ NdisZeroMemory(pBeaconSync->BeaconBuf[apidx], HW_BEACON_OFFSET);
+ pBeaconSync->CapabilityInfoLocationInBeacon[apidx] = CapabilityInfoLocationInBeacon;
+ pBeaconSync->TimIELocationInBeacon[apidx] = TimIELocationInBeacon;
+ NdisZeroMemory(pBeaconSync->BeaconTxWI[apidx], TXWISize);
+ }
+ pBeaconSync->BeaconBitMap = 0;
+ pBeaconSync->DtimBitOn = 0;
+ pAd->CommonCfg.BeaconUpdateTimer.Repeat = TRUE;
+
+ pAd->CommonCfg.BeaconAdjust = 0;
+ pAd->CommonCfg.BeaconFactor = 0xffffffff / (pAd->CommonCfg.BeaconPeriod << 10);
+ pAd->CommonCfg.BeaconRemain = (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1;
+ DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBssBeaconStart:BeaconFactor=%d, BeaconRemain=%d!\n",
+ pAd->CommonCfg.BeaconFactor, pAd->CommonCfg.BeaconRemain));
+ RTMPSetTimer(&pAd->CommonCfg.BeaconUpdateTimer, 10 /*pAd->CommonCfg.BeaconPeriod*/);
+
+ }
+}
+
+
+VOID RTUSBBssBeaconInit(
+ IN RTMP_ADAPTER *pAd)
+{
+ BEACON_SYNC_STRUCT *pBeaconSync;
+ int i, j;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+ os_alloc_mem(pAd, (PUCHAR *)(&pAd->CommonCfg.pBeaconSync), sizeof(BEACON_SYNC_STRUCT));
+
+ if (pAd->CommonCfg.pBeaconSync)
+ {
+ pBeaconSync = pAd->CommonCfg.pBeaconSync;
+ NdisZeroMemory(pBeaconSync, sizeof(BEACON_SYNC_STRUCT));
+ for(i=0; i < HW_BEACON_MAX_COUNT(pAd); i++)
+ {
+ NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
+ pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
+ pBeaconSync->TimIELocationInBeacon[i] = 0;
+ os_alloc_mem(pAd, &pBeaconSync->BeaconTxWI[i], TXWISize);
+ if (pBeaconSync->BeaconTxWI[i])
+ NdisZeroMemory(pBeaconSync->BeaconTxWI[i], TXWISize);
+ else
+ goto error2;
+ }
+ pBeaconSync->BeaconBitMap = 0;
+
+ /*RTMPInitTimer(pAd, &pAd->CommonCfg.BeaconUpdateTimer, GET_TIMER_FUNCTION(BeaconUpdateExec), pAd, TRUE);*/
+ pBeaconSync->EnableBeacon = TRUE;
+ }else
+ goto error1;
+
+ return;
+
+error2:
+ for (j = 0; j < i; j++)
+ os_free_mem(pAd, pBeaconSync->BeaconTxWI[j]);
+
+ os_free_mem(pAd, pAd->CommonCfg.pBeaconSync);
+
+error1:
+ DBGPRINT(RT_DEBUG_ERROR, ("memory are not available\n"));
+}
+
+
+VOID RTUSBBssBeaconExit(
+ IN RTMP_ADAPTER *pAd)
+{
+ BEACON_SYNC_STRUCT *pBeaconSync;
+ BOOLEAN Cancelled = TRUE;
+ int i;
+
+ if (pAd->CommonCfg.pBeaconSync)
+ {
+ pBeaconSync = pAd->CommonCfg.pBeaconSync;
+ pBeaconSync->EnableBeacon = FALSE;
+ RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
+ pBeaconSync->BeaconBitMap = 0;
+
+ for(i=0; i<HW_BEACON_MAX_COUNT(pAd); i++)
+ {
+ NdisZeroMemory(pBeaconSync->BeaconBuf[i], HW_BEACON_OFFSET);
+ pBeaconSync->CapabilityInfoLocationInBeacon[i] = 0;
+ pBeaconSync->TimIELocationInBeacon[i] = 0;
+ os_free_mem(pAd, pBeaconSync->BeaconTxWI[i]);
+ }
+
+ os_free_mem(pAd, pAd->CommonCfg.pBeaconSync);
+ pAd->CommonCfg.pBeaconSync = NULL;
+ }
+}
+
+
+/*
+ ========================================================================
+ Routine Description:
+ For device work as AP mode but didn't have TBTT interrupt event, we need a mechanism
+ to update the beacon context in each Beacon interval. Here we use a periodical timer
+ to simulate the TBTT interrupt to handle the beacon context update.
+
+ Arguments:
+ SystemSpecific1 - Not used.
+ FunctionContext - Pointer to our Adapter context.
+ SystemSpecific2 - Not used.
+ SystemSpecific3 - Not used.
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID BeaconUpdateExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
+ LARGE_INTEGER tsfTime_a;/*, tsfTime_b, deltaTime_exp, deltaTime_ab;*/
+ UINT32 delta, delta2MS, period2US, remain, remain_low, remain_high;
+/* BOOLEAN positive;*/
+
+ if (pAd->CommonCfg.IsUpdateBeacon==TRUE)
+ {
+ ReSyncBeaconTime(pAd);
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ BEACON_SYNC_STRUCT *pBeaconSync = pAd->CommonCfg.pBeaconSync;
+ ULONG UpTime;
+
+ /* update channel utilization */
+ NdisGetSystemUpTime(&UpTime);
+
+#ifdef AP_QLOAD_SUPPORT
+ QBSS_LoadUpdate(pAd, UpTime);
+#endif /* AP_QLOAD_SUPPORT */
+
+
+ if (pAd->ApCfg.DtimCount == 0 && pBeaconSync->DtimBitOn)
+ {
+ POS_COOKIE pObj;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+ RTMP_OS_TASKLET_SCHE(&pObj->tbtt_task);
+ }
+
+
+ APUpdateAllBeaconFrame(pAd);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+
+ RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &tsfTime_a.u.LowPart);
+ RTMP_IO_READ32(pAd, TSF_TIMER_DW1, &tsfTime_a.u.HighPart);
+
+
+ /*
+ Calculate next beacon time to wake up to update.
+
+ BeaconRemain = (0xffffffff % (pAd->CommonCfg.BeaconPeriod << 10)) + 1;
+
+ Background: Timestamp (us) % Beacon Period (us) shall be 0 at TBTT
+
+ Formula: (a+b) mod m = ((a mod m) + (b mod m)) mod m
+ (a*b) mod m = ((a mod m) * (b mod m)) mod m
+
+ ==> ((HighPart * 0xFFFFFFFF) + LowPart) mod Beacon_Period
+ ==> (((HighPart * 0xFFFFFFFF) mod Beacon_Period) +
+ (LowPart mod (Beacon_Period))) mod Beacon_Period
+ ==> ((HighPart mod Beacon_Period) * (0xFFFFFFFF mod Beacon_Period)) mod
+ Beacon_Period
+
+ Steps:
+ 1. Calculate the delta time between now and next TBTT;
+
+ delta time = (Beacon Period) - ((64-bit timestamp) % (Beacon Period))
+
+ (1) If no overflow for LowPart, 32-bit, we can calcualte the delta
+ time by using LowPart;
+
+ delta time = LowPart % (Beacon Period)
+
+ (2) If overflow for LowPart, we need to care about HighPart value;
+
+ delta time = (BeaconRemain * HighPart + LowPart) % (Beacon Period)
+
+ Ex: if the maximum value is 0x00 0xFF (255), Beacon Period = 100,
+ TBTT timestamp will be 100, 200, 300, 400, ...
+ when TBTT timestamp is 300 = 1*56 + 44, means HighPart = 1,
+ Low Part = 44
+
+ 2. Adjust next update time of the timer to (delta time + 10ms).
+ */
+
+ /*positive=getDeltaTime(tsfTime_a, expectedTime, &deltaTime_exp);*/
+ period2US = (pAd->CommonCfg.BeaconPeriod << 10);
+ remain_high = pAd->CommonCfg.BeaconRemain * tsfTime_a.u.HighPart;
+ remain_low = tsfTime_a.u.LowPart % (pAd->CommonCfg.BeaconPeriod << 10);
+ remain = (remain_high + remain_low)%(pAd->CommonCfg.BeaconPeriod << 10);
+ delta = (pAd->CommonCfg.BeaconPeriod << 10) - remain;
+
+ delta2MS = (delta>>10);
+ if (delta2MS > 150)
+ {
+ pAd->CommonCfg.BeaconUpdateTimer.TimerValue = 100;
+ pAd->CommonCfg.IsUpdateBeacon=FALSE;
+ }
+ else
+ {
+ pAd->CommonCfg.BeaconUpdateTimer.TimerValue = delta2MS + 10;
+ pAd->CommonCfg.IsUpdateBeacon=TRUE;
+ }
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if ((pAd->CommonCfg.Channel > 14)
+ && (pAd->CommonCfg.bIEEE80211H == 1)
+ && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE))
+ {
+ ChannelSwitchingCountDownProc(pAd);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+}
+
+
+/********************************************************************
+ *
+ * 2870 Radio on/off Related functions.
+ *
+ ********************************************************************/
+VOID RT28xxUsbMlmeRadioOn(
+ IN PRTMP_ADAPTER pAd)
+{
+
+ DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOn()\n"));
+
+ if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
+ return;
+
+ ASIC_RADIO_ON(pAd, MLME_RADIO_ON);
+
+ /* Clear Radio off flag*/
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ APStartUp(pAd);
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef LED_CONTROL_SUPPORT
+ /* Set LED*/
+#ifdef CONFIG_AP_SUPPORT
+ RTMPSetLED(pAd, LED_LINK_UP);
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* LED_CONTROL_SUPPORT */
+
+}
+
+
+VOID RT28xxUsbMlmeRadioOFF(
+ IN PRTMP_ADAPTER pAd)
+{
+#ifdef WSC_INCLUDED
+#ifdef WSC_LED_SUPPORT
+ UINT WPSLedMode10;
+#endif /* WSC_LED_SUPPORT */
+#endif /* WSC_INCLUDED */
+
+ DBGPRINT(RT_DEBUG_TRACE,("RT28xxUsbMlmeRadioOFF()\n"));
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
+ return;
+
+#ifdef WSC_INCLUDED
+#ifdef WSC_LED_SUPPORT
+ if(LED_MODE(pAd) == WPS_LED_MODE_10)
+ {
+ //WPSLedMode10 = LINK_STATUS_WPS_MODE10_TURN_OFF;
+ //RTEnqueueInternalCmd(pAd, CMDTHREAD_LED_WPS_MODE10, &WPSLedMode10, sizeof(WPSLedMode10));
+ }
+#endif /* WSC_LED_SUPPORT */
+#endif /* WSC_INCLUDED */
+
+
+ /* Set Radio off flag*/
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ APStop(pAd);
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef LED_CONTROL_SUPPORT
+ /* Set LED*/
+ RTMPSetLED(pAd, LED_RADIO_OFF);
+#endif /* LED_CONTROL_SUPPORT */
+
+ ASIC_RADIO_OFF(pAd, MLME_RADIO_OFF);
+}
+
+
+VOID RT28xxUsbAsicRadioOff(RTMP_ADAPTER *pAd)
+{
+ WPDMA_GLO_CFG_STRUC GloCfg;
+ UINT32 Value;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> %s\n", __FUNCTION__));
+
+ if (pAd->CommonCfg.CentralChannel)
+ AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
+ else
+ AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
+
+#ifdef MT7601
+ if ( IS_MT7601(pAd) )
+ {
+ //MT7601DisableTxRx(pAd, GUIRADIO_OFF);
+ MT7601DisableTxRx(pAd, GUIRADIO_OFF);
+
+ AndesPwrSavingOP(pAd, RADIO_OFF, 0x01, 0, 0, 0, 0);
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD);
+ }
+ else
+#endif /* MT7601 */
+ {
+ /* Disable Tx/Rx DMA*/
+ RTUSBReadMACRegister(pAd, WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */
+ GloCfg.field.EnableTxDMA = 0;
+ GloCfg.field.EnableRxDMA = 0;
+ RTUSBWriteMACRegister(pAd, WPDMA_GLO_CFG, GloCfg.word, FALSE); /* abort all TX rings*/
+
+ /* Waiting for DMA idle*/
+ AsicWaitPDMAIdle(pAd, 100, 1000);
+
+ /* Disable MAC Tx/Rx*/
+ RTUSBReadMACRegister(pAd, MAC_SYS_CTRL, &Value);
+ Value &= (0xfffffff3);
+ RTUSBWriteMACRegister(pAd, MAC_SYS_CTRL, Value, FALSE);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<== %s\n", __FUNCTION__));
+
+}
+
+
+VOID RT28xxUsbAsicRadioOn(RTMP_ADAPTER *pAd)
+{
+ UINT32 MACValue = 0;
+ BOOLEAN brc;
+ UINT RetryRound = 0;
+ UINT32 rx_filter_flag;
+ WPDMA_GLO_CFG_STRUC GloCfg;
+ RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
+
+
+#ifdef CONFIG_PM
+#ifdef USB_SUPPORT_SELECTIVE_SUSPEND
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> %s\n", __FUNCTION__));
+
+ if( (RTMP_Usb_AutoPM_Get_Interface(pObj->pUsb_Dev,pObj->intf)) == 1)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RT28xxUsbAsicRadioOn: autopm_resume success\n"));
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_SUSPEND);
+ }
+ else if ((RTMP_Usb_AutoPM_Get_Interface(pObj->pUsb_Dev,pObj->intf)) == (-1))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RT28xxUsbAsicRadioOn autopm_resume fail ------\n"));
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_SUSPEND);
+ return;
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("RT28xxUsbAsicRadioOn: autopm_resume do nothing \n"));
+
+#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */
+#endif /* CONFIG_PM */
+
+
+ /* make some traffic to invoke EvtDeviceD0Entry callback function*/
+
+
+ RTUSBReadMACRegister(pAd,0x1000,&MACValue);
+ DBGPRINT(RT_DEBUG_TRACE,("A MAC query to invoke EvtDeviceD0Entry, MACValue = 0x%x\n",MACValue));
+
+ /* 1. Send wake up command.*/
+
+#ifdef MT7601
+ if ( IS_MT7601(pAd) )
+ {
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD);
+ AndesPwrSavingOP(pAd, RADIO_ON, 0, 0, 0, 0, 0);
+
+ //pAd->hw_cfg.cent_ch = pAd->CommonCfg.CentralChannel;
+
+ //AsicSwitchChannel(pAd, pAd->hw_cfg.cent_ch, FALSE);
+ //AsicLockChannel(pAd, pAd->hw_cfg.cent_ch);
+
+ }
+ else
+#endif /* MT7601 */
+ {
+ RetryRound = 0;
+
+ do
+ {
+ brc = AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02, FALSE);
+ if (brc)
+ {
+ /* Wait command ok.*/
+ brc = AsicCheckCommandOk(pAd, PowerWakeCID);
+ }
+ if(brc){
+ break; /* PowerWakeCID cmd successed*/
+ }
+ DBGPRINT(RT_DEBUG_WARN, ("PSM :WakeUp Cmd Failed, retry %d\n", RetryRound));
+
+ /* try 10 times at most*/
+ if ((RetryRound++) > 10)
+ break;
+ /* delay and try again*/
+ RTMPusecDelay(200);
+ } while (TRUE);
+ if (RetryRound > 10)
+ DBGPRINT(RT_DEBUG_WARN, ("PSM :ASIC 0x31 WakeUp Cmd may Fail %d*******\n", RetryRound));
+
+ }
+
+
+ /* 2. Enable Tx/Rx DMA.*/
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
+
+
+ /* enable RX of MAC block*/
+
+#ifdef XLINK_SUPPORT
+ if (pAd->StaCfg.PSPXlink)
+ rx_filter_flag = PSPXLINK;
+ else
+#endif /* XLINK_SUPPORT */
+ rx_filter_flag = STANORMAL; /* Staion not drop control frame will fail WiFi Certification.*/
+ RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
+
+ /* 3. Turn on RF*/
+/* RT28xxUsbAsicRFOn(pAd);*/
+ if (pChipOps->AsicReverseRfFromSleepMode)
+ pChipOps->AsicReverseRfFromSleepMode(pAd, FALSE);
+
+
+ /* 4. Clear idle flag*/
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
+
+ /* Send Bulkin IRPs after flag fRTMP_ADAPTER_IDLE_RADIO_OFF is cleared.*/
+ /* */
+ DBGPRINT(RT_DEBUG_TRACE, ("<== %s\n", __FUNCTION__));
+
+
+}
+
+
+BOOLEAN AsicCheckCommandOk(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Command)
+{
+ UINT32 CmdStatus, CID, i;
+ UINT32 ThisCIDMask = 0;
+ INT ret;
+
+
+#ifdef RTMP_MAC_USB
+ if (IS_USB_INF(pAd))
+ {
+ RTMP_SEM_EVENT_WAIT(&pAd->reg_atomic, ret);
+ if (ret != 0) {
+ DBGPRINT(RT_DEBUG_ERROR, ("reg_atomic get failed(ret=%d)\n", ret));
+ return FALSE;
+ }
+ }
+#endif /* RTMP_MAC_USB */
+
+ i = 0;
+ do
+ {
+ RTUSBReadMACRegister(pAd, H2M_MAILBOX_CID, &CID);
+ if ((CID & CID0MASK) == Command)
+ {
+ ThisCIDMask = CID0MASK;
+ break;
+ }
+ else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
+ {
+ ThisCIDMask = CID1MASK;
+ break;
+ }
+ else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
+ {
+ ThisCIDMask = CID2MASK;
+ break;
+ }
+ else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
+ {
+ ThisCIDMask = CID3MASK;
+ break;
+ }
+
+ RTMPusecDelay(100);
+ i++;
+ }while (i < 200);
+
+ ret = FALSE;
+ RTUSBReadMACRegister(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
+ if (i < 200)
+ {
+ if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
+ || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
+ ret = TRUE;
+ }
+ RTUSBWriteMACRegister(pAd, H2M_MAILBOX_STATUS, 0xffffffff, FALSE);
+ RTUSBWriteMACRegister(pAd, H2M_MAILBOX_CID, 0xffffffff, FALSE);
+
+#ifdef RTMP_MAC_USB
+ if (IS_USB_INF(pAd))
+ {
+ RTMP_SEM_EVENT_UP(&pAd->reg_atomic);
+ }
+#endif /* RTMP_MAC_USB */
+
+
+ return ret;
+
+}
+
+
+#ifdef WOW_SUPPORT
+VOID RT28xxUsbAsicWOWEnable(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 Value;
+
+ /* load WOW-enable firmware */
+ AsicLoadWOWFirmware(pAd, TRUE);
+ /* put null frame data to MCU memory from 0x7780 */
+ AsicWOWSendNullFrame(pAd, pAd->CommonCfg.TxRate, (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) ? TRUE:FALSE));
+ /* send WOW enable command to MCU. */
+ AsicSendCommandToMcu(pAd, 0x33, 0xff, pAd->WOW_Cfg.nSelectedGPIO, pAd->WOW_Cfg.nDelay, FALSE);
+ /* set GPIO pulse hold time at MSB (Byte) */
+ RTMP_IO_READ32(pAd, GPIO_HOLDTIME_OFFSET, &Value);
+ Value &= 0x00FFFFFF;
+ Value |= (pAd->WOW_Cfg.nHoldTime << 24);
+ RTMP_IO_WRITE32(pAd, GPIO_HOLDTIME_OFFSET, Value);
+ DBGPRINT(RT_DEBUG_OFF, ("Send WOW enable cmd (%d/%d/%d)\n", pAd->WOW_Cfg.nDelay, pAd->WOW_Cfg.nSelectedGPIO, pAd->WOW_Cfg.nHoldTime));
+ RTMP_IO_READ32(pAd, GPIO_HOLDTIME_OFFSET, &Value);
+ DBGPRINT(RT_DEBUG_OFF, ("Hold time: 0x7020 ==> %x\n", Value));
+}
+
+VOID RT28xxUsbAsicWOWDisable(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 Value;
+ /* load normal firmware */
+ AsicLoadWOWFirmware(pAd, FALSE);
+ /* for suspend/resume, needs to restore RX Queue operation mode to auto mode */
+ RTMP_IO_READ32(pAd, PBF_CFG, &Value);
+ Value &= ~0x2200;
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Value);
+ //AsicSendCommandToMcu(pAd, 0x34, 0xff, 0x00, 0x00, FALSE); /* send WOW disable command to MCU*/
+ DBGPRINT(RT_DEBUG_OFF, ("MCU back to normal mode (%d/%d)\n", pAd->WOW_Cfg.nDelay, pAd->WOW_Cfg.nSelectedGPIO));
+}
+#endif /* WOW_SUPPORT */
+#endif /* RTMP_MAC_USB */
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_mat.c b/cleopatre/devkit/mt7601udrv/common/cmm_mat.c
new file mode 100644
index 0000000000..307c9b0255
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_mat.c
@@ -0,0 +1,443 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ cmm_mat.c
+
+ Abstract:
+ Support Mac Address Translation function.
+
+ Note:
+ MAC Address Translation(MAT) engine subroutines, we should just take care
+ packet to bridge.
+
+ Revision History:
+ Who When What
+ -------------- ---------- ----------------------------------------------
+ Shiang 02-26-2007 Init version
+*/
+
+#ifdef MAT_SUPPORT
+
+#include "rt_config.h"
+
+
+extern MATProtoOps MATProtoIPHandle;
+extern MATProtoOps MATProtoARPHandle;
+extern MATProtoOps MATProtoPPPoEDisHandle;
+extern MATProtoOps MATProtoPPPoESesHandle;
+extern MATProtoOps MATProtoIPv6Handle;
+
+extern UCHAR SNAP_802_1H[];
+extern UCHAR SNAP_BRIDGE_TUNNEL[];
+
+#define MAX_MAT_NODE_ENTRY_NUM 128 /* We support maximum 128 node entry for our system */
+#define MAT_NODE_ENTRY_SIZE 40 /*28 // bytes //change to 40 for IPv6Mac Table */
+
+typedef struct _MATNodeEntry
+{
+ UCHAR data[MAT_NODE_ENTRY_SIZE];
+ struct _MATNodeEntry *next;
+}MATNodeEntry, *PMATNodeEntry;
+
+
+#ifdef KMALLOC_BATCH
+/*static MATNodeEntry *MATNodeEntryPoll = NULL; */
+#endif
+
+static MATProtoTable MATProtoTb[]=
+{
+ {ETH_P_IP, &MATProtoIPHandle}, /* IP handler */
+ {ETH_P_ARP, &MATProtoARPHandle}, /* ARP handler */
+ {ETH_P_PPP_DISC, &MATProtoPPPoEDisHandle}, /* PPPoE discovery stage handler */
+ {ETH_P_PPP_SES, &MATProtoPPPoESesHandle}, /* PPPoE session stage handler */
+ {ETH_P_IPV6, &MATProtoIPv6Handle}, /* IPv6 handler */
+};
+
+#define MAX_MAT_SUPPORT_PROTO_NUM (sizeof(MATProtoTb)/sizeof(MATProtoTable))
+
+
+/* --------------------------------- Public Function-------------------------------- */
+NDIS_STATUS MATDBEntryFree(
+ IN MAT_STRUCT *pMatStruct,
+ IN PUCHAR NodeEntry)
+{
+#ifdef KMALLOC_BATCH
+ MATNodeEntry *pPtr, *pMATNodeEntryPoll;
+
+ pMATNodeEntryPoll = (MATNodeEntry *)pAd->MatCfg.MATNodeEntryPoll;
+ pPtr = (MATNodeEntry *)NodeEntry;
+ NdisZeroMemory(pPtr, sizeof(MATNodeEntry));
+ if (pMATNodeEntryPoll->next)
+ {
+ pPtr->next = pMATNodeEntryPoll->next;
+ pMATNodeEntryPoll->next = pPtr;
+ } else {
+ pMATNodeEntryPoll->next = pPtr;
+ }
+#else
+ os_free_mem(NULL, NodeEntry);
+#endif
+
+ return TRUE;
+
+}
+
+PUCHAR MATDBEntryAlloc(IN MAT_STRUCT *pMatStruct, IN UINT32 size)
+{
+#ifdef KMALLOC_BATCH
+ MATNodeEntry *pPtr = NULL, *pMATNodeEntryPoll;
+ pMATNodeEntryPoll = (MATNodeEntry *)pMatStruct->pMATNodeEntryPoll;
+
+ if (pMATNodeEntryPoll->next)
+ {
+ pPtr = pMATNodeEntryPoll->next;
+ pMATNodeEntryPoll->next = pPtr->next;
+ }
+
+#else
+ UCHAR *pPtr = NULL;
+
+ os_alloc_mem(NULL, (PUCHAR *)&pPtr, size);
+ /*pPtr = kmalloc(size, MEM_ALLOC_FLAG); */
+
+#endif
+
+ return (PUCHAR)pPtr;
+}
+
+
+VOID dumpPkt(PUCHAR pHeader, int len)
+{
+ int i;
+ PSTRING tmp;
+
+ tmp = (PSTRING)pHeader;
+
+ DBGPRINT(RT_DEBUG_OFF, ("--StartDump\n"));
+ for(i=0;i<len; i++)
+ {
+ if ( (i%16==0) && (i!=0))
+ DBGPRINT(RT_DEBUG_OFF, ("\n"));
+ DBGPRINT(RT_DEBUG_OFF, ("%02x ", tmp[i]& 0xff));
+ }
+ DBGPRINT(RT_DEBUG_OFF, ("\n--EndDump\n"));
+
+ return;
+}
+
+
+/*
+ ========================================================================
+ Routine Description:
+ For each out-going packet, check the upper layer protocol type if need
+ to handled by our APCLI convert engine. If yes, call corresponding handler
+ to handle it.
+
+ Arguments:
+ pAd =>Pointer to our adapter
+ pPkt =>pointer to the 802.11 header of outgoing packet
+ ifIdx =>Interface Index want to dispatch to.
+
+ Return Value:
+ Success =>
+ TRUE
+ Mapped mac address if found, else return specific default mac address
+ depends on the upper layer protocol type.
+ Error =>
+ FALSE.
+
+ Note:
+ 1.the pPktHdr must be a 802.3 packet.
+ 2.Maybe we need a TxD arguments?
+ 3.We check every packet here including group mac address becasue we need to
+ handle DHCP packet.
+ ========================================================================
+ */
+PUCHAR MATEngineTxHandle(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPkt,
+ IN UINT ifIdx,
+ IN UCHAR OpMode)
+{
+ PUCHAR pLayerHdr = NULL, pPktHdr = NULL, pMacAddr = NULL;
+ UINT16 protoType, protoType_ori;
+ INT i;
+ struct _MATProtoOps *pHandle = NULL;
+ PUCHAR retSkb = NULL;
+ BOOLEAN bVLANPkt = FALSE;
+
+
+ if(pAd->MatCfg.status != MAT_ENGINE_STAT_INITED)
+ return NULL;
+
+ pPktHdr = GET_OS_PKT_DATAPTR(pPkt);
+ if (!pPktHdr)
+ return NULL;
+
+ protoType_ori = get_unaligned((PUINT16)(pPktHdr + 12));
+
+ /* Get the upper layer protocol type of this 802.3 pkt. */
+ protoType = OS_NTOHS(protoType_ori);
+
+ /* handle 802.1q enabled packet. Skip the VLAN tag field to get the protocol type. */
+ if (protoType == 0x8100)
+ {
+ protoType_ori = get_unaligned((PUINT16)(pPktHdr + 12 + 4));
+ protoType = OS_NTOHS(protoType_ori);
+ bVLANPkt = TRUE;
+ }
+
+
+ /* For differnet protocol, dispatch to specific handler */
+ for (i=0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++)
+ {
+ if (protoType == MATProtoTb[i].protocol)
+ {
+ pHandle = MATProtoTb[i].pHandle; /* the pHandle must not be null! */
+ pLayerHdr = bVLANPkt ? (pPktHdr + MAT_VLAN_ETH_HDR_LEN) : (pPktHdr + MAT_ETHER_HDR_LEN);
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ pMacAddr = &pAd->ApCfg.ApCliTab[ifIdx].CurrentAddress[0];
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ if (pHandle->tx!=NULL)
+ retSkb = pHandle->tx((PVOID)&pAd->MatCfg, RTPKT_TO_OSPKT(pPkt), pLayerHdr, pMacAddr);
+
+ return retSkb;
+ }
+ }
+ return retSkb;
+}
+
+
+/*
+ ========================================================================
+ Routine Description:
+ Depends on the Received packet, check the upper layer protocol type
+ and search for specific mapping table to find out the real destination
+ MAC address.
+
+ Arguments:
+ pAd =>Pointer to our adapter
+ pPkt =>pointer to the 802.11 header of receviced packet
+ infIdx =>Interface Index want to dispatch to.
+
+ Return Value:
+ Success =>
+ Mapped mac address if found, else return specific default mac address
+ depends on the upper layer protocol type.
+ Error =>
+ NULL
+
+ Note:
+ ========================================================================
+ */
+PUCHAR MATEngineRxHandle(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPkt,
+ IN UINT infIdx)
+{
+ PUCHAR pMacAddr = NULL;
+ PUCHAR pLayerHdr = NULL, pPktHdr = NULL;
+ UINT16 protoType;
+ INT i =0;
+ struct _MATProtoOps *pHandle = NULL;
+
+
+ if(pAd->MatCfg.status != MAT_ENGINE_STAT_INITED)
+ return NULL;
+
+ pPktHdr = GET_OS_PKT_DATAPTR(pPkt);
+ if (!pPktHdr)
+ return NULL;
+
+ /* If it's a multicast/broadcast packet, we do nothing. */
+ if (IS_GROUP_MAC(pPktHdr))
+ return NULL;
+
+ /* Get the upper layer protocol type of this 802.3 pkt and dispatch to specific handler */
+ protoType = OS_NTOHS(get_unaligned((PUINT16)(pPktHdr + 12)));
+
+ for (i=0; i<MAX_MAT_SUPPORT_PROTO_NUM; i++)
+ {
+ if (protoType == MATProtoTb[i].protocol)
+ {
+ pHandle = MATProtoTb[i].pHandle; /* the pHandle must not be null! */
+ pLayerHdr = (pPktHdr + MAT_ETHER_HDR_LEN);
+/* RTMP_SEM_LOCK(&MATDBLock); */
+ if(pHandle->rx!=NULL)
+ pMacAddr = pHandle->rx((PVOID)&pAd->MatCfg, RTPKT_TO_OSPKT(pPkt), pLayerHdr, NULL);
+/* RTMP_SEM_UNLOCK(&MATDBLock); */
+ break;
+ }
+ }
+
+ if (pMacAddr)
+ NdisMoveMemory(pPktHdr, pMacAddr, MAC_ADDR_LEN);
+
+ return NULL;
+
+}
+
+
+BOOLEAN MATPktRxNeedConvert(
+ IN PRTMP_ADAPTER pAd,
+ IN PNET_DEV net_dev)
+{
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ int i = 0;
+
+ /* Check if the packet will be send to apcli interface. */
+ while(i<MAX_APCLI_NUM)
+ {
+ /*BSSID match the ApCliBssid ?(from a valid AP) */
+ if ((pAd->ApCfg.ApCliTab[i].Valid == TRUE)
+ && (net_dev == pAd->ApCfg.ApCliTab[i].dev))
+ return TRUE;
+ i++;
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ return FALSE;
+
+}
+
+
+NDIS_STATUS MATEngineExit(
+ IN RTMP_ADAPTER *pAd)
+{
+ struct _MATProtoOps *pHandle = NULL;
+ int i;
+
+ if(pAd->MatCfg.status == MAT_ENGINE_STAT_EXITED)
+ return TRUE;
+
+ /* For each registered protocol, we call it's exit handler. */
+ for (i=0; i<MAX_MAT_SUPPORT_PROTO_NUM; i++)
+ {
+ pHandle = MATProtoTb[i].pHandle;
+ if (pHandle->exit!=NULL)
+ pHandle->exit(&pAd->MatCfg);
+ }
+
+#ifdef KMALLOC_BATCH
+ /* Free the memory used to store node entries. */
+ if (pAd->MatCfg.pMATNodeEntryPoll)
+ {
+ os_free_mem(pAd, pAd->MatCfg.pMATNodeEntryPoll);
+ pAd->MatCfg.pMATNodeEntryPoll = NULL;
+ }
+#endif
+
+ pAd->MatCfg.status = MAT_ENGINE_STAT_EXITED;
+
+ return TRUE;
+
+}
+
+
+NDIS_STATUS MATEngineInit(
+ IN RTMP_ADAPTER *pAd)
+{
+ MATProtoOps *pHandle = NULL;
+ int i, status;
+
+ if(pAd->MatCfg.status == MAT_ENGINE_STAT_INITED)
+ return TRUE;
+
+#ifdef KMALLOC_BATCH
+ /* Allocate memory for node entry, we totally allocate 128 entries and link them together. */
+/* pAd->MatCfg.pMATNodeEntryPoll = kmalloc(sizeof(MATNodeEntry) * MAX_MAT_NODE_ENTRY_NUM, GFP_KERNEL); */
+ os_alloc_mem_suspend(NULL, (UCHAR **)&(pAd->MatCfg.pMATNodeEntryPoll), sizeof(MATNodeEntry) * MAX_MAT_NODE_ENTRY_NUM);
+ if (pAd->MatCfg.pMATNodeEntryPoll != NULL)
+ {
+ MATNodeEntry *pPtr=NULL;
+
+ NdisZeroMemory(pAd->MatCfg.pMATNodeEntryPoll, sizeof(MATNodeEntry) * MAX_MAT_NODE_ENTRY_NUM);
+ pPtr = pAd->MatCfg.pMATNodeEntryPoll;
+ for (i = 0; i < (MAX_MAT_NODE_ENTRY_NUM -1); i++)
+ {
+ pPtr->next = (MATNodeEntry *)(pPtr+1);
+ pPtr = pPtr->next;
+ }
+ pPtr->next = NULL;
+ } else {
+ return FALSE;
+ }
+#endif
+
+ /* For each specific protocol, call it's init function. */
+ for (i = 0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++)
+ {
+ pHandle = MATProtoTb[i].pHandle;
+ ASSERT(pHandle);
+ if (pHandle->init != NULL)
+ {
+ status = pHandle->init(&pAd->MatCfg);
+ if (status == FALSE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MATEngine Init Protocol (0x%x) failed, Stop the MAT Funciton initialization failed!\n", MATProtoTb[i].protocol));
+ goto init_failed;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("MATEngine Init Protocol (0x%04x) success!\n", MATProtoTb[i].protocol));
+ }
+ }
+
+ NdisAllocateSpinLock(pAd, &pAd->MatCfg.MATDBLock);
+ pAd->MatCfg.pPriv = (VOID *)pAd;
+ pAd->MatCfg.status = MAT_ENGINE_STAT_INITED;
+
+ return TRUE;
+
+init_failed:
+ /* For each specific protocol, call it's exit function. */
+ for (i = 0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++)
+ {
+ if ((pHandle = MATProtoTb[i].pHandle) != NULL)
+ {
+ if (pHandle->exit != NULL)
+ {
+ status = pHandle->exit(&pAd->MatCfg);
+ if (status == FALSE)
+ goto init_failed;
+ }
+ }
+ }
+
+#ifdef KMALLOC_BATCH
+ if (pAd->MatCfg.pMATNodeEntryPoll)
+ os_free_mem(pAd, pAd->MatCfg.pMATNodeEntryPoll);
+ pAd->MatCfg.status = MAT_ENGINE_STAT_EXITED;
+#endif /* KMALLOC_BATCH */
+
+ return FALSE;
+
+}
+
+#endif /* MAT_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_mat_iparp.c b/cleopatre/devkit/mt7601udrv/common/cmm_mat_iparp.c
new file mode 100644
index 0000000000..5f799962e3
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_mat_iparp.c
@@ -0,0 +1,694 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ cmm_mat_iparp.c
+
+ Abstract:
+ MAT convert engine subroutine for ip base protocols, currently now we
+ just handle IP/ARP protocols.
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Shiang 02/26/07 Init version
+*/
+#ifdef MAT_SUPPORT
+
+#include "rt_config.h"
+
+static NDIS_STATUS MATProto_IP_Init(MAT_STRUCT *pMatCfg);
+static NDIS_STATUS MATProto_IP_Exit(MAT_STRUCT *pMatCfg);
+static PUCHAR MATProto_IP_Rx(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pMacAddr);
+static PUCHAR MATProto_IP_Tx(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pMacAddr);
+
+static NDIS_STATUS MATProto_ARP_Init(MAT_STRUCT *pMatCfg);
+static NDIS_STATUS MATProto_ARP_Exit(MAT_STRUCT *pMatCfg);
+static PUCHAR MATProto_ARP_Rx(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pMacAddr);
+static PUCHAR MATProto_ARP_Tx(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb,PUCHAR pLayerHdr, PUCHAR pMacAddr);
+
+#define IPV4_ADDR_LEN 4
+
+#define NEED_UPDATE_IPMAC_TB(Mac, IP) (IS_UCAST_MAC(Mac) && IS_GOOD_IP(IP))
+
+
+typedef struct _IPMacMappingEntry
+{
+ UINT ipAddr; /* In network order */
+ UCHAR macAddr[MAC_ADDR_LEN];
+ ULONG lastTime;
+ struct _IPMacMappingEntry *pNext;
+}IPMacMappingEntry, *PIPMacMappingEntry;
+
+
+typedef struct _IPMacMappingTable
+{
+ BOOLEAN valid;
+ IPMacMappingEntry *hash[MAT_MAX_HASH_ENTRY_SUPPORT+1]; /*0~63 for specific station, 64 for broadcast MacAddress */
+ UCHAR curMcastAddr[MAC_ADDR_LEN]; /* The multicast mac addr for currecnt received packet destined to ipv4 multicast addr */
+}IPMacMappingTable;
+
+
+struct _MATProtoOps MATProtoIPHandle =
+{
+ .init = MATProto_IP_Init,
+ .tx = MATProto_IP_Tx,
+ .rx = MATProto_IP_Rx,
+ .exit = MATProto_IP_Exit,
+};
+
+struct _MATProtoOps MATProtoARPHandle =
+{
+ .init = MATProto_ARP_Init,
+ .tx = MATProto_ARP_Tx,
+ .rx = MATProto_ARP_Rx,
+ .exit =MATProto_ARP_Exit,
+};
+
+
+VOID dumpIPMacTb(
+ IN MAT_STRUCT *pMatCfg,
+ IN int index)
+{
+ IPMacMappingTable *pIPMacTable;
+ IPMacMappingEntry *pHead;
+ int startIdx, endIdx;
+
+ pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
+ if (!pIPMacTable)
+ return;
+
+ if (!pIPMacTable->valid)
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("%s():IPMacTable not init yet, so cannot do dump!\n", __FUNCTION__));
+ return;
+ }
+
+
+ if(index < 0)
+ { /* dump all. */
+ startIdx = 0;
+ endIdx = MAT_MAX_HASH_ENTRY_SUPPORT;
+ }
+ else
+ { /* dump specific hash index. */
+ startIdx = endIdx = index;
+ }
+
+ DBGPRINT(RT_DEBUG_OFF, ("%s():\n", __FUNCTION__));
+ for(; startIdx<= endIdx; startIdx++)
+ {
+ pHead = pIPMacTable->hash[startIdx];
+ while(pHead)
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("IPMac[%d]:\n", startIdx));
+ DBGPRINT(RT_DEBUG_OFF, ("\t:IP=0x%x,Mac=%02x:%02x:%02x:%02x:%02x:%02x, lastTime=0x%lx, next=%p\n",
+ pHead->ipAddr, pHead->macAddr[0],pHead->macAddr[1],pHead->macAddr[2],
+ pHead->macAddr[3],pHead->macAddr[4],pHead->macAddr[5], pHead->lastTime,
+ pHead->pNext));
+ pHead = pHead->pNext;
+ }
+ }
+ DBGPRINT(RT_DEBUG_OFF, ("\t----EndOfDump!\n"));
+
+}
+
+
+static inline NDIS_STATUS getDstIPFromIpPkt(
+ IN PUCHAR pIpHdr,
+ IN UINT *dstIP)
+{
+
+ if (!pIpHdr)
+ return FALSE;
+
+ NdisMoveMemory(dstIP, (pIpHdr + 16), 4); /*shift 16 for IP header len before DstIP. */
+/* DBGPRINT(RT_DEBUG_TRACE, ("%s(): Get the dstIP=0x%x\n", __FUNCTION__, *dstIP)); */
+
+ return TRUE;
+}
+
+static inline NDIS_STATUS getSrcIPFromIpPkt(
+ IN PUCHAR pIpHdr,
+ IN UINT *pSrcIP)
+{
+
+ if (!pIpHdr)
+ return FALSE;
+
+ NdisMoveMemory(pSrcIP, (pIpHdr + 12), 4); /*shift 12 for IP header len before DstIP. */
+/* DBGPRINT(RT_DEBUG_TRACE, ("%s(): Get the srcIP=0x%x\n", __FUNCTION__, *pSrcIP)); */
+
+ return TRUE;
+
+}
+
+static NDIS_STATUS IPMacTableUpdate(
+ IN MAT_STRUCT *pMatCfg,
+ IN PUCHAR pMacAddr,
+ IN UINT ipAddr)
+{
+ UINT hashIdx;
+ IPMacMappingTable *pIPMacTable;
+ IPMacMappingEntry *pEntry = NULL, *pPrev = NULL, *pNewEntry =NULL;
+ ULONG now;
+
+ pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
+
+ if (!pIPMacTable)
+ return FALSE;
+
+ if (!pIPMacTable->valid)
+ return FALSE;
+
+ hashIdx = MAT_IP_ADDR_HASH_INDEX(ipAddr);
+
+ pEntry = pPrev = pIPMacTable->hash[hashIdx];
+ while(pEntry)
+ {
+ NdisGetSystemUpTime(&now);
+
+ /* Find a existed IP-MAC Mapping entry */
+ if (ipAddr == pEntry->ipAddr)
+ {
+ /* DBGPRINT(RT_DEBUG_TRACE, ("%s(): Got the Mac(%02x:%02x:%02x:%02x:%02x:%02x) of mapped IP(%d.%d.%d.%d)\n",
+ __FUNCTION__, pEntry->macAddr[0],pEntry->macAddr[1],pEntry->macAddr[2], pEntry->macAddr[3],pEntry->macAddr[4],
+ pEntry->macAddr[5], (ipAddr>>24) & 0xff, (ipAddr>>16) & 0xff, (ipAddr>>8) & 0xff, ipAddr & 0xff));
+ */
+ /* compare is useless. So we directly copy it into the entry. */
+ NdisMoveMemory(pEntry->macAddr, pMacAddr, 6);
+ pEntry->lastTime = now;
+ return TRUE;
+ }
+ else
+ { /* handle the age-out situation */
+ /*if ((Now - pEntry->lastTime) > MAT_TB_ENTRY_AGEOUT_TIME) */
+ if (RTMP_TIME_AFTER(now, pEntry->lastTime + MAT_TB_ENTRY_AGEOUT_TIME))
+ {
+ /* Remove the aged entry */
+ if (pEntry == pIPMacTable->hash[hashIdx])
+ {
+ pIPMacTable->hash[hashIdx]= pEntry->pNext;
+ pPrev = pIPMacTable->hash[hashIdx];
+ }
+ else
+ {
+ pPrev->pNext = pEntry->pNext;
+ }
+ MATDBEntryFree(pMatCfg, (PUCHAR)pEntry);
+
+ pEntry = (pPrev == NULL ? NULL: pPrev->pNext);
+ pMatCfg->nodeCount--;
+ }
+ else
+ {
+ pPrev = pEntry;
+ pEntry = pEntry->pNext;
+ }
+ }
+ }
+
+
+ /* Allocate a new IPMacMapping entry and insert into the hash */
+ pNewEntry = (IPMacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(IPMacMappingEntry));
+ if (pNewEntry != NULL)
+ {
+ pNewEntry->ipAddr = ipAddr;
+ NdisMoveMemory(pNewEntry->macAddr, pMacAddr, 6);
+ pNewEntry->pNext = NULL;
+ NdisGetSystemUpTime(&pNewEntry->lastTime);
+
+ if (pIPMacTable->hash[hashIdx] == NULL)
+ { /* Hash list is empty, directly assign it. */
+ pIPMacTable->hash[hashIdx] = pNewEntry;
+ }
+ else
+ {
+ /* Ok, we insert the new entry into the root of hash[hashIdx] */
+ pNewEntry->pNext = pIPMacTable->hash[hashIdx];
+ pIPMacTable->hash[hashIdx] = pNewEntry;
+ }
+ /*dumpIPMacTb(pMatCfg, hashIdx); //for debug */
+
+ pMatCfg->nodeCount++;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+static PUCHAR IPMacTableLookUp(
+ IN MAT_STRUCT *pMatCfg,
+ IN UINT ipAddr)
+{
+ IPMacMappingTable *pIPMacTable;
+ UINT hashIdx, ip;
+ IPMacMappingEntry *pEntry = NULL;
+ PUCHAR pGroupMacAddr;
+
+ pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
+
+ if (!pIPMacTable)
+ return NULL;
+
+ if (!pIPMacTable->valid)
+ return NULL;
+
+ /*if multicast ip, need converting multicast group address to ethernet address. */
+ ip = ntohl(ipAddr);
+ if (IS_MULTICAST_IP(ip))
+ {
+ pGroupMacAddr = (PUCHAR)(&pIPMacTable->curMcastAddr);
+ ConvertMulticastIP2MAC((PUCHAR) &ipAddr, (UCHAR **)(&pGroupMacAddr), ETH_P_IP);
+ return pIPMacTable->curMcastAddr;
+ }
+
+ /* Use hash to find out the location of that entry and get the Mac address. */
+ hashIdx = MAT_IP_ADDR_HASH_INDEX(ipAddr);
+
+/* spin_lock_irqsave(&IPMacTabLock, irqFlag); */
+ pEntry = pIPMacTable->hash[hashIdx];
+ while(pEntry)
+ {
+ if (pEntry->ipAddr == ipAddr)
+ {
+/* DBGPRINT(RT_DEBUG_TRACE, ("%s(): dstMac=%02x:%02x:%02x:%02x:%02x:%02x for mapped dstIP(%d.%d.%d.%d)\n",
+ __FUNCTION__, pEntry->macAddr[0],pEntry->macAddr[1],pEntry->macAddr[2],
+ pEntry->macAddr[3],pEntry->macAddr[4],pEntry->macAddr[5],
+ (ipAddr>>24) & 0xff, (ipAddr>>16) & 0xff, (ipAddr>>8) & 0xff, ipAddr & 0xff));
+*/
+
+ /*Update the lastTime to prevent the aging before pDA processed! */
+ NdisGetSystemUpTime(&pEntry->lastTime);
+
+ return pEntry->macAddr;
+ }
+ else
+ pEntry = pEntry->pNext;
+ }
+
+ /*
+ We didn't find any matched Mac address, our policy is treat it as
+ broadcast packet and send to all.
+ */
+ return pIPMacTable->hash[IPMAC_TB_HASH_INDEX_OF_BCAST]->macAddr;
+
+}
+
+
+static NDIS_STATUS IPMacTable_RemoveAll(
+ IN MAT_STRUCT *pMatCfg)
+{
+ IPMacMappingEntry *pEntry;
+ IPMacMappingTable *pIPMacTable;
+ INT i;
+
+
+ pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
+
+ if (!pIPMacTable)
+ return TRUE;
+
+ if (pIPMacTable->valid)
+ {
+ pIPMacTable->valid = FALSE;
+ for (i=0; i<IPMAC_TB_HASH_ENTRY_NUM; i++)
+ {
+ while((pEntry = pIPMacTable->hash[i]) != NULL)
+ {
+ pIPMacTable->hash[i] = pEntry->pNext;
+ MATDBEntryFree(pMatCfg, (PUCHAR)pEntry);
+ }
+ }
+ }
+
+/* kfree(pIPMacTable); */
+ os_free_mem(NULL, pIPMacTable);
+ pMatCfg->MatTableSet.IPMacTable = NULL;
+
+ return TRUE;
+
+}
+
+
+static NDIS_STATUS IPMacTable_init(
+ IN MAT_STRUCT *pMatCfg)
+{
+ IPMacMappingTable *pIPMacTable;
+ IPMacMappingEntry *pEntry = NULL;
+
+
+ if (pMatCfg->MatTableSet.IPMacTable != NULL)
+ {
+ pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
+ }
+ else
+ {
+/* pMatCfg->MatTableSet.IPMacTable = kmalloc(sizeof(IPMacMappingTable), GFP_KERNEL); */
+ os_alloc_mem_suspend(NULL, (UCHAR **)&(pMatCfg->MatTableSet.IPMacTable), sizeof(IPMacMappingTable));
+ if (pMatCfg->MatTableSet.IPMacTable)
+ {
+ pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
+ NdisZeroMemory(pIPMacTable, sizeof(IPMacMappingTable));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("IPMacTable_init(): Allocate memory for IPMacTable failed!\n"));
+ return FALSE;
+ }
+ }
+
+ if (pIPMacTable->valid == FALSE)
+ {
+ /*Set the last hash entry (hash[64]) as our default broadcast Mac address */
+ pEntry = (IPMacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(IPMacMappingEntry));
+ if (!pEntry)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("IPMacTable_init(): Allocate memory for IPMacTable broadcast entry failed!\n"));
+ return FALSE;
+ }
+
+ /*pEntry->ipAddr = 0; */
+ NdisZeroMemory(pEntry, sizeof(IPMacMappingEntry));
+ NdisMoveMemory(&pEntry->macAddr[0], &BROADCAST_ADDR[0], 6);
+ pEntry->pNext = NULL;
+ pIPMacTable->hash[IPMAC_TB_HASH_INDEX_OF_BCAST] = pEntry;
+
+ pIPMacTable->valid = TRUE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): IPMacTable already inited!\n", __FUNCTION__));
+ }
+
+ return TRUE;
+
+}
+
+
+static NDIS_STATUS MATProto_ARP_Exit(
+ IN MAT_STRUCT *pMatCfg)
+{
+ INT status;
+
+ status = IPMacTable_RemoveAll(pMatCfg);
+
+ return status;
+}
+
+static PUCHAR MATProto_ARP_Rx(
+ IN MAT_STRUCT *pMatCfg,
+ IN PNDIS_PACKET pSkb,
+ IN PUCHAR pLayerHdr,
+ IN PUCHAR pMacAddr)
+{
+ PUCHAR pArpHdr = NULL, pRealMac = NULL;
+ PUCHAR tgtMac, tgtIP;
+ BOOLEAN isUcastMac, isGoodIP;
+
+
+ pArpHdr = pLayerHdr;
+
+/*dumpPkt(RTPKT_TO_OSPKT(pSkb)->data, RTPKT_TO_OSPKT(pSkb)->len); */
+ /* We just take care about the target(Mac/IP address) fields. */
+ tgtMac = pArpHdr + 18;
+ tgtIP = tgtMac + 6;
+
+ /* isUcastMac = !(00:00:00:00:00:00|| mcastMac); */
+ isUcastMac = ((tgtMac[0]|tgtMac[1]|tgtMac[2]|tgtMac[3]|tgtMac[4]|tgtMac[5])!=0);
+ isUcastMac &= ((tgtMac[0] & 0x1)==0);
+
+ /* isGoodIP = ip address is not 0.0.0.0 */
+ isGoodIP = (*(UINT *)tgtIP != 0);
+
+
+ if (isUcastMac && isGoodIP)
+ pRealMac = IPMacTableLookUp(pMatCfg, *(UINT *)tgtIP);
+
+ /*
+ For need replaced mac, we need to replace the targetMAC as correct one to make
+ the real receiver can receive that.
+ */
+ if (isUcastMac && pRealMac)
+ NdisMoveMemory(tgtMac, pRealMac, MAC_ADDR_LEN);
+
+ if (pRealMac == NULL)
+ pRealMac = &BROADCAST_ADDR[0];
+/* pRealMac = pIPMacTable->hash[IPMAC_TB_HASH_INDEX_OF_BCAST]->macAddr; */
+
+ return pRealMac;
+}
+
+static PUCHAR MATProto_ARP_Tx(
+ IN MAT_STRUCT *pMatCfg,
+ IN PNDIS_PACKET pSkb,
+ IN PUCHAR pLayerHdr,
+ IN PUCHAR pMacAddr)
+{
+ PUCHAR pSMac, pSIP;
+ BOOLEAN isUcastMac, isGoodIP;
+ NET_PRO_ARP_HDR *arpHdr;
+ PUCHAR pPktHdr;
+ PNDIS_PACKET newSkb = NULL;
+
+ pPktHdr = GET_OS_PKT_DATAPTR(pSkb);
+
+ arpHdr = (NET_PRO_ARP_HDR *)pLayerHdr;
+
+ /*
+ Check the arp header.
+ We just handle ether type hardware address and IPv4 internet
+ address type and opcode is ARP reuqest/response.
+ */
+ if ((arpHdr->ar_hrd != OS_HTONS(ARPHRD_ETHER)) || (arpHdr->ar_pro != OS_HTONS(ETH_P_IP)) ||
+ (arpHdr->ar_op != OS_HTONS(ARPOP_REPLY) && arpHdr->ar_op != OS_HTONS(ARPOP_REQUEST)))
+ return NULL;
+
+ /* We just take care about the sender(Mac/IP address) fields. */
+ pSMac =(PUCHAR)(pLayerHdr + 8);
+ pSIP = (PUCHAR)(pSMac + MAC_ADDR_LEN);
+
+ isUcastMac = IS_UCAST_MAC(pSMac);
+ isGoodIP = IS_GOOD_IP(get_unaligned32((PUINT) pSIP));
+
+/*
+ DBGPRINT(RT_DEBUG_TRACE,("%s(): ARP Pkt=>senderIP=%d.%d.%d.%d, senderMac=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ __FUNCTION__, pSIP[0], pSIP[1], pSIP[2], pSIP[3],
+ pSMac[0],pSMac[1],pSMac[2],pSMac[3],pSMac[4],pSMac[5]));
+*/
+ if (isUcastMac && isGoodIP)
+ IPMacTableUpdate(pMatCfg, pSMac, get_unaligned32((PUINT) pSIP));
+
+ /*
+ For outgoing unicast mac, we need to replace the senderMAC as ourself to make
+ the receiver can send to us.
+ */
+ if (isUcastMac)
+ {
+ if(OS_PKT_CLONED(pSkb))
+ {
+ newSkb = (PNDIS_PACKET)OS_PKT_COPY(pSkb);
+ if(newSkb)
+ {
+ if (IS_VLAN_PACKET(GET_OS_PKT_DATAPTR(newSkb)))
+ pSMac = (PUCHAR)(GET_OS_PKT_DATAPTR(newSkb) + MAT_VLAN_ETH_HDR_LEN + 8);
+ else
+ pSMac = (PUCHAR)(GET_OS_PKT_DATAPTR(newSkb) + MAT_ETHER_HDR_LEN + 8);
+ }
+ }
+
+ ASSERT(pMacAddr);
+ NdisMoveMemory(pSMac, pMacAddr, MAC_ADDR_LEN);
+ }
+
+ return (PUCHAR)newSkb;
+}
+
+
+static NDIS_STATUS MATProto_ARP_Init(
+ IN MAT_STRUCT *pMatCfg)
+{
+ BOOLEAN status = FALSE;
+
+ status = IPMacTable_init(pMatCfg);
+
+ return status;
+}
+
+
+static NDIS_STATUS MATProto_IP_Exit(
+ IN MAT_STRUCT *pMatCfg)
+{
+ INT status;
+
+ status = IPMacTable_RemoveAll(pMatCfg);
+
+ return status;
+}
+
+
+static PUCHAR MATProto_IP_Rx(
+ IN MAT_STRUCT *pMatCfg,
+ IN PNDIS_PACKET pSkb,
+ IN PUCHAR pLayerHdr,
+ IN PUCHAR pDevMacAdr)
+{
+ PUCHAR pMacAddr;
+ UINT dstIP;
+
+ /* Fetch the IP addres from the packet header. */
+ getDstIPFromIpPkt(pLayerHdr, &dstIP);
+ pMacAddr = IPMacTableLookUp(pMatCfg, dstIP);
+
+ return pMacAddr;
+}
+
+static UCHAR DHCP_MAGIC[]= {0x63, 0x82, 0x53, 0x63};
+static PUCHAR MATProto_IP_Tx(
+ IN MAT_STRUCT *pMatCfg,
+ IN PNDIS_PACKET pSkb,
+ IN PUCHAR pLayerHdr,
+ IN PUCHAR pDevMacAdr)
+{
+ PUCHAR pSrcMac;
+ PUCHAR pSrcIP;
+ BOOLEAN needUpdate;
+ PUCHAR pPktHdr;
+
+ pPktHdr = GET_OS_PKT_DATAPTR(pSkb);
+
+ pSrcMac = pPktHdr + 6;
+ pSrcIP = pLayerHdr + 12;
+
+
+ needUpdate = NEED_UPDATE_IPMAC_TB(pSrcMac, get_unaligned32((PUINT)(pSrcIP)));
+ if (needUpdate)
+ IPMacTableUpdate(pMatCfg, pSrcMac, get_unaligned32((PUINT)(pSrcIP)));
+
+ /*For UDP packet, we need to check about the DHCP packet, to modify the flag of DHCP discovey/request as broadcast. */
+ if (*(pLayerHdr + 9) == 0x11)
+ {
+ PUCHAR udpHdr;
+ UINT16 srcPort, dstPort;
+
+ udpHdr = pLayerHdr + 20;
+ srcPort = OS_NTOHS(get_unaligned((PUINT16)(udpHdr)));
+ dstPort = OS_NTOHS(get_unaligned((PUINT16)(udpHdr+2)));
+
+ if (srcPort==68 && dstPort==67) /*It's a DHCP packet */
+ {
+ PUCHAR bootpHdr;
+ UINT16 bootpFlag;
+
+ bootpHdr = udpHdr + 8;
+ bootpFlag = OS_NTOHS(get_unaligned((PUINT16)(bootpHdr+10)));
+ DBGPRINT(RT_DEBUG_TRACE, ("is bootp packet! bootpFlag=0x%x\n", bootpFlag));
+ if (bootpFlag != 0x8000) /*check if it's a broadcast request. */
+ {
+ PUCHAR dhcpHdr;
+
+ dhcpHdr = bootpHdr + 236;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("the DHCP flag is a unicast, dhcp_magic=%02x:%02x:%02x:%02x\n",
+ dhcpHdr[0], dhcpHdr[1], dhcpHdr[2], dhcpHdr[3]));
+ if (NdisEqualMemory(dhcpHdr, DHCP_MAGIC, 4))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("dhcp magic macthed!\n"));
+ bootpFlag = OS_HTONS(0x8000);
+ NdisMoveMemory((bootpHdr+10), &bootpFlag, 2); /*Set the bootp flag as broadcast */
+ NdisZeroMemory((udpHdr+6), 2); /*modify the UDP chksum as zero */
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+static NDIS_STATUS MATProto_IP_Init(
+ IN MAT_STRUCT *pMatCfg)
+{
+ BOOLEAN status;
+
+ status = IPMacTable_init(pMatCfg);
+
+ return status;
+}
+
+
+static inline void IPintToIPstr(int ipint, char Ipstr[20], ULONG BufLen)
+{
+ int temp = 0;
+
+ temp = ipint & 0x000FF;
+ snprintf(Ipstr, BufLen, "%d.", temp);
+ temp = (ipint>>8) & 0x000FF;
+ snprintf(Ipstr, BufLen, "%s%d.", Ipstr, temp);
+ temp = (ipint>>16) & 0x000FF;
+ snprintf(Ipstr, BufLen, "%s%d.", Ipstr, temp);
+ temp = (ipint>>24) & 0x000FF;
+ snprintf(Ipstr, BufLen, "%s%d", Ipstr, temp);
+}
+
+
+VOID getIPMacTbInfo(
+ IN MAT_STRUCT *pMatCfg,
+ IN char *pOutBuf,
+ IN ULONG BufLen)
+{
+ IPMacMappingTable *pIPMacTable;
+ IPMacMappingEntry *pHead;
+ int startIdx, endIdx;
+ char Ipstr[20] = {0};
+
+
+ pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
+ if ((!pIPMacTable) || (!pIPMacTable->valid))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():IPMacTable not init yet!\n", __FUNCTION__));
+ return;
+ }
+
+ /* dump all. */
+ startIdx = 0;
+ endIdx = MAT_MAX_HASH_ENTRY_SUPPORT;
+
+ sprintf(pOutBuf, "\n");
+ sprintf(pOutBuf+strlen(pOutBuf), "%-18s%-20s\n", "IP", "MAC");
+ for(; startIdx< endIdx; startIdx++)
+ {
+ pHead = pIPMacTable->hash[startIdx];
+ while(pHead)
+ {
+/* if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30)) */
+ if (RtmpOsCmdDisplayLenCheck(strlen(pOutBuf), 30) == FALSE)
+ break;
+ NdisZeroMemory(Ipstr, 20);
+ IPintToIPstr(pHead->ipAddr, Ipstr, sizeof(Ipstr));
+ sprintf(pOutBuf+strlen(pOutBuf), "%-18s%02x:%02x:%02x:%02x:%02x:%02x\n",
+ Ipstr, pHead->macAddr[0],pHead->macAddr[1],pHead->macAddr[2],
+ pHead->macAddr[3],pHead->macAddr[4],pHead->macAddr[5]);
+ pHead = pHead->pNext;
+ }
+ }
+}
+
+#endif /* MAT_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_mat_ipv6.c b/cleopatre/devkit/mt7601udrv/common/cmm_mat_ipv6.c
new file mode 100644
index 0000000000..814d001f26
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_mat_ipv6.c
@@ -0,0 +1,824 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ cmm_mat_ipv6.c
+
+ Abstract:
+ MAT convert engine subroutine for ipv6 base protocols, currently now we
+ just handle IPv6/ICMPv6 packets without Authentication/Encryption headers.
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Shiang 06/03/07 Init version
+*/
+#ifdef MAT_SUPPORT
+
+#include "rt_config.h"
+#include "ipv6.h"
+
+/*#include <asm/checksum.h> */
+/*#include <net/ip6_checksum.h> */
+
+const UCHAR IPV6_LOOPBACKADDR[] ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
+
+static NDIS_STATUS MATProto_IPv6_Init(MAT_STRUCT *pMatCfg);
+static NDIS_STATUS MATProto_IPv6_Exit(MAT_STRUCT *pMatCfg);
+static PUCHAR MATProto_IPv6_Rx(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pDevMacAdr);
+static PUCHAR MATProto_IPv6_Tx(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pDevMacAdr);
+
+#define RT_UDP_HDR_LEN 8
+
+typedef struct _IPv6MacMappingEntry
+{
+ UCHAR ipv6Addr[16]; /* In network order */
+ UCHAR macAddr[MAC_ADDR_LEN];
+ ULONG lastTime;
+ struct _IPv6MacMappingEntry *pNext;
+}IPv6MacMappingEntry, *PIPv6MacMappingEntry;
+
+
+typedef struct _IPv6MacMappingTable
+{
+ BOOLEAN valid;
+ IPv6MacMappingEntry *hash[MAT_MAX_HASH_ENTRY_SUPPORT+1]; /*0~63 for specific station, 64 for broadcast MacAddress */
+ UCHAR curMcastAddr[MAC_ADDR_LEN]; /* The multicast mac addr for currecnt received packet destined to ipv6 multicast addr */
+}IPv6MacMappingTable;
+
+
+struct _MATProtoOps MATProtoIPv6Handle =
+{
+ .init = MATProto_IPv6_Init,
+ .tx = MATProto_IPv6_Tx,
+ .rx = MATProto_IPv6_Rx,
+ .exit = MATProto_IPv6_Exit,
+};
+
+static inline BOOLEAN needUpdateIPv6MacTB(
+ UCHAR *pMac,
+ RT_IPV6_ADDR *pIPv6Addr)
+{
+ ASSERT(pIPv6Addr);
+
+ if (isMcastEtherAddr(pMac) || isZeroEtherAddr(pMac))
+ return FALSE;
+
+ /* IPv6 multicast address */
+ if (IS_MULTICAST_IPV6_ADDR(*pIPv6Addr))
+ return FALSE;
+
+ /* unspecified address */
+ if(IS_UNSPECIFIED_IPV6_ADDR(*pIPv6Addr))
+ return FALSE;
+
+ /* loopback address */
+ if (IS_LOOPBACK_IPV6_ADDR(*pIPv6Addr))
+ return FALSE;
+
+/*
+ DBGPRINT(RT_DEBUG_INFO, ("%s(): Good IPv6 unicast addr=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ __FUNCTION__, PRINT_IPV6_ADDR(*pIPv6Addr)));
+*/
+ return TRUE;
+}
+
+
+/*
+ IPv6 Header Format
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Version| Traffic Class | Flow Label |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Payload Length | Next Header | Hop Limit |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | Source Address |
+ + +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | Destination Address |
+ + +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ICMPv6 Format:
+ |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Message Body |
+ + +
+ | |
+ ......
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+NDIS_STATUS dumpIPv6MacTb(
+ IN MAT_STRUCT *pMatCfg,
+ IN int index)
+{
+ IPv6MacMappingTable *pIPv6MacTable;
+ IPv6MacMappingEntry *pHead;
+ int startIdx, endIdx;
+
+
+ pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
+ if ((!pIPv6MacTable) || (!pIPv6MacTable->valid))
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("%s():IPv6MacTable not init yet, so cannot do dump!\n", __FUNCTION__));
+ return FALSE;
+ }
+
+
+ if(index < 0)
+ { /* dump all. */
+ startIdx = 0;
+ endIdx = MAT_MAX_HASH_ENTRY_SUPPORT;
+ }
+ else
+ { /* dump specific hash index. */
+ startIdx = endIdx = index;
+ }
+
+ DBGPRINT(RT_DEBUG_OFF, ("%s():\n", __FUNCTION__));
+ for(; startIdx<= endIdx; startIdx++)
+ {
+ pHead = pIPv6MacTable->hash[startIdx];
+ while(pHead)
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("IPv6Mac[%d]:\n", startIdx));
+ DBGPRINT(RT_DEBUG_OFF, ("\t:IPv6=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x,Mac=%02x:%02x:%02x:%02x:%02x:%02x, lastTime=0x%lx, next=%p\n",
+ PRINT_IPV6_ADDR(*((RT_IPV6_ADDR *)(&pHead->ipv6Addr[0]))), pHead->macAddr[0],pHead->macAddr[1],pHead->macAddr[2],
+ pHead->macAddr[3],pHead->macAddr[4],pHead->macAddr[5], pHead->lastTime, pHead->pNext));
+ pHead = pHead->pNext;
+ }
+ }
+ DBGPRINT(RT_DEBUG_OFF, ("\t----EndOfDump!\n"));
+
+ return TRUE;
+}
+
+
+
+static NDIS_STATUS IPv6MacTableUpdate(
+ IN MAT_STRUCT *pMatCfg,
+ IN PUCHAR pMacAddr,
+ IN PCHAR pIPv6Addr)
+{
+ UINT hashIdx;
+ IPv6MacMappingTable *pIPv6MacTable;
+ IPv6MacMappingEntry *pEntry = NULL, *pPrev = NULL, *pNewEntry =NULL;
+ ULONG now;
+
+
+ pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
+ if ((!pIPv6MacTable) || (!pIPv6MacTable->valid))
+ return FALSE;
+
+ hashIdx = MAT_IPV6_ADDR_HASH_INDEX(pIPv6Addr);
+ pEntry = pPrev = pIPv6MacTable->hash[hashIdx];
+ while(pEntry)
+ {
+ NdisGetSystemUpTime(&now);
+
+ /* Find a existed IP-MAC Mapping entry */
+ if (NdisEqualMemory(pIPv6Addr, pEntry->ipv6Addr, IPV6_ADDR_LEN))
+ {
+
+ /* comparison is useless. So we directly copy it into the entry. */
+ NdisMoveMemory(pEntry->macAddr, pMacAddr, 6);
+ NdisGetSystemUpTime(&pEntry->lastTime);
+
+ return TRUE;
+ }
+ else
+ { /* handle the aging-out situation */
+ if (RTMP_TIME_AFTER(now, (pEntry->lastTime + MAT_TB_ENTRY_AGEOUT_TIME)))
+ {
+ /* Remove the aged entry */
+ if (pEntry == pIPv6MacTable->hash[hashIdx])
+ {
+ pIPv6MacTable->hash[hashIdx]= pEntry->pNext;
+ pPrev = pIPv6MacTable->hash[hashIdx];
+ }
+ else
+ {
+ pPrev->pNext = pEntry->pNext;
+ }
+ MATDBEntryFree(pMatCfg, (PUCHAR)pEntry);
+
+ pEntry = (pPrev == NULL ? NULL: pPrev->pNext);
+ pMatCfg->nodeCount--;
+ }
+ else
+ {
+ pPrev = pEntry;
+ pEntry = pEntry->pNext;
+ }
+ }
+ }
+
+
+ /* Allocate a new IPv6MacMapping entry and insert into the hash */
+ pNewEntry = (IPv6MacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(IPv6MacMappingEntry));
+ if (pNewEntry != NULL)
+ {
+ NdisMoveMemory(pNewEntry->ipv6Addr, pIPv6Addr, IPV6_ADDR_LEN);
+ NdisMoveMemory(pNewEntry->macAddr, pMacAddr, 6);
+ pNewEntry->pNext = NULL;
+ NdisGetSystemUpTime(&pNewEntry->lastTime);
+
+ if (pIPv6MacTable->hash[hashIdx] == NULL)
+ { /* Hash list is empty, directly assign it. */
+ pIPv6MacTable->hash[hashIdx] = pNewEntry;
+ }
+ else
+ {
+ /* Ok, we insert the new entry into the root of hash[hashIdx] */
+ pNewEntry->pNext = pIPv6MacTable->hash[hashIdx];
+ pIPv6MacTable->hash[hashIdx] = pNewEntry;
+ }
+ /*dumpIPv6MacTb(pMatCfg, hashIdx); //for debug */
+
+ pMatCfg->nodeCount++;
+
+ return TRUE;
+ }
+
+ DBGPRINT(RT_DEBUG_ERROR, ("IPv6MacTableUpdate():Insertion failed!\n"));
+
+ return FALSE;
+}
+
+
+static PUCHAR IPv6MacTableLookUp(
+ IN MAT_STRUCT *pMatCfg,
+ IN PUCHAR pIPv6Addr)
+{
+ UINT hashIdx;
+ IPv6MacMappingTable *pIPv6MacTable;
+ IPv6MacMappingEntry *pEntry = NULL;
+ PUCHAR pGroupMacAddr;
+
+
+ pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
+ if ((!pIPv6MacTable) ||(!pIPv6MacTable->valid))
+ return NULL;
+
+ /*if IPV6 multicast address, need converting multicast group address to ethernet address. */
+ if (IS_MULTICAST_IPV6_ADDR(*(RT_IPV6_ADDR *)pIPv6Addr))
+ {
+ pGroupMacAddr = (PUCHAR)&pIPv6MacTable->curMcastAddr;
+ ConvertMulticastIP2MAC(pIPv6Addr, (UCHAR **)(&pGroupMacAddr), ETH_P_IPV6);
+ return pIPv6MacTable->curMcastAddr;
+ }
+
+ /* Use hash to find out the location of that entry and get the Mac address. */
+ hashIdx = MAT_IPV6_ADDR_HASH_INDEX(pIPv6Addr);
+
+/* spin_lock_irqsave(&IPMacTabLock, irqFlag); */
+ pEntry = pIPv6MacTable->hash[hashIdx];
+ while(pEntry)
+ {
+ if (NdisEqualMemory(pEntry->ipv6Addr, pIPv6Addr, IPV6_ADDR_LEN))
+ {
+
+ /*Update the lastTime to prevent the aging before pDA processed! */
+ NdisGetSystemUpTime(&pEntry->lastTime);
+
+ return pEntry->macAddr;
+ }
+ else
+ {
+ pEntry = pEntry->pNext;
+ }
+ }
+
+ /*
+ We didn't find any matched Mac address, our policy is treat it as
+ broadcast packet and send to all.
+ */
+ return pIPv6MacTable->hash[IPV6MAC_TB_HASH_INDEX_OF_BCAST]->macAddr;
+
+}
+
+
+static inline unsigned short int icmpv6_csum(
+ RT_IPV6_ADDR *saddr,
+ RT_IPV6_ADDR *daddr,
+ USHORT len,
+ UCHAR proto,
+ UCHAR *pICMPMsg)
+{
+ int carry;
+ UINT32 ulen;
+ UINT32 uproto;
+ int i;
+ unsigned int csum = 0;
+ unsigned short int chksum;
+
+ if (len % 4)
+ return 0;
+
+ for( i = 0; i < 4; i++)
+ {
+ csum += saddr->ipv6_addr32[i];
+ carry = (csum < saddr->ipv6_addr32[i]);
+ csum += carry;
+ }
+
+ for( i = 0; i < 4; i++)
+ {
+ csum += daddr->ipv6_addr32[i];
+ carry = (csum < daddr->ipv6_addr32[i]);
+ csum += carry;
+ }
+
+ ulen = OS_HTONL((UINT32)len);
+ csum += ulen;
+ carry = (csum < ulen);
+ csum += carry;
+
+ uproto = OS_HTONL((UINT32)proto);
+ csum += uproto;
+ carry = (csum < uproto);
+ csum += carry;
+
+ for (i = 0; i < len; i += 4)
+ {
+ csum += get_unaligned32(((UINT32 *)&pICMPMsg[i]));
+ carry = (csum < get_unaligned32(((UINT32 *)&pICMPMsg[i])));
+ csum += carry;
+ }
+
+ while (csum>>16)
+ csum = (csum & 0xffff) + (csum >> 16);
+
+ chksum = ~csum;
+
+ return chksum;
+}
+
+
+
+static PUCHAR MATProto_IPv6_Rx(
+ IN MAT_STRUCT *pMatCfg,
+ IN PNDIS_PACKET pSkb,
+ IN PUCHAR pLayerHdr,
+ IN PUCHAR pDevMacAdr)
+{
+
+ PUCHAR pMacAddr;
+ PUCHAR pDstIPv6Addr;
+
+ /* Fetch the IPv6 addres from the packet header. */
+ pDstIPv6Addr = (UCHAR *)(&((RT_IPV6_HDR *)pLayerHdr)->dstAddr);
+
+ pMacAddr = IPv6MacTableLookUp(pMatCfg, pDstIPv6Addr);
+
+ return pMacAddr;
+
+}
+
+static PNDIS_PACKET ICMPv6_Handle_Tx(
+ IN MAT_STRUCT *pMatSrtuct,
+ IN PNDIS_PACKET pSkb,
+ IN PUCHAR pLayerHdr,
+ IN PUCHAR pDevMacAdr,
+ IN UINT32 offset)
+{
+ RT_IPV6_HDR *pIPv6Hdr;
+ RT_ICMPV6_HDR *pICMPv6Hdr;
+ RT_ICMPV6_OPTION_HDR *pOptHdr;
+
+ USHORT payloadLen;
+ UINT32 ICMPOffset = 0, ICMPMsgLen = 0, leftLen;
+
+ PNDIS_PACKET newSkb = NULL;
+ BOOLEAN needModify = FALSE;
+ PUCHAR pSrcMac;
+
+ pIPv6Hdr = (RT_IPV6_HDR *)pLayerHdr;
+ payloadLen = OS_NTOHS(pIPv6Hdr->payload_len);
+
+ pICMPv6Hdr = (RT_ICMPV6_HDR *)(pLayerHdr + offset);
+ ICMPOffset = offset;
+ ICMPMsgLen = payloadLen + IPV6_HDR_LEN - ICMPOffset;
+
+
+
+ leftLen = ICMPMsgLen;
+ switch (pICMPv6Hdr->type)
+ {
+ case ICMPV6_MSG_TYPE_ROUTER_SOLICITATION:
+ offset += ROUTER_SOLICITATION_FIXED_LEN;
+ /* for unspecified source address, it should not include the option about link-layer address. */
+ if (!(IS_UNSPECIFIED_IPV6_ADDR(pIPv6Hdr->srcAddr)))
+ {
+ while(leftLen > sizeof(RT_ICMPV6_OPTION_HDR))
+ {
+ pOptHdr = (RT_ICMPV6_OPTION_HDR *)(pLayerHdr + offset);
+ if (pOptHdr->len == 0)
+ break; /* discard it, because it's invalid. */
+
+ if (pOptHdr->type == TYPE_SRC_LL_ADDR)
+ {
+ /*replace the src link-layer address as ours. */
+ needModify = TRUE;
+ offset += 2; /* 2 = "type, len" fields. Here indicate to the place of src mac. */
+
+ break;
+ } else {
+ offset += (pOptHdr->len * 8); /* in unit of 8 octets. */
+ leftLen -= (pOptHdr->len * 8);
+ }
+ }
+ }
+ break;
+
+ case ICMPV6_MSG_TYPE_ROUTER_ADVERTISEMENT:
+ offset += ROUTER_ADVERTISEMENT_FIXED_LEN;
+ /* for unspecified source address, it should not include the option about link-layer address. */
+ if (!(IS_UNSPECIFIED_IPV6_ADDR(pIPv6Hdr->srcAddr)))
+ {
+ while(leftLen > sizeof(RT_ICMPV6_OPTION_HDR))
+ {
+ pOptHdr = (RT_ICMPV6_OPTION_HDR *)(pLayerHdr + offset);
+ if (pOptHdr->len == 0)
+ break; /* discard it, because it's invalid. */
+
+ if (pOptHdr->type == TYPE_SRC_LL_ADDR)
+ {
+ /*replace the src link-layer address as ours. */
+ needModify = TRUE;
+ offset += 2; /* 2 = "type, len" fields. Here indicate to the place of src mac. */
+
+ break;
+ } else {
+ offset += (pOptHdr->len * 8); /* in unit of 8 octets. */
+ leftLen -= (pOptHdr->len * 8);
+ }
+ }
+ }
+ break;
+
+ case ICMPV6_MSG_TYPE_NEIGHBOR_SOLICITATION:
+ offset += NEIGHBOR_SOLICITATION_FIXED_LEN;
+ /* for unspecified source address, it should not include the option about link-layer address. */
+ if (!(IS_UNSPECIFIED_IPV6_ADDR(pIPv6Hdr->srcAddr)))
+ {
+ while(leftLen > sizeof(RT_ICMPV6_OPTION_HDR))
+ {
+ pOptHdr = (RT_ICMPV6_OPTION_HDR *)(pLayerHdr + offset);
+ if (pOptHdr->len == 0)
+ break; /* discard it, because it's invalid. */
+
+ if (pOptHdr->type == TYPE_SRC_LL_ADDR)
+ {
+ /*replace the src link-layer address as ours. */
+ needModify = TRUE;
+ offset += 2; /* 2 = "type, len" fields. Here indicate to the place of src mac. */
+
+ break;
+ } else {
+ offset += (pOptHdr->len * 8); /* in unit of 8 octets. */
+ leftLen -= (pOptHdr->len * 8);
+ }
+ }
+ }
+ break;
+
+ case ICMPV6_MSG_TYPE_NEIGHBOR_ADVERTISEMENT:
+ offset += NEIGHBOR_ADVERTISEMENT_FIXED_LEN;
+ /* for unspecified source address, it should not include the option about link-layer address. */
+ if (!(IS_UNSPECIFIED_IPV6_ADDR(pIPv6Hdr->srcAddr)))
+ {
+ while(leftLen > sizeof(RT_ICMPV6_OPTION_HDR))
+ {
+ pOptHdr = (RT_ICMPV6_OPTION_HDR *)(pLayerHdr + offset);
+ if (pOptHdr->len == 0)
+ break; /* discard it, because it's invalid. */
+
+ if (pOptHdr->type == TYPE_TGT_LL_ADDR)
+ {
+ /*replace the src link-layer address as ours. */
+ needModify = TRUE;
+ offset += 2; /* 2 = "type, len" fields. */
+
+ break;
+ }else {
+ offset += (pOptHdr->len * 8); /* in unit of 8 octets. */
+ leftLen -= (pOptHdr->len * 8);
+ }
+ }
+ }
+ break;
+ case ICMPV6_MSG_TYPE_REDIRECT:
+ offset += REDIRECT_FIXED_LEN;
+ /* for unspecified source address, it should not include the options about link-layer address. */
+ if (!(IS_UNSPECIFIED_IPV6_ADDR(pIPv6Hdr->srcAddr)))
+ {
+ while(leftLen > sizeof(RT_ICMPV6_OPTION_HDR))
+ {
+ pOptHdr = (RT_ICMPV6_OPTION_HDR *)(pLayerHdr + offset);
+ if (pOptHdr->len == 0)
+ break; /* discard it, because it's invalid. */
+
+ if (pOptHdr->type == TYPE_TGT_LL_ADDR)
+ {
+ /* TODO: Need to check if the TGT_LL_ADDR is the inner MAC. */
+ /*replace the src link-layer address as ours. */
+ needModify = TRUE;
+ offset += 2; /* 2 = "type, len" fields. */
+
+ break;
+ }else {
+ offset += (pOptHdr->len * 8); /* in unit of 8 octets. */
+ leftLen -= (pOptHdr->len * 8);
+ }
+ }
+ }
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("Un-supported ICMPv6 msg type(0x%x)! Ignore it\n", pICMPv6Hdr->type));
+ break;
+ }
+
+ /* We need to handle about the solicitation/Advertisement packets. */
+ if (needModify)
+ {
+ if(OS_PKT_CLONED(pSkb))
+ {
+ newSkb = (PNDIS_PACKET)OS_PKT_COPY(RTPKT_TO_OSPKT(pSkb));
+ if(newSkb) {
+ if (IS_VLAN_PACKET(GET_OS_PKT_DATAPTR(newSkb)))
+ pIPv6Hdr = (RT_IPV6_HDR *)(GET_OS_PKT_DATAPTR(newSkb) + MAT_VLAN_ETH_HDR_LEN);
+ else
+ pIPv6Hdr = (RT_IPV6_HDR *)(GET_OS_PKT_DATAPTR(newSkb) + MAT_ETHER_HDR_LEN);
+ }
+ }
+
+ pICMPv6Hdr = (RT_ICMPV6_HDR *)((PUCHAR)pIPv6Hdr + ICMPOffset);
+ pSrcMac = (PUCHAR)((PUCHAR)pIPv6Hdr + offset);
+ NdisMoveMemory(pSrcMac, pDevMacAdr, MAC_ADDR_LEN);
+
+ /* Now re-calculate the Checksum. */
+ pICMPv6Hdr->chksum = 0;
+ pICMPv6Hdr->chksum = icmpv6_csum(&pIPv6Hdr->srcAddr, &pIPv6Hdr->dstAddr, ICMPMsgLen ,
+ IPV6_NEXT_HEADER_ICMPV6, (PUCHAR)pICMPv6Hdr);
+ }
+
+ return newSkb;
+
+}
+
+
+static PUCHAR MATProto_IPv6_Tx(
+ IN MAT_STRUCT *pMatCfg,
+ IN PNDIS_PACKET pSkb,
+ IN PUCHAR pLayerHdr,
+ IN PUCHAR pDevMacAdr)
+{
+ PUCHAR pSrcMac, pSrcIP;
+ BOOLEAN needUpdate;
+ UCHAR nextProtocol;
+ UINT32 offset;
+ HEADER_802_3 *pEthHdr;
+ RT_IPV6_HDR *pIPv6Hdr;
+ PNDIS_PACKET newSkb = NULL;
+
+ pIPv6Hdr = (RT_IPV6_HDR *)pLayerHdr;
+ pEthHdr = (HEADER_802_3 *)(GET_OS_PKT_DATAPTR(pSkb));
+
+ pSrcMac = (UCHAR *)&pEthHdr->SAAddr2;
+ pSrcIP = (UCHAR *)&pIPv6Hdr->srcAddr;
+
+
+
+ needUpdate = needUpdateIPv6MacTB(pSrcMac, (RT_IPV6_ADDR *)(&pIPv6Hdr->srcAddr));
+ if (needUpdate)
+ IPv6MacTableUpdate(pMatCfg, pSrcMac, (CHAR *)(&pIPv6Hdr->srcAddr));
+
+
+ /* We need to traverse the whole IPv6 Header and extend headers to check about the ICMPv6 pacekt. */
+
+ nextProtocol = pIPv6Hdr->nextHdr;
+ offset = IPV6_HDR_LEN;
+ /*DBGPRINT(RT_DEBUG_INFO, ("NextProtocol=0x%x! payloadLen=%d! offset=%d!\n", nextProtocol, payloadLen, offset)); */
+ while(nextProtocol != IPV6_NEXT_HEADER_ICMPV6 &&
+ nextProtocol != IPV6_NEXT_HEADER_UDP &&
+ nextProtocol != IPV6_NEXT_HEADER_TCP &&
+ nextProtocol != IPV6_NEXT_HEADER_NONE)
+ {
+ if(IPv6ExtHdrHandle((RT_IPV6_EXT_HDR *)(pLayerHdr + offset), &nextProtocol, &offset) == FALSE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("IPv6ExtHdrHandle failed!\n"));
+ break;
+ }
+ }
+
+ switch (nextProtocol)
+ {
+ case IPV6_NEXT_HEADER_ICMPV6:
+ newSkb = ICMPv6_Handle_Tx(pMatCfg, pSkb, pLayerHdr, pDevMacAdr, offset);
+ break;
+
+ case IPV6_NEXT_HEADER_UDP:
+ /*newSkb = DHCPv6_Handle_Tx(pMatStrcut, pSkb, pLayerHdr, pMacAddr, offset); */
+ break;
+
+ case IPV6_NEXT_HEADER_TCP:
+ case IPV6_NEXT_HEADER_NONE:
+ default:
+ break;
+ }
+
+ return (PUCHAR)newSkb;
+
+}
+
+
+
+static NDIS_STATUS IPv6MacTable_RemoveAll(
+ IN MAT_STRUCT *pMatCfg)
+{
+ IPv6MacMappingTable *pIPv6MacTable;
+ IPv6MacMappingEntry *pEntry;
+ UINT32 i;
+
+
+ pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
+ if (!pIPv6MacTable)
+ return TRUE;
+
+ if (pIPv6MacTable->valid)
+ {
+ pIPv6MacTable->valid = FALSE;
+ for (i=0; i<IPV6MAC_TB_HASH_ENTRY_NUM; i++)
+ {
+ while((pEntry = pIPv6MacTable->hash[i]) != NULL)
+ {
+ pIPv6MacTable->hash[i] = pEntry->pNext;
+ MATDBEntryFree(pMatCfg, (PUCHAR)pEntry);
+ }
+ }
+ }
+
+/* kfree(pIPv6MacTable); */
+ os_free_mem(NULL, pIPv6MacTable);
+ pMatCfg->MatTableSet.IPv6MacTable = NULL;
+
+ return TRUE;
+
+}
+
+
+static NDIS_STATUS IPv6MacTable_init(
+ IN MAT_STRUCT *pMatCfg)
+{
+ IPv6MacMappingEntry *pEntry = NULL;
+ IPv6MacMappingTable *pIPv6MacTable;
+
+
+ if (pMatCfg->MatTableSet.IPv6MacTable != NULL)
+ {
+ pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
+ }
+ else
+ {
+/* pMatCfg->MatTableSet.IPv6MacTable = kmalloc(sizeof(IPv6MacMappingTable), GFP_KERNEL); */
+ os_alloc_mem_suspend(NULL, (UCHAR **)&(pMatCfg->MatTableSet.IPv6MacTable), sizeof(IPv6MacMappingTable));
+ if (pMatCfg->MatTableSet.IPv6MacTable)
+ {
+ pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
+ NdisZeroMemory(pIPv6MacTable, sizeof(IPv6MacMappingTable));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("IPMacTable_init(): Allocate memory for IPv6MacTable failed!\n"));
+ return FALSE;
+ }
+ }
+
+ if (pIPv6MacTable->valid == FALSE)
+ {
+ /*Set the last hash entry (hash[64]) as our default broadcast Mac address */
+ pEntry = (IPv6MacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(IPv6MacMappingEntry));
+ if (!pEntry)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("IPMacTable_init(): Allocate memory for IPMacTable broadcast entry failed!\n"));
+ return FALSE;
+ }
+ NdisZeroMemory(pEntry, sizeof(IPv6MacMappingEntry));
+ NdisMoveMemory(pEntry->macAddr, BROADCAST_ADDR, MAC_ADDR_LEN);
+ pEntry->pNext = NULL;
+ pIPv6MacTable->hash[IPV6MAC_TB_HASH_INDEX_OF_BCAST] = pEntry;
+
+ pIPv6MacTable->valid = TRUE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): IPv6MacTable already inited!\n", __FUNCTION__));
+ }
+
+ return TRUE;
+
+}
+
+
+static NDIS_STATUS MATProto_IPv6_Exit(
+ IN MAT_STRUCT *pMatCfg)
+{
+ INT status;
+
+ status = IPv6MacTable_RemoveAll(pMatCfg);
+
+ return status;
+}
+
+
+static NDIS_STATUS MATProto_IPv6_Init(
+ IN MAT_STRUCT *pMatCfg)
+{
+
+ BOOLEAN status = FALSE;
+
+ status = IPv6MacTable_init(pMatCfg);
+
+ return status;
+}
+
+
+
+VOID getIPv6MacTbInfo(
+ IN MAT_STRUCT *pMatCfg,
+ IN char *pOutBuf,
+ IN ULONG BufLen)
+{
+ IPv6MacMappingTable *pIPv6MacTable;
+ IPv6MacMappingEntry *pHead;
+ int startIdx, endIdx;
+ char Ipv6str[40] = {0};
+
+
+ pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
+ if ((!pIPv6MacTable) || (!pIPv6MacTable->valid))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():IPv6MacTable not init yet!\n", __FUNCTION__));
+ return;
+ }
+
+
+ /* dump all. */
+ startIdx = 0;
+ endIdx = MAT_MAX_HASH_ENTRY_SUPPORT;
+
+ sprintf(pOutBuf, "\n");
+ sprintf(pOutBuf+strlen(pOutBuf), "%-40s%-20s\n", "IP", "MAC");
+ for(; startIdx< endIdx; startIdx++)
+ {
+ pHead = pIPv6MacTable->hash[startIdx];
+
+ while(pHead)
+ {
+/* if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30)) */
+ if (RtmpOsCmdDisplayLenCheck(strlen(pOutBuf), 30) == FALSE)
+ break;
+ NdisZeroMemory(Ipv6str, 40);
+ sprintf(Ipv6str, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", PRINT_IPV6_ADDR(*((RT_IPV6_ADDR *)(&pHead->ipv6Addr[0]))));
+ sprintf(pOutBuf+strlen(pOutBuf), "%-40s%02x:%02x:%02x:%02x:%02x:%02x\n",
+ Ipv6str, pHead->macAddr[0],pHead->macAddr[1],pHead->macAddr[2],
+ pHead->macAddr[3],pHead->macAddr[4],pHead->macAddr[5]);
+ pHead = pHead->pNext;
+ }
+ }
+}
+
+#endif /* MAT_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_mat_pppoe.c b/cleopatre/devkit/mt7601udrv/common/cmm_mat_pppoe.c
new file mode 100644
index 0000000000..8988a7dcb6
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_mat_pppoe.c
@@ -0,0 +1,1062 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ cmm_mat_pppoe.c
+
+ Abstract:
+ MAT convert engine subroutine for PPPoE protocol.Due to the difference
+ of characteristic of PPPoE discovery stage and session stage, we seperate
+ that as two parts and used different stretegy to handle it.
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Shiang 02/26/07 Init version
+*/
+
+#ifdef MAT_SUPPORT
+
+#include "rt_config.h"
+
+static NDIS_STATUS MATProto_PPPoEDis_Init(MAT_STRUCT *pMatStruct);
+static NDIS_STATUS MATProto_PPPoEDis_Exit(MAT_STRUCT *pMatStruct);
+static PUCHAR MATProto_PPPoEDis_Rx(MAT_STRUCT *pMatStruct, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pDevMacAdr);
+static PUCHAR MATProto_PPPoEDis_Tx(MAT_STRUCT *pMatStruct, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pDevMacAdr);
+
+static NDIS_STATUS MATProto_PPPoESes_Init(MAT_STRUCT *pMatStruct);
+static NDIS_STATUS MATProto_PPPoESes_Exit(MAT_STRUCT *pMatStruct);
+static PUCHAR MATProto_PPPoESes_Rx(MAT_STRUCT *pMatStruct, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pDevMacAdr);
+static PUCHAR MATProto_PPPoESes_Tx(MAT_STRUCT *pMatStruct, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pDevMacAdr);
+
+
+/*
+ 1 2 3 4
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | VER | TYPE | CODE | SESSION_ID |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | LENGTH | payload ~
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ VER = 0x1, TYPE =0x1
+
+PPPoE Discovery Stage(Ethernet protocol type = 0x8863):
+ PADI:
+ DESTINATION_ADDR = 0xffffffff
+ CODE = 0x09, SESSION_ID = 0x0000
+ LENGTH = payload length
+
+ PADO:
+ DESTINATION_ADDR = Unicast Ethernet address of sender
+ CODE = 0x07, SESSION_ID = 0x0000
+ LENGTH = payload length
+ NEcessary TAGS: AC-NAME(0x0102), Sevice-Name(0x0101), and other service names.
+
+ Note: if the PPPoE server cannot serve the PADI it MUST NOT respond with a PADO
+
+
+ PADR:
+ DESTINATION_ADDR = unicast Ethernet address
+ CODE = 0x19, SESSION_ID = 0x0000
+ LENGTH = payload length
+ Necessary TAGS: Service-Name(0x0101)
+ Optional TAGS: ....
+
+ PADS:
+ If success:
+ DESTINATION_ADDR = unicast Ethernet address
+ CODE = 0x65, SESSION_ID = unique value for this pppoe session.(16 bits)
+ LENGHT - payload length
+ Necessary TAGS: Service-Name(0x0101)
+
+ if failed:
+ SESSION_ID = 0x0000
+ Necessary TAGS: Service-Name-Error(0x0201).
+
+ PADT:
+ DESTINATION_ADDR = unicast Ethernet address
+ CODE = 0xa7, SESSION_ID = previous assigned 16 bits session ID.
+ Necessary TAGS: NO.
+
+PPPoE Session Stage(Ethernet protocol type = 0x8864):
+ PPP data:
+ DESTINATION_ADDR = unicast Ethernet address
+ CODE = 0x00,
+ LCP:
+ DESTINATION_ADDR = unicast Ethernet address
+ CODE = 0x00,
+
+*/
+
+#define PPPOE_CODE_PADI 0x09
+#define PPPOE_CODE_PADO 0x07
+#define PPPOE_CODE_PADR 0x19
+#define PPPOE_CODE_PADS 0x65
+#define PPPOE_CODE_PADT 0xa7
+#define PPPOE_TAG_ID_HOST_UNIQ 0x0103
+#define PPPOE_TAG_ID_AC_COOKIE 0x0104
+
+#define PPPoE_SES_ENTRY_AGEOUT_TIME 3000
+
+/* Data structure used for PPPoE discovery stage */
+#define PPPOE_DIS_UID_LEN 6
+typedef struct _UidMacMappingEntry
+{
+ UCHAR isServer;
+ UCHAR uIDAddByUs; /* If the host-uniq or AC-cookie is add by our driver, set it as 1, else set as 0. */
+ UCHAR uIDStr[PPPOE_DIS_UID_LEN]; /* String used for identify who sent this pppoe packet in discovery stage. */
+ UCHAR macAddr[MAC_ADDR_LEN]; /* Mac address associated to this uid string. */
+ ULONG lastTime;
+ struct _UidMacMappingEntry *pNext; /*Pointer to next entry in link-list of Uid hash table. */
+}UidMacMappingEntry, *PUidMacMappingEntry;
+
+typedef struct _UidMacMappingTable
+{
+ BOOLEAN valid;
+ UidMacMappingEntry *uidHash[MAT_MAX_HASH_ENTRY_SUPPORT];
+}UidMacMappingTable;
+
+/* "Host-Uniq <-> Mac Address" Mapping table used for PPPoE Discovery stage */
+
+/* Data struct used for PPPoE session stage */
+typedef struct _SesMacMappingEntry
+{
+ UINT16 sessionID; /* In network order */
+ UCHAR outMacAddr[MAC_ADDR_LEN];
+ UCHAR inMacAddr[MAC_ADDR_LEN];
+ ULONG lastTime;
+ struct _SesMacMappingEntry *pNext;
+}SesMacMappingEntry, *PSesMacMappingEntry;
+
+typedef struct _SesMacMappingTable
+{
+ BOOLEAN valid;
+ SesMacMappingEntry *sesHash[MAT_MAX_HASH_ENTRY_SUPPORT];
+}SesMacMappingTable;
+
+/* Declaration of protocol handler for PPPoE Discovery stage */
+struct _MATProtoOps MATProtoPPPoEDisHandle =
+{
+ .init = MATProto_PPPoEDis_Init,
+ .tx = MATProto_PPPoEDis_Tx,
+ .rx = MATProto_PPPoEDis_Rx,
+ .exit = MATProto_PPPoEDis_Exit,
+};
+
+/* Declaration of protocol handler for PPPoE Session stage */
+struct _MATProtoOps MATProtoPPPoESesHandle =
+{
+ .init = MATProto_PPPoESes_Init,
+ .tx = MATProto_PPPoESes_Tx,
+ .rx = MATProto_PPPoESes_Rx,
+ .exit =MATProto_PPPoESes_Exit,
+};
+
+
+NDIS_STATUS dumpSesMacTb(
+ IN MAT_STRUCT *pMatCfg,
+ IN int hashIdx)
+{
+ SesMacMappingTable *pSesMacTable;
+ SesMacMappingEntry *pHead;
+ int startIdx, endIdx;
+
+
+ pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable;
+ if ((!pSesMacTable) || (!pSesMacTable->valid))
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("SesMacTable not init yet, so cannot do dump!\n"));
+ return FALSE;
+ }
+
+ if(hashIdx < 0)
+ { /* dump all. */
+ startIdx = 0;
+ endIdx = MAT_MAX_HASH_ENTRY_SUPPORT - 1;
+ }
+ else
+ { /* dump specific hash index. */
+ startIdx = endIdx = hashIdx;
+ }
+
+ DBGPRINT(RT_DEBUG_OFF, ("%s():\n", __FUNCTION__));
+ for (; startIdx<= endIdx; startIdx++)
+ {
+ pHead = pSesMacTable->sesHash[startIdx];
+ while(pHead)
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("SesMac[%d]:\n", startIdx));
+ DBGPRINT(RT_DEBUG_OFF, ("\tsesID=%d,inMac=%02x:%02x:%02x:%02x:%02x:%02x,outMac=%02x:%02x:%02x:%02x:%02x:%02x,lastTime=0x%lx, pNext=%p\n",
+ pHead->sessionID, PRINT_MAC(pHead->inMacAddr), PRINT_MAC(pHead->outMacAddr), pHead->lastTime, pHead->pNext));
+ pHead = pHead->pNext;
+ }
+ }
+ DBGPRINT(RT_DEBUG_OFF, ("\t----EndOfDump!\n"));
+
+ return TRUE;
+
+}
+
+
+NDIS_STATUS dumpUidMacTb(MAT_STRUCT *pMatCfg, int hashIdx)
+{
+ UidMacMappingTable *pUidMacTable;
+ UidMacMappingEntry *pHead;
+ int i;
+ int startIdx, endIdx;
+
+
+ pUidMacTable = (UidMacMappingTable *)pMatCfg->MatTableSet.UidMacTable;
+ if ((!pUidMacTable) || (!pUidMacTable->valid))
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("UidMacTable not init yet, so cannot do dump!\n"));
+ return FALSE;
+ }
+
+ if(hashIdx < 0)
+ { /* dump all. */
+ startIdx = 0;
+ endIdx = MAT_MAX_HASH_ENTRY_SUPPORT-1;
+ }
+ else
+ { /* dump specific hash index. */
+ startIdx = endIdx = hashIdx;
+ }
+
+ DBGPRINT(RT_DEBUG_OFF, ("%s():\n", __FUNCTION__));
+ for (; startIdx<= endIdx; startIdx++)
+ {
+ pHead = pUidMacTable->uidHash[startIdx];
+ while(pHead)
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("UidMac[%d]:\n", startIdx));
+ DBGPRINT(RT_DEBUG_OFF, ("\tisSrv=%d, uIDAddbyUs=%d, Mac=%02x:%02x:%02x:%02x:%02x:%02x, lastTime=0x%lx, pNext=%p\n",
+ pHead->isServer, pHead->uIDAddByUs, PRINT_MAC(pHead->macAddr), pHead->lastTime, pHead->pNext));
+ DBGPRINT(RT_DEBUG_OFF, ("\tuIDStr="));
+ for(i=0; i< PPPOE_DIS_UID_LEN; i++)
+ DBGPRINT(RT_DEBUG_OFF, ("%02x", pHead->uIDStr[i]));
+ DBGPRINT(RT_DEBUG_OFF, ("\n"));
+ pHead = pHead->pNext;
+ }
+ }
+ DBGPRINT(RT_DEBUG_OFF, ("\t----EndOfDump!\n"));
+
+ return TRUE;
+}
+
+
+static NDIS_STATUS UidMacTable_RemoveAll(
+ IN MAT_STRUCT *pMatCfg)
+{
+ UidMacMappingTable *pUidMacTable;
+ UidMacMappingEntry *pEntry;
+ INT i;
+
+ pUidMacTable = (UidMacMappingTable *)pMatCfg->MatTableSet.UidMacTable;
+
+ if(!pUidMacTable)
+ return TRUE;
+
+ if (pUidMacTable->valid)
+ {
+ pUidMacTable->valid = FALSE;
+ for (i=0; i<MAT_MAX_HASH_ENTRY_SUPPORT; i++)
+ {
+ while((pEntry = pUidMacTable->uidHash[i]) != NULL)
+ {
+ pUidMacTable->uidHash[i] = pEntry->pNext;
+ MATDBEntryFree(pMatCfg, (PUCHAR)pEntry);
+ }
+ }
+ }
+
+/* kfree(pMatCfg->MatTableSet.UidMacTable); */
+ os_free_mem(NULL, pMatCfg->MatTableSet.UidMacTable);
+ pMatCfg->MatTableSet.UidMacTable = NULL;
+
+ return TRUE;
+}
+
+
+static NDIS_STATUS SesMacTable_RemoveAll(
+ IN MAT_STRUCT *pMatCfg)
+{
+ SesMacMappingTable *pSesMacTable;
+ SesMacMappingEntry *pEntry;
+ INT i;
+
+ pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable;
+ if (!pSesMacTable)
+ return TRUE;
+
+ if (pSesMacTable->valid)
+ {
+ pSesMacTable->valid = FALSE;
+ for (i=0; i<MAT_MAX_HASH_ENTRY_SUPPORT; i++)
+ {
+ while((pEntry = pSesMacTable->sesHash[i]) != NULL)
+ {
+ pSesMacTable->sesHash[i] = pEntry->pNext;
+ MATDBEntryFree(pMatCfg, (PUCHAR)pEntry);
+ }
+ }
+ }
+
+/* kfree(pMatCfg->MatTableSet.SesMacTable); */
+ os_free_mem(NULL, pMatCfg->MatTableSet.SesMacTable);
+ pMatCfg->MatTableSet.SesMacTable = NULL;
+
+ return TRUE;
+
+}
+
+
+static PUidMacMappingEntry UidMacTableUpdate(
+ IN MAT_STRUCT *pMatCfg,
+ IN PUCHAR pInMac,
+ IN PUCHAR pOutMac,
+ IN PUCHAR pTagInfo,
+ IN UINT16 tagLen,
+ IN UINT16 isServer)
+{
+ UINT hashIdx, i=0, uIDAddByUs = 0;
+ UidMacMappingTable *pUidMacTable;
+ UidMacMappingEntry *pEntry = NULL, *pPrev = NULL, *pNewEntry =NULL;
+ UCHAR hashVal = 0;
+ PUCHAR pUIDStr= NULL;
+ ULONG now;
+
+
+ pUidMacTable = (UidMacMappingTable *)pMatCfg->MatTableSet.UidMacTable;
+ if ((!pUidMacTable) || (!pUidMacTable->valid))
+ return NULL;
+
+ if (pTagInfo && tagLen >0)
+ {
+ pUIDStr = pTagInfo;
+ uIDAddByUs = 0;
+ tagLen = (tagLen > PPPOE_DIS_UID_LEN ? PPPOE_DIS_UID_LEN : tagLen);
+ }
+ else
+ {
+ /*
+ We assume the station just have one role,i.e., just a PPPoE server or just a PPPoE client.
+ For a packet send by server, we use the destination MAC as our uIDStr
+ For a packet send by client, we use the source MAC as our uIDStr.
+ */
+ pUIDStr = isServer ? pOutMac: pInMac;
+ tagLen = MAC_ADDR_LEN;
+ uIDAddByUs = 1;
+ }
+
+ for (i=0; i<tagLen; i++)
+ hashVal ^= (pUIDStr[i] & 0xff);
+ hashIdx = hashVal % MAT_MAX_HASH_ENTRY_SUPPORT;
+
+ /*First, check if the hashIdx exists */
+ if (hashIdx < MAT_MAX_HASH_ENTRY_SUPPORT)
+ {
+ pEntry = pPrev = pUidMacTable->uidHash[hashIdx];
+ while(pEntry)
+ {
+ NdisGetSystemUpTime(&now);
+
+ /* Find the existed UidMac Mapping entry */
+ if (NdisEqualMemory(pUIDStr, pEntry->uIDStr, tagLen) && IS_EQUAL_MAC(pEntry->macAddr, pInMac))
+ {
+ /* Update info of this entry */
+ pEntry->isServer = isServer;
+ pEntry->uIDAddByUs = uIDAddByUs;
+ pEntry->lastTime = now;
+
+ return pEntry;
+ }
+ else
+ { /* handle the age-out situation */
+ if (RTMP_TIME_AFTER(now, (pEntry->lastTime + MAT_TB_ENTRY_AGEOUT_TIME)))
+ {
+ /* Remove the aged entry from the uidHash */
+ if (pEntry == pUidMacTable->uidHash[hashIdx])
+ {
+ pUidMacTable->uidHash[hashIdx]= pEntry->pNext;
+ pPrev = pUidMacTable->uidHash[hashIdx];
+ }
+ else
+ {
+ pPrev->pNext = pEntry->pNext;
+ }
+
+ /*After remove this entry from macHash list and uidHash list, now free it! */
+ MATDBEntryFree(pMatCfg, (PUCHAR)pEntry);
+ pMatCfg->nodeCount--;
+ pEntry = (pPrev == NULL ? NULL: pPrev->pNext);
+ }
+ else
+ {
+ pPrev = pEntry;
+ pEntry = pEntry->pNext;
+ }
+ }
+ }
+ }
+
+
+ /* Allocate a new UidMacMapping entry and insert into the double-hash */
+ pNewEntry = (UidMacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(UidMacMappingEntry));
+ if (pNewEntry)
+ {
+ NdisZeroMemory(pNewEntry, sizeof(UidMacMappingEntry));
+
+ pNewEntry->isServer = isServer;
+ pNewEntry->uIDAddByUs = uIDAddByUs;
+ NdisMoveMemory(pNewEntry->macAddr, pInMac, MAC_ADDR_LEN);
+ NdisMoveMemory(pNewEntry->uIDStr, pUIDStr, tagLen);
+ pNewEntry->pNext = NULL;
+ NdisGetSystemUpTime(&pNewEntry->lastTime);
+
+ /* Update mac-side hash link list */
+ if (pUidMacTable->uidHash[hashIdx] == NULL)
+ { /* Hash list is empty, directly assign it. */
+ pUidMacTable->uidHash[hashIdx] = pNewEntry;
+ }
+ else
+ {
+ /* Ok, we insert the new entry into the root of uidHash[hashIdx] */
+ pNewEntry->pNext = pUidMacTable->uidHash[hashIdx];
+ pUidMacTable->uidHash[hashIdx] = pNewEntry;
+ }
+ /*dumpUidMacTb(pMatCfg, hashIdx); //for debug */
+
+ pMatCfg->nodeCount++;
+
+ return pNewEntry;
+ }
+
+ return NULL;
+}
+
+
+static PUidMacMappingEntry UidMacTableLookUp(
+ IN MAT_STRUCT *pMatCfg,
+ IN PUCHAR pTagInfo,
+ IN UINT16 tagLen)
+{
+ UINT hashIdx;
+ UINT16 len;
+ UCHAR hashValue = 0;
+ UidMacMappingEntry *pEntry = NULL;
+ UidMacMappingTable *pUidMacTable;
+
+ pUidMacTable = (UidMacMappingTable *)pMatCfg->MatTableSet.UidMacTable;
+ if ((!pUidMacTable) || (!pUidMacTable->valid))
+ return NULL;
+
+ /* Use hash to find out the location of that entry and get the Mac address. */
+ len = tagLen;
+ while(len)
+ hashValue ^= pTagInfo[--len];
+ hashIdx = hashValue % MAT_MAX_HASH_ENTRY_SUPPORT;
+
+ pEntry = pUidMacTable->uidHash[hashIdx];
+ while(pEntry)
+ {
+ if (NdisEqualMemory(pEntry->uIDStr, pTagInfo, tagLen))
+ {
+/* DBGPRINT(RT_DEBUG_TRACE,("%s(): dstMac=%02x:%02x:%02x:%02x:%02x:%02x for mapped dstIP(%d.%d.%d.%d)\n",
+ __FUNCTION__, pEntry->macAddr[0],pEntry->macAddr[1],pEntry->macAddr[2],
+ pEntry->macAddr[3],pEntry->macAddr[4],pEntry->macAddr[5],
+ (ipAddr>>24) & 0xff, (ipAddr>>16) & 0xff, (ipAddr>>8) & 0xff, ipAddr & 0xff));
+*/
+ /*Update the lastTime to prevent the aging before pDA processed! */
+ NdisGetSystemUpTime(&pEntry->lastTime);
+
+ return pEntry;
+ }
+ else
+ pEntry = pEntry->pNext;
+ }
+
+ /* We didn't find any matched Mac address. */
+ return NULL;
+
+}
+
+
+static PUCHAR getInMacByOutMacFromSesMacTb(
+ IN MAT_STRUCT *pMatCfg,
+ IN PUCHAR outMac,
+ IN UINT16 sesID)
+{
+ UINT16 hashIdx;
+ SesMacMappingEntry *pEntry = NULL;
+ SesMacMappingTable *pSesMacTable;
+
+ pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable;
+
+ if (!pSesMacTable->valid)
+ return NULL;
+
+ /* Use hash to find out the location of that entry and get the Mac address. */
+ hashIdx = sesID % MAT_MAX_HASH_ENTRY_SUPPORT;
+
+ pEntry = pSesMacTable->sesHash[hashIdx];
+ while(pEntry)
+ {
+ if ((pEntry->sessionID == sesID) && IS_EQUAL_MAC(pEntry->outMacAddr, outMac))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): find it! dstMac=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ __FUNCTION__, pEntry->inMacAddr[0],pEntry->inMacAddr[1],pEntry->inMacAddr[2],
+ pEntry->inMacAddr[3],pEntry->inMacAddr[4],pEntry->inMacAddr[5]));
+
+ /*Update the lastTime to prevent the aging before pDA processed! */
+ NdisGetSystemUpTime(&pEntry->lastTime);
+
+ return pEntry->inMacAddr;
+ }
+ else
+ {
+ pEntry = pEntry->pNext;
+ }
+ }
+
+ /* We didn't find any matched Mac address, just return and didn't do any modification */
+ return NULL;
+}
+
+
+/* This function used to maintain the pppoe convert table which incoming node
+ is a pppoe client and want to connect to use inner pppoe server.
+*/
+static NDIS_STATUS SesMacTableUpdate(
+ IN MAT_STRUCT *pMatCfg,
+ IN PUCHAR inMacAddr,
+ IN UINT16 sesID,
+ IN PUCHAR outMacAddr)
+{
+ UINT16 hashIdx;
+ SesMacMappingEntry *pEntry, *pPrev, *pNewEntry;
+ SesMacMappingTable *pSesMacTable;
+ ULONG now;
+
+ pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable;
+ if ((!pSesMacTable) || (!pSesMacTable->valid))
+ return FALSE;
+
+ hashIdx = sesID % MAT_MAX_HASH_ENTRY_SUPPORT;
+
+/*
+ DBGPRINT(RT_DEBUG_TRACE,("%s():sesID=0x%04x,inMac=%02x%02x:%02x:%02x:%02x:%02x,
+ outMac=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, sesID,
+ inMacAddr[0],inMacAddr[1],inMacAddr[2],inMacAddr[3],inMacAddr[4],inMacAddr[5],
+ outMacAddr[0],outMacAddr[1],outMacAddr[2],outMacAddr[3],outMacAddr[4],outMacAddr[5]));
+*/
+
+ pEntry = pPrev = pSesMacTable->sesHash[hashIdx];
+ while(pEntry)
+ {
+ NdisGetSystemUpTime(&now);
+
+ /* Find a existed IP-MAC Mapping entry */
+ if ((sesID == pEntry->sessionID) &&
+ IS_EQUAL_MAC(pEntry->inMacAddr, inMacAddr) &&
+ IS_EQUAL_MAC(pEntry->outMacAddr, outMacAddr))
+ {
+ /* compare is useless. So we directly copy it into the entry. */
+ pEntry->lastTime = now;
+
+ return TRUE;
+ }
+ else
+ { /* handle the age-out situation */
+ if (RTMP_TIME_AFTER(now, (pEntry->lastTime + PPPoE_SES_ENTRY_AGEOUT_TIME)))
+ {
+ /* Remove the aged entry */
+ if (pEntry == pSesMacTable->sesHash[hashIdx])
+ {
+ pSesMacTable->sesHash[hashIdx]= pEntry->pNext;
+ pPrev = pSesMacTable->sesHash[hashIdx];
+ }
+ else
+ {
+ pPrev->pNext = pEntry->pNext;
+ }
+ MATDBEntryFree(pMatCfg, (PUCHAR)pEntry);
+ pMatCfg->nodeCount--;
+ pEntry = (pPrev == NULL ? NULL: pPrev->pNext);
+ }
+ else
+ {
+ pPrev = pEntry;
+ pEntry = pEntry->pNext;
+ }
+ }
+ }
+
+
+ /* Allocate a new IPMacMapping entry and insert into the hash */
+ pNewEntry = (SesMacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(SesMacMappingEntry));
+ if (pNewEntry != NULL)
+ {
+ pNewEntry->sessionID= sesID;
+ NdisMoveMemory(pNewEntry->inMacAddr, inMacAddr, MAC_ADDR_LEN);
+ NdisMoveMemory(pNewEntry->outMacAddr, outMacAddr, MAC_ADDR_LEN);
+ pNewEntry->pNext = NULL;
+ NdisGetSystemUpTime(&pNewEntry->lastTime);
+
+ if (pSesMacTable->sesHash[hashIdx] == NULL)
+ { /* Hash list is empty, directly assign it. */
+ pSesMacTable->sesHash[hashIdx] = pNewEntry;
+ }
+ else
+ {
+ /* Ok, we insert the new entry into the root of hash[hashIdx] */
+ pNewEntry->pNext = pSesMacTable->sesHash[hashIdx];
+ pSesMacTable->sesHash[hashIdx] = pNewEntry;
+ }
+
+ /*dumpSesMacTb(pMatCfg, hashIdx); */
+ pMatCfg->nodeCount++;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/* PPPoE discovery stage Rx handler.
+ When Rx, check if the PPPoE tag "Host-uniq" exists or not.
+ If exists, we check our database and convert the dstMac to correct one.
+ */
+static PUCHAR MATProto_PPPoEDis_Rx(
+ IN MAT_STRUCT *pMatCfg,
+ IN PNDIS_PACKET pSkb,
+ IN PUCHAR pLayerHdr,
+ IN PUCHAR pDevMacAdr)
+{
+ PUCHAR pData, pSrvMac = NULL, pCliMac= NULL, pOutMac=NULL, pInMac = NULL, pTagContent = NULL, pPayloadLen;
+ UINT16 payloadLen, leftLen;
+ UINT16 tagID, tagLen =0;
+ UINT16 needUpdateSesTb= 0, sesID=0, isPADT = 0;
+ UINT16 findTag=0;
+ PUidMacMappingEntry pEntry = NULL;
+
+ pData = pLayerHdr;
+ if (*(pData) != 0x11)
+ return NULL;
+
+ /* Check the Code type. */
+ pData++;
+ switch(*pData)
+ {
+ case PPPOE_CODE_PADO:
+ /*It's a packet send by a PPPoE server which behind of our device. */
+ findTag = PPPOE_TAG_ID_HOST_UNIQ;
+ break;
+ case PPPOE_CODE_PADS:
+ needUpdateSesTb = 1;
+ findTag = PPPOE_TAG_ID_HOST_UNIQ;
+ pCliMac = (PUCHAR)(GET_OS_PKT_DATAPTR(pSkb));
+ pSrvMac = (PUCHAR)(GET_OS_PKT_DATAPTR(pSkb) + 6);
+ break;
+ case PPPOE_CODE_PADR:
+ /*It's a packet send by a PPPoE client which in front of our device. */
+ findTag = PPPOE_TAG_ID_AC_COOKIE;
+ break;
+ case PPPOE_CODE_PADI:
+ /*Do nothing! Just forward this packet to upper layer directly. */
+ return NULL;
+ case PPPOE_CODE_PADT:
+ isPADT = 1;
+ pOutMac= (PUCHAR)(GET_OS_PKT_DATAPTR(pSkb) + 6);
+ break;
+ default:
+ return NULL;
+ }
+
+ /* Ignore the Code field(length=1) */
+ pData ++;
+ if (needUpdateSesTb || isPADT)
+ sesID = OS_NTOHS(get_unaligned((PUINT16)(pData)));
+
+ if (isPADT)
+ {
+ pInMac = getInMacByOutMacFromSesMacTb(pMatCfg, pOutMac, sesID);
+ return pInMac;
+ }
+ /* Ignore the session ID field.(length = 2) */
+ pData += 2;
+
+ /* Get the payload length, ignore the payload length field.(length = 2) */
+ payloadLen = OS_NTOHS(get_unaligned((PUINT16)(pData)));
+ pPayloadLen = pData;
+ pData += 2;
+
+
+ /* First parsing the PPPoE paylod to find out the required tag(e.g., x0103 or 0x0104) */
+ leftLen = payloadLen;
+ while (leftLen)
+ {
+ tagID = OS_NTOHS(get_unaligned((PUINT16)(pData)));
+ tagLen = OS_NTOHS(get_unaligned((PUINT16)(pData+2)));
+
+ if (tagID== findTag && tagLen>0)
+ {
+
+ /*shift to the tag value field. */
+ pTagContent = pData + 4;
+ tagLen = tagLen > PPPOE_DIS_UID_LEN ? PPPOE_DIS_UID_LEN : tagLen;
+ break;
+ }
+ else
+ {
+ pData += (tagLen + 4);
+ leftLen -= (tagLen + 4);
+ }
+ }
+
+
+ /* Now update our pppoe discovery table "UidMacTable" */
+ if (pTagContent)
+ {
+ pEntry = UidMacTableLookUp(pMatCfg, pTagContent, tagLen);
+
+ /* Remove the AC-Cookie or host-uniq if we ever add the field for this session. */
+ if (pEntry)
+ {
+ if (pEntry->uIDAddByUs)
+ {
+ PUCHAR tagHead, nextTagHead;
+ UINT removedTagLen, tailLen;
+
+ removedTagLen = 4 + tagLen; /*The total length tag ID/info we want to remove. */
+ tagHead = pTagContent - 4; /*The start address of the tag we want to remove in sk bufffer */
+ tailLen = GET_OS_PKT_LEN(pSkb) - (pTagContent - (PUCHAR)(GET_OS_PKT_DATAPTR(pSkb))) - removedTagLen; /*Total left bytes we want to move. */
+ if (tailLen)
+ {
+ nextTagHead = pTagContent + tagLen; /*The start address of next tag ID/info in sk buffer. */
+ memmove(tagHead, nextTagHead, tailLen);
+ }
+/* SET_OS_PKT_DATATAIL(pSkb, GET_OS_PKT_DATATAIL(pSkb), (-removedTagLen)); */
+/* GET_OS_PKT_LEN(pSkb) -= removedTagLen; */
+ OS_PKT_TAIL_ADJUST(pSkb, removedTagLen);
+
+ *((UINT16 *)pPayloadLen) = OS_HTONS(payloadLen - removedTagLen);
+ }
+
+ if (needUpdateSesTb) {
+
+ SesMacTableUpdate(pMatCfg, pEntry->macAddr,sesID, pSrvMac);
+ }
+
+ return pEntry->macAddr;
+ }
+ }
+
+ return NULL;
+}
+
+
+
+/* PPPoE discovery stage Tx handler.
+ If the pakcet is PADI/PADR, check if the PPPoE tag "Host-uniq" exists or not.
+ If exists, we just record it in our table, else we insert the Mac address
+ of Sender as well as the host-uniq, then forward to the destination. It's
+ a one(MAC)-to-one(Host-uniq) mapping in our table.
+ If the packet is PADO/PADS, check if the PPPoE tag "AC-Cookie" exists or not.
+ If exists, we just record it in our table, else we insert the Mac address
+ of Sender as well as the AC-Cookie, then forward to the destination. It may
+ one(MAC)-to-many(AC-Cookie) mapping in our table.
+
+ Host-uniq TAG ID= 0x0103
+ AC-Cookie TAG ID= 0x0104
+ */
+static PUCHAR MATProto_PPPoEDis_Tx(
+ IN MAT_STRUCT *pMatStruct,
+ IN PNDIS_PACKET pSkb,
+ IN PUCHAR pLayerHdr,
+ IN PUCHAR pDevMacAdr)
+{
+ PUCHAR pData, pTagContent = NULL, pPayloadLen, pPPPPoETail;
+ PUCHAR pSrcMac, pDstMac;
+ UINT16 payloadLen, leftLen, offset;
+ UINT16 tagID, tagLen =0;
+ UINT16 isServer = 0, needUpdateSesTb= 0, sesID = 0;
+ UINT16 findTag=0;
+ PUidMacMappingEntry pEntry = NULL;
+ PUCHAR pPktHdr;
+ PNDIS_PACKET pModSkb = NULL;
+
+ pPktHdr = GET_OS_PKT_DATAPTR(pSkb);
+ pDstMac = pPktHdr;
+ pSrcMac = (pPktHdr + 6);
+ pData = pLayerHdr;
+
+
+ /* Check the pppoe version and Type. It should be 0x11 */
+ if (*(pData) != 0x11)
+ return NULL;
+
+ /* Check the Code type. */
+ pData++;
+ switch(*pData)
+ {
+ /* Send by pppoe client */
+ case PPPOE_CODE_PADI:
+ case PPPOE_CODE_PADR:
+ findTag = PPPOE_TAG_ID_HOST_UNIQ;
+ break;
+ /* Send by pppoe server */
+ case PPPOE_CODE_PADO:
+ case PPPOE_CODE_PADS:
+ isServer = 1;
+ findTag = PPPOE_TAG_ID_AC_COOKIE;
+ if (*pData == PPPOE_CODE_PADS) /* For PADS, we need record the session ID. */
+ needUpdateSesTb = 1;
+ break;
+ /* Both server and client can send this packet */
+ case PPPOE_CODE_PADT:
+ /* TODO:
+ currently we didn't handle PADT packet. We just leave the
+ session entry and make it age-out automatically. Maybe we
+ can remove the entry when we receive this packet.
+ */
+ return NULL;
+ default:
+ return NULL;
+ }
+
+ /*
+ Ignore the Code field(length=1) and if it's a PADS packet, we
+ should hold the session ID and for latter to update our table.
+ */
+ pData ++;
+ if (needUpdateSesTb)
+ sesID = OS_NTOHS(get_unaligned((PUINT16)(pData)));
+
+ /* Ignore the session ID field.(length = 2) */
+ pData += 2;
+
+ /* Get the payload length, and shift the payload length field(length = 2) to next field. */
+ payloadLen = OS_NTOHS(get_unaligned((PUINT16)(pData)));
+ pPayloadLen = pData;
+ offset = pPayloadLen - (PUCHAR)(GET_OS_PKT_DATAPTR(pSkb));
+ pData += 2;
+
+
+ /* First parsing the PPPoE paylod to find out the required tag(e.g., x0103 or 0x0104) */
+ leftLen = payloadLen;
+ while (leftLen)
+ {
+ tagID = OS_NTOHS(get_unaligned((PUINT16)(pData)));
+ tagLen = OS_NTOHS(get_unaligned((PUINT16)(pData+2)));
+
+ if (tagID== findTag && tagLen>0)
+ {
+
+ /* Move the pointer to the tag value field. 4 = 2(TAG ID) + 2(TAG_LEN) */
+ pTagContent = pData + 4;
+/* tagLen = tagLen > PPPOE_DIS_UID_LEN ? PPPOE_DIS_UID_LEN : tagLen; */
+ break;
+ }
+ else
+ {
+ pData += (tagLen + 4);
+ leftLen -= (tagLen + 4);
+ }
+ }
+
+
+ /* Now update our pppoe discovery table "UidMacTable" */
+ pEntry = UidMacTableUpdate(pMatStruct, pSrcMac, pDstMac, pTagContent, tagLen, isServer);
+
+ if (pEntry && (pTagContent == NULL))
+ {
+ PUCHAR tailHead;
+
+ if(OS_PKT_CLONED(pSkb))
+ {
+/* pModSkb = (PNDIS_PACKET)skb_copy(RTPKT_TO_OSPKT(pSkb), MEM_ALLOC_FLAG); */
+ pModSkb = (PNDIS_PACKET)OS_PKT_COPY(RTPKT_TO_OSPKT(pSkb));
+ }
+ else
+ pModSkb = (PNDIS_PACKET)RTPKT_TO_OSPKT(pSkb);
+
+ if(!pModSkb)
+ return NULL;
+
+/* tailHead = skb_put(RTPKT_TO_OSPKT(pModSkb), (PPPOE_DIS_UID_LEN + 4)); */
+ tailHead = OS_PKT_TAIL_BUF_EXTEND(pModSkb, (PPPOE_DIS_UID_LEN + 4));
+ if (tailHead)
+ {
+ pPayloadLen = GET_OS_PKT_DATAPTR(pModSkb) + offset;
+ pPPPPoETail = pPayloadLen + payloadLen;
+ if(tailHead > pPPPPoETail)
+ tailHead = pPPPPoETail;
+
+ if (pEntry->isServer)
+ { /*Append the AC-Cookie tag info in the tail of the pppoe packet. */
+ tailHead[0] = 0x01;
+ tailHead[1] = 0x04;
+ tailHead[2] = 0x00;
+ tailHead[3] = PPPOE_DIS_UID_LEN;
+ tailHead += 4;
+ NdisMoveMemory(tailHead, pEntry->uIDStr, PPPOE_DIS_UID_LEN);
+ }
+ else
+ { /*Append the host-uniq tag info in the tail of the pppoe packet. */
+ tailHead[0] = 0x01;
+ tailHead[1] = 0x03;
+ tailHead[2] = 0x00;
+ tailHead[3] = PPPOE_DIS_UID_LEN;
+ tailHead += 4;
+ NdisMoveMemory(tailHead, pEntry->uIDStr, PPPOE_DIS_UID_LEN);
+ }
+ *(UINT16 *)pPayloadLen = OS_HTONS(payloadLen + 4 + PPPOE_DIS_UID_LEN);
+ }
+ }
+
+ if (needUpdateSesTb)
+ SesMacTableUpdate(pMatStruct, pSrcMac, sesID, pDstMac);
+
+ return (PUCHAR)pModSkb;
+}
+
+
+/* PPPoE discovery stage init function */
+static NDIS_STATUS MATProto_PPPoEDis_Init(
+ IN MAT_STRUCT *pMatCfg)
+{
+ UidMacMappingTable *pUidMacTable;
+ SesMacMappingTable *pSesMacTable;
+
+ pUidMacTable = (UidMacMappingTable *)pMatCfg->MatTableSet.UidMacTable;
+ if (!pUidMacTable)
+ {
+/* pMatCfg->MatTableSet.UidMacTable = (VOID *)kmalloc(sizeof(UidMacMappingTable), GFP_KERNEL); */
+ os_alloc_mem_suspend(NULL, (UCHAR **)&(pMatCfg->MatTableSet.UidMacTable), sizeof(UidMacMappingTable));
+ if (pMatCfg->MatTableSet.UidMacTable)
+ {
+ pUidMacTable = (UidMacMappingTable *)pMatCfg->MatTableSet.UidMacTable;
+ NdisZeroMemory(pUidMacTable, sizeof(UidMacMappingTable));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MATProto_PPPoEDis_Init(): Allocate memory for UidMacTable failed!\n"));
+ return FALSE;
+ }
+ }
+ pUidMacTable->valid = TRUE;
+
+ pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable;
+ if (!pSesMacTable)
+ {
+/* pMatCfg->MatTableSet.SesMacTable = (VOID *)kmalloc(sizeof(SesMacMappingTable), GFP_KERNEL); */
+ os_alloc_mem_suspend(NULL, (UCHAR **)&(pMatCfg->MatTableSet.SesMacTable), sizeof(SesMacMappingTable));
+ if (pMatCfg->MatTableSet.SesMacTable)
+ {
+ pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable;
+ NdisZeroMemory(pSesMacTable, sizeof(SesMacMappingTable));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MATProto_PPPoEDis_Init(): Allocate memory for SesMacTable failed!\n"));
+ return FALSE;
+ }
+
+ }
+ pSesMacTable->valid = TRUE;
+
+ return TRUE;
+}
+
+
+/* PPPoE discovery stage exit function */
+static NDIS_STATUS MATProto_PPPoEDis_Exit(
+ IN MAT_STRUCT *pMatCfg)
+{
+ UidMacTable_RemoveAll(pMatCfg);
+ SesMacTable_RemoveAll(pMatCfg);
+
+ return TRUE;
+}
+
+
+/* PPPoE Session stage Rx handler
+ When we receive a ppp pakcet, first check if the srcMac is a PPPoE server or not.
+ if it's a server, check the session ID of specific PPPoEServeryEntry and find out the
+ correct dstMac Address.
+ if it's not a server, check the session ID and find out the cor
+
+ */
+static PUCHAR MATProto_PPPoESes_Rx(
+ IN MAT_STRUCT *pMatCfg,
+ IN PNDIS_PACKET pSkb,
+ IN PUCHAR pLayerHdr,
+ IN PUCHAR pDevMacAdr)
+{
+ PUCHAR srcMac, dstMac = NULL, pData;
+ UINT16 sesID;
+
+ srcMac = (GET_OS_PKT_DATAPTR(pSkb) + 6);
+ pData = pLayerHdr;
+
+ /*skip the first two bytes.(version/Type/Code) */
+ pData += 2;
+
+ /*get the session ID */
+ sesID = OS_NTOHS(get_unaligned((PUINT16)(pData)));
+
+ /* Try to find the dstMac from SesMacHash table. */
+ dstMac = getInMacByOutMacFromSesMacTb(pMatCfg, srcMac, sesID);
+
+ return dstMac;
+}
+
+/* PPPoE Session stage Tx handler */
+static PUCHAR MATProto_PPPoESes_Tx(
+ IN MAT_STRUCT *pMatStruct,
+ IN PNDIS_PACKET pSkb,
+ IN PUCHAR pLayerHdr,
+ IN PUCHAR pDevMacAdr)
+{
+
+ /*
+ For transmit packet, we do nothing.
+ */
+ return NULL;
+}
+
+
+/* PPPoE session stage init function */
+static NDIS_STATUS MATProto_PPPoESes_Init(
+ IN MAT_STRUCT *pMatStruct)
+{
+ return TRUE;
+}
+
+/* PPPoE session stage exit function */
+static NDIS_STATUS MATProto_PPPoESes_Exit(
+ IN MAT_STRUCT *pMatStruct)
+{
+
+ return TRUE;
+}
+
+#endif /* MAT_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_profile.c b/cleopatre/devkit/mt7601udrv/common/cmm_profile.c
new file mode 100644
index 0000000000..fe324ff12a
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_profile.c
@@ -0,0 +1,5059 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ****************************************************************************
+
+ Module Name:
+ cmm_profile.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ --------- ---------- ----------------------------------------------
+ */
+
+#include "rt_config.h"
+
+
+#define ETH_MAC_ADDR_STR_LEN 17 /* in format of xx:xx:xx:xx:xx:xx*/
+
+/* We assume the s1 is a sting, s2 is a memory space with 6 bytes. and content of s1 will be changed.*/
+BOOLEAN rtstrmactohex(PSTRING s1, PSTRING s2)
+{
+ int i = 0;
+ PSTRING ptokS = s1, ptokE = s1;
+
+ if (strlen(s1) != ETH_MAC_ADDR_STR_LEN)
+ return FALSE;
+
+ while((*ptokS) != '\0')
+ {
+ if((ptokE = strchr(ptokS, ':')) != NULL)
+ *ptokE++ = '\0';
+ if ((strlen(ptokS) != 2) || (!isxdigit(*ptokS)) || (!isxdigit(*(ptokS+1))))
+ break; /* fail*/
+ AtoH(ptokS, (PUCHAR)&s2[i++], 1);
+ ptokS = ptokE;
+ if (ptokS == NULL)
+ break;
+ if (i == 6)
+ break; /* parsing finished*/
+ }
+
+ return ( i == 6 ? TRUE : FALSE);
+
+}
+
+
+#define ASC_LOWER(_x) ((((_x) >= 0x41) && ((_x) <= 0x5a)) ? (_x) + 0x20 : (_x))
+/* we assume the s1 and s2 both are strings.*/
+BOOLEAN rtstrcasecmp(PSTRING s1, PSTRING s2)
+{
+ PSTRING p1 = s1, p2 = s2;
+ CHAR c1, c2;
+
+ if (strlen(s1) != strlen(s2))
+ return FALSE;
+
+ while(*p1 != '\0')
+ {
+ c1 = ASC_LOWER(*p1);
+ c2 = ASC_LOWER(*p2);
+ if(c1 != c2)
+ return FALSE;
+ p1++;
+ p2++;
+ }
+
+ return TRUE;
+}
+
+
+/* we assume the s1 (buffer) and s2 (key) both are strings.*/
+PSTRING rtstrstruncasecmp(PSTRING s1, PSTRING s2)
+{
+ INT l1, l2, i;
+ char temp1, temp2;
+
+ l2 = strlen(s2);
+ if (!l2)
+ return (char *) s1;
+
+ l1 = strlen(s1);
+
+ while (l1 >= l2)
+ {
+ l1--;
+
+ for(i=0; i<l2; i++)
+ {
+ temp1 = *(s1+i);
+ temp2 = *(s2+i);
+
+ if (('a' <= temp1) && (temp1 <= 'z'))
+ temp1 = 'A'+(temp1-'a');
+ if (('a' <= temp2) && (temp2 <= 'z'))
+ temp2 = 'A'+(temp2-'a');
+
+ if (temp1 != temp2)
+ break;
+ }
+
+ if (i == l2)
+ return (char *) s1;
+
+ s1++;
+ }
+
+ return NULL; /* not found*/
+}
+
+
+ /**
+ * strstr - Find the first substring in a %NUL terminated string
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ */
+PSTRING rtstrstr(PSTRING s1,const PSTRING s2)
+{
+ INT l1, l2;
+
+ l2 = strlen(s2);
+ if (!l2)
+ return s1;
+
+ l1 = strlen(s1);
+
+ while (l1 >= l2)
+ {
+ l1--;
+ if (!memcmp(s1,s2,l2))
+ return s1;
+ s1++;
+ }
+
+ return NULL;
+}
+
+/**
+ * rstrtok - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ * * WARNING: strtok is deprecated, use strsep instead. However strsep is not compatible with old architecture.
+ */
+PSTRING __rstrtok;
+PSTRING rstrtok(PSTRING s,const PSTRING ct)
+{
+ PSTRING sbegin, send;
+
+ sbegin = s ? s : __rstrtok;
+ if (!sbegin)
+ {
+ return NULL;
+ }
+
+ sbegin += strspn(sbegin,ct);
+ if (*sbegin == '\0')
+ {
+ __rstrtok = NULL;
+ return( NULL );
+ }
+
+ send = strpbrk( sbegin, ct);
+ if (send && *send != '\0')
+ *send++ = '\0';
+
+ __rstrtok = send;
+
+ return (sbegin);
+}
+
+/**
+ * delimitcnt - return the count of a given delimiter in a given string.
+ * @s: The string to be searched.
+ * @ct: The delimiter to search for.
+ * Notice : We suppose the delimiter is a single-char string(for example : ";").
+ */
+INT delimitcnt(PSTRING s,PSTRING ct)
+{
+ INT count = 0;
+ /* point to the beginning of the line */
+ PSTRING token = s;
+
+ for ( ;; )
+ {
+ token = strpbrk(token, ct); /* search for delimiters */
+
+ if ( token == NULL )
+ {
+ /* advanced to the terminating null character */
+ break;
+ }
+ /* skip the delimiter */
+ ++token;
+
+ /*
+ * Print the found text: use len with %.*s to specify field width.
+ */
+
+ /* accumulate delimiter count */
+ ++count;
+ }
+ return count;
+}
+
+/*
+ * converts the Internet host address from the standard numbers-and-dots notation
+ * into binary data.
+ * returns nonzero if the address is valid, zero if not.
+ */
+int rtinet_aton(PSTRING cp, unsigned int *addr)
+{
+ unsigned int val;
+ int base, n;
+ STRING c;
+ unsigned int parts[4];
+ unsigned int *pp = parts;
+
+ for (;;)
+ {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, other=decimal.
+ */
+ val = 0;
+ base = 10;
+ if (*cp == '0')
+ {
+ if (*++cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+ else
+ base = 8;
+ }
+ while ((c = *cp) != '\0')
+ {
+ if (isdigit((unsigned char) c))
+ {
+ val = (val * base) + (c - '0');
+ cp++;
+ continue;
+ }
+ if (base == 16 && isxdigit((unsigned char) c))
+ {
+ val = (val << 4) +
+ (c + 10 - (islower((unsigned char) c) ? 'a' : 'A'));
+ cp++;
+ continue;
+ }
+ break;
+ }
+ if (*cp == '.')
+ {
+ /*
+ * Internet format: a.b.c.d a.b.c (with c treated as 16-bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3 || val > 0xff)
+ return 0;
+ *pp++ = val, cp++;
+ }
+ else
+ break;
+ }
+
+ /*
+ * Check for trailing junk.
+ */
+ while (*cp)
+ if (!isspace((unsigned char) *cp++))
+ return 0;
+
+ /*
+ * Concoct the address according to the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n)
+ {
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffff)
+ return 0;
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff)
+ return 0;
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff)
+ return 0;
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+
+ *addr = OS_HTONL(val);
+ return 1;
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Find key section for Get key parameter.
+
+ Arguments:
+ buffer Pointer to the buffer to start find the key section
+ section the key of the secion to be find
+
+ Return Value:
+ NULL Fail
+ Others Success
+ ========================================================================
+*/
+PSTRING RTMPFindSection(
+ IN PSTRING buffer)
+{
+ STRING temp_buf[32];
+ PSTRING ptr;
+
+ strcpy(temp_buf, "Default");
+
+ if((ptr = rtstrstr(buffer, temp_buf)) != NULL)
+ return (ptr+strlen("\n"));
+ else
+ return NULL;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Get key parameter.
+
+ Arguments:
+ key Pointer to key string
+ dest Pointer to destination
+ destsize The datasize of the destination
+ buffer Pointer to the buffer to start find the key
+ bTrimSpace Set true if you want to strip the space character of the result pattern
+
+ Return Value:
+ TRUE Success
+ FALSE Fail
+
+ Note:
+ This routine get the value with the matched key (case case-sensitive)
+ For SSID and security key related parameters, we SHALL NOT trim the space(' ') character.
+ ========================================================================
+*/
+INT RTMPGetKeyParameter(
+ IN PSTRING key,
+ OUT PSTRING dest,
+ IN INT destsize,
+ IN PSTRING buffer,
+ IN BOOLEAN bTrimSpace)
+{
+ PSTRING pMemBuf, temp_buf1 = NULL, temp_buf2 = NULL;
+ PSTRING start_ptr, end_ptr;
+ PSTRING ptr;
+ PSTRING offset = NULL;
+ INT len, keyLen;
+
+
+ keyLen = strlen(key);
+ os_alloc_mem(NULL, (PUCHAR *)&pMemBuf, MAX_PARAM_BUFFER_SIZE * 2);
+ if (pMemBuf == NULL)
+ return (FALSE);
+
+ memset(pMemBuf, 0, MAX_PARAM_BUFFER_SIZE * 2);
+ temp_buf1 = pMemBuf;
+ temp_buf2 = (PSTRING)(pMemBuf + MAX_PARAM_BUFFER_SIZE);
+
+
+ /*find section*/
+ if((offset = RTMPFindSection(buffer)) == NULL)
+ {
+ os_free_mem(NULL, (PUCHAR)pMemBuf);
+ return (FALSE);
+ }
+
+ strcpy(temp_buf1, "\n");
+ strcat(temp_buf1, key);
+ strcat(temp_buf1, "=");
+
+ /*search key*/
+ if((start_ptr=rtstrstr(offset, temp_buf1)) == NULL)
+ {
+ os_free_mem(NULL, (PUCHAR)pMemBuf);
+ return (FALSE);
+ }
+
+ start_ptr += strlen("\n");
+ if((end_ptr = rtstrstr(start_ptr, "\n"))==NULL)
+ end_ptr = start_ptr+strlen(start_ptr);
+
+ if (end_ptr<start_ptr)
+ {
+ os_free_mem(NULL, (PUCHAR)pMemBuf);
+ return (FALSE);
+ }
+
+ NdisMoveMemory(temp_buf2, start_ptr, end_ptr-start_ptr);
+ temp_buf2[end_ptr-start_ptr]='\0';
+
+ if((start_ptr=rtstrstr(temp_buf2, "=")) == NULL)
+ {
+ os_free_mem(NULL, (PUCHAR)pMemBuf);
+ return (FALSE);
+ }
+ ptr = (start_ptr +1);
+ /*trim special characters, i.e., TAB or space*/
+ while(*start_ptr != 0x00)
+ {
+ if( ((*ptr == ' ') && bTrimSpace) || (*ptr == '\t') )
+ ptr++;
+ else
+ break;
+ }
+ len = strlen(start_ptr);
+
+ memset(dest, 0x00, destsize);
+ strncpy(dest, ptr, ((len >= destsize) ? destsize: len));
+
+ os_free_mem(NULL, (PUCHAR)pMemBuf);
+
+ return TRUE;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Get multiple key parameter.
+
+ Arguments:
+ key Pointer to key string
+ dest Pointer to destination
+ destsize The datasize of the destination
+ buffer Pointer to the buffer to start find the key
+
+ Return Value:
+ TRUE Success
+ FALSE Fail
+
+ Note:
+ This routine get the value with the matched key (case case-sensitive)
+ ========================================================================
+*/
+INT RTMPGetKeyParameterWithOffset(
+ IN PSTRING key,
+ OUT PSTRING dest,
+ OUT USHORT *end_offset,
+ IN INT destsize,
+ IN PSTRING buffer,
+ IN BOOLEAN bTrimSpace)
+{
+ PSTRING temp_buf1 = NULL;
+ PSTRING temp_buf2 = NULL;
+ PSTRING start_ptr;
+ PSTRING end_ptr;
+ PSTRING ptr;
+ PSTRING offset = 0;
+ INT len;
+
+ if (*end_offset >= MAX_INI_BUFFER_SIZE)
+ return (FALSE);
+
+ os_alloc_mem(NULL, (PUCHAR *)&temp_buf1, MAX_PARAM_BUFFER_SIZE);
+
+ if(temp_buf1 == NULL)
+ return (FALSE);
+
+ os_alloc_mem(NULL, (PUCHAR *)&temp_buf2, MAX_PARAM_BUFFER_SIZE);
+ if(temp_buf2 == NULL)
+ {
+ os_free_mem(NULL, (PUCHAR)temp_buf1);
+ return (FALSE);
+ }
+
+ /*find section */
+ if(*end_offset == 0)
+ {
+ if ((offset = RTMPFindSection(buffer)) == NULL)
+ {
+ os_free_mem(NULL, (PUCHAR)temp_buf1);
+ os_free_mem(NULL, (PUCHAR)temp_buf2);
+ return (FALSE);
+ }
+ }
+ else
+ offset = buffer + (*end_offset);
+
+ strcpy(temp_buf1, "\n");
+ strcat(temp_buf1, key);
+ strcat(temp_buf1, "=");
+
+ /*search key*/
+ if((start_ptr=rtstrstr(offset, temp_buf1))==NULL)
+ {
+ os_free_mem(NULL, (PUCHAR)temp_buf1);
+ os_free_mem(NULL, (PUCHAR)temp_buf2);
+ return (FALSE);
+ }
+
+ start_ptr+=strlen("\n");
+ if((end_ptr=rtstrstr(start_ptr, "\n"))==NULL)
+ end_ptr=start_ptr+strlen(start_ptr);
+
+ if (end_ptr<start_ptr)
+ {
+ os_free_mem(NULL, (PUCHAR)temp_buf1);
+ os_free_mem(NULL, (PUCHAR)temp_buf2);
+ return (FALSE);
+ }
+
+ *end_offset = end_ptr - buffer;
+
+ NdisMoveMemory(temp_buf2, start_ptr, end_ptr-start_ptr);
+ temp_buf2[end_ptr-start_ptr]='\0';
+ len = strlen(temp_buf2);
+ strcpy(temp_buf1, temp_buf2);
+ if((start_ptr=rtstrstr(temp_buf1, "=")) == NULL)
+ {
+ os_free_mem(NULL, (PUCHAR)temp_buf1);
+ os_free_mem(NULL, (PUCHAR)temp_buf2);
+ return (FALSE);
+ }
+
+ strcpy(temp_buf2, start_ptr+1);
+ ptr = temp_buf2;
+ /*trim space or tab*/
+ while(*ptr != 0x00)
+ {
+ if((bTrimSpace && (*ptr == ' ')) || (*ptr == '\t') )
+ ptr++;
+ else
+ break;
+ }
+
+ len = strlen(ptr);
+ memset(dest, 0x00, destsize);
+ strncpy(dest, ptr, len >= destsize ? destsize: len);
+
+ os_free_mem(NULL, (PUCHAR)temp_buf1);
+ os_free_mem(NULL, (PUCHAR)temp_buf2);
+ return TRUE;
+}
+
+
+
+
+static int rtmp_parse_key_buffer_from_file(IN PRTMP_ADAPTER pAd,IN PSTRING buffer,IN ULONG KeyType,IN INT BSSIdx,IN INT KeyIdx)
+{
+ PSTRING keybuff;
+ /*INT i = BSSIdx, idx = KeyIdx, retVal;*/
+ ULONG KeyLen;
+ /*UCHAR CipherAlg = CIPHER_WEP64;*/
+ CIPHER_KEY *pSharedKey;
+
+ keybuff = buffer;
+ KeyLen = strlen(keybuff);
+ pSharedKey = &pAd->SharedKey[BSSIdx][KeyIdx];
+
+ if(((KeyType != 0) && (KeyType != 1)) ||
+ ((KeyType == 0) && (KeyLen != 10) && (KeyLen != 26)) ||
+ ((KeyType== 1) && (KeyLen != 5) && (KeyLen != 13)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Key%dStr is Invalid key length(%ld) or Type(%ld)\n",
+ KeyIdx+1, KeyLen, KeyType));
+ return FALSE;
+ }
+ else
+ {
+ return RT_CfgSetWepKey(pAd, buffer, pSharedKey, KeyIdx);
+ }
+
+}
+
+
+static void rtmp_read_key_parms_from_file(IN PRTMP_ADAPTER pAd, PSTRING tmpbuf, PSTRING buffer)
+{
+ STRING tok_str[16];
+ PSTRING macptr;
+ INT i = 0, idx;
+ ULONG KeyType[HW_BEACON_MAX_NUM];
+ ULONG KeyIdx;
+
+ NdisZeroMemory(KeyType, sizeof(KeyType));
+
+ /*DefaultKeyID*/
+ if(RTMPGetKeyParameter("DefaultKeyID", tmpbuf, 25, buffer, TRUE))
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i >= pAd->ApCfg.BssidNum)
+ {
+ break;
+ }
+
+ KeyIdx = simple_strtol(macptr, 0, 10);
+ if((KeyIdx >= 1 ) && (KeyIdx <= 4))
+ pAd->ApCfg.MBSSID[i].DefaultKeyId = (UCHAR) (KeyIdx - 1 );
+ else
+ pAd->ApCfg.MBSSID[i].DefaultKeyId = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) DefaultKeyID(0~3)=%d\n", i, pAd->ApCfg.MBSSID[i].DefaultKeyId));
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+
+
+ for (idx = 0; idx < 4; idx++)
+ {
+ snprintf(tok_str, sizeof(tok_str), "Key%dType", idx + 1);
+ /*Key1Type*/
+ if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ /*
+ do sanity check for KeyType length;
+ or in station mode, the KeyType length > 1,
+ the code will overwrite the stack of caller
+ (RTMPSetProfileParameters) and cause srcbuf = NULL
+ */
+ if (i < MAX_MBSSID_NUM(pAd))
+ KeyType[i] = simple_strtol(macptr, 0, 10);
+ }
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if (TRUE)
+ {
+ BOOLEAN bKeyxStryIsUsed = FALSE;
+
+ //GPRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.BssidNum=%d\n", pAd->ApCfg.BssidNum));
+ for (i = 0; i < pAd->ApCfg.BssidNum; i++)
+ {
+ snprintf(tok_str, sizeof(tok_str), "Key%dStr%d", idx + 1, i + 1);
+ if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE))
+ {
+ rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[i], i, idx);
+
+ if (bKeyxStryIsUsed == FALSE)
+ {
+ bKeyxStryIsUsed = TRUE;
+ }
+ }
+ }
+
+ if (bKeyxStryIsUsed == FALSE)
+ {
+ snprintf(tok_str, sizeof(tok_str), "Key%dStr", idx + 1);
+ if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE))
+ {
+ if (pAd->ApCfg.BssidNum == 1)
+ {
+ rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[BSS0], BSS0, idx);
+ }
+ else
+ {
+ /* Anyway, we still do the legacy dissection of the whole KeyxStr string.*/
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ rtmp_parse_key_buffer_from_file(pAd, macptr, KeyType[i], i, idx);
+ }
+ }
+ }
+ }
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ }
+}
+
+#ifdef CONFIG_AP_SUPPORT
+
+#ifdef APCLI_SUPPORT
+static void rtmp_read_ap_client_from_file(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING tmpbuf,
+ IN PSTRING buffer)
+{
+ PSTRING macptr = NULL;
+ INT i=0, j=0, idx;
+ UCHAR macAddress[MAC_ADDR_LEN];
+ /*UCHAR keyMaterial[40];*/
+ PAPCLI_STRUCT pApCliEntry = NULL;
+ ULONG KeyIdx;
+ STRING tok_str[16];
+ ULONG KeyType[MAX_APCLI_NUM];
+ ULONG KeyLen;
+ /*UCHAR CipherAlg = CIPHER_WEP64;*/
+
+
+ NdisZeroMemory(KeyType, sizeof(KeyType));
+
+ /*ApCliEnable*/
+ if(RTMPGetKeyParameter("ApCliEnable", tmpbuf, 128, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++)
+ {
+ pApCliEntry = &pAd->ApCfg.ApCliTab[i];
+ if ((strncmp(macptr, "0", 1) == 0))
+ pApCliEntry->Enable = FALSE;
+ else if ((strncmp(macptr, "1", 1) == 0))
+ pApCliEntry->Enable = TRUE;
+ else
+ pApCliEntry->Enable = FALSE;
+
+ if (pApCliEntry->Enable)
+ {
+ /*pApCliEntry->WpaState = SS_NOTUSE;*/
+ /*pApCliEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;*/
+ /*NdisZeroMemory(pApCliEntry->ReplayCounter, LEN_KEY_DESC_REPLAY); */
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("ApCliEntry[%d].Enable=%d\n", i, pApCliEntry->Enable));
+ }
+ }
+
+ /*ApCliSsid*/
+ if(RTMPGetKeyParameter("ApCliSsid", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, FALSE))
+ {
+ for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++)
+ {
+ pApCliEntry = &pAd->ApCfg.ApCliTab[i];
+
+ /*Ssid acceptable strlen must be less than 32 and bigger than 0.*/
+ pApCliEntry->CfgSsidLen = (UCHAR)strlen(macptr);
+ if (pApCliEntry->CfgSsidLen > 32)
+ {
+ pApCliEntry->CfgSsidLen = 0;
+ continue;
+ }
+ if(pApCliEntry->CfgSsidLen > 0)
+ {
+ memcpy(&pApCliEntry->CfgSsid, macptr, pApCliEntry->CfgSsidLen);
+ pApCliEntry->Valid = FALSE;/* it should be set when successfuley association*/
+ } else
+ {
+ NdisZeroMemory(&(pApCliEntry->CfgSsid), MAX_LEN_OF_SSID);
+ continue;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("ApCliEntry[%d].CfgSsidLen=%d, CfgSsid=%s\n", i, pApCliEntry->CfgSsidLen, pApCliEntry->CfgSsid));
+ }
+ }
+
+ /*ApCliBssid*/
+ if(RTMPGetKeyParameter("ApCliBssid", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE))
+ {
+ for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++)
+ {
+ pApCliEntry = &pAd->ApCfg.ApCliTab[i];
+
+ if(strlen(macptr) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17*/
+ continue;
+ if(strcmp(macptr,"00:00:00:00:00:00") == 0)
+ continue;
+ for (j=0; j<ETH_LENGTH_OF_ADDRESS; j++)
+ {
+ AtoH(macptr, &macAddress[j], 1);
+ macptr=macptr+3;
+ }
+ memcpy(pApCliEntry->CfgApCliBssid, &macAddress, ETH_LENGTH_OF_ADDRESS);
+ pApCliEntry->Valid = FALSE;/* it should be set when successfuley association*/
+ }
+ }
+
+ /*ApCliAuthMode*/
+ if (RTMPGetKeyParameter("ApCliAuthMode", tmpbuf, 255, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++)
+ {
+ pApCliEntry = &pAd->ApCfg.ApCliTab[i];
+
+ if ((strncmp(macptr, "WEPAUTO", 7) == 0) || (strncmp(macptr, "wepauto", 7) == 0))
+ pApCliEntry->AuthMode = Ndis802_11AuthModeAutoSwitch;
+ else if ((strncmp(macptr, "SHARED", 6) == 0) || (strncmp(macptr, "shared", 6) == 0))
+ pApCliEntry->AuthMode = Ndis802_11AuthModeShared;
+ else if ((strncmp(macptr, "WPAPSK", 6) == 0) || (strncmp(macptr, "wpapsk", 6) == 0))
+ pApCliEntry->AuthMode = Ndis802_11AuthModeWPAPSK;
+ else if ((strncmp(macptr, "WPA2PSK", 7) == 0) || (strncmp(macptr, "wpa2psk", 7) == 0))
+ pApCliEntry->AuthMode = Ndis802_11AuthModeWPA2PSK;
+ else
+ pApCliEntry->AuthMode = Ndis802_11AuthModeOpen;
+
+ /*pApCliEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;*/
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) ApCli_AuthMode=%d \n", i, pApCliEntry->AuthMode));
+ RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (i + MIN_NET_DEVICE_FOR_APCLI));
+ }
+
+ }
+
+ /*ApCliEncrypType*/
+ if (RTMPGetKeyParameter("ApCliEncrypType", tmpbuf, 255, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++)
+ {
+ pApCliEntry = &pAd->ApCfg.ApCliTab[i];
+
+ pApCliEntry->WepStatus = Ndis802_11WEPDisabled;
+ if ((strncmp(macptr, "WEP", 3) == 0) || (strncmp(macptr, "wep", 3) == 0))
+ {
+ if (pApCliEntry->AuthMode < Ndis802_11AuthModeWPA)
+ pApCliEntry->WepStatus = Ndis802_11WEPEnabled;
+ }
+ else if ((strncmp(macptr, "TKIP", 4) == 0) || (strncmp(macptr, "tkip", 4) == 0))
+ {
+ if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA)
+ pApCliEntry->WepStatus = Ndis802_11Encryption2Enabled;
+ }
+ else if ((strncmp(macptr, "AES", 3) == 0) || (strncmp(macptr, "aes", 3) == 0))
+ {
+ if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA)
+ pApCliEntry->WepStatus = Ndis802_11Encryption3Enabled;
+ }
+ else
+ {
+ pApCliEntry->WepStatus = Ndis802_11WEPDisabled;
+ }
+
+ pApCliEntry->PairCipher = pApCliEntry->WepStatus;
+ pApCliEntry->GroupCipher = pApCliEntry->WepStatus;
+ pApCliEntry->bMixCipher = FALSE;
+
+ /*pApCliEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;*/
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) APCli_EncrypType = %d \n", i, pApCliEntry->WepStatus));
+ RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (i + MIN_NET_DEVICE_FOR_APCLI));
+ }
+
+ }
+
+ /*ApCliWPAPSK*/
+ if (RTMPGetKeyParameter("ApCliWPAPSK", tmpbuf, 255, buffer, FALSE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++)
+ {
+ int retval = TRUE;
+
+ pApCliEntry = &pAd->ApCfg.ApCliTab[i];
+
+ if((strlen(macptr) < 8) || (strlen(macptr) > 64))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("APCli_WPAPSK_KEY, key string required 8 ~ 64 characters!!!\n"));
+ continue;
+ }
+
+ NdisMoveMemory(pApCliEntry->PSK, macptr, strlen(macptr));
+ pApCliEntry->PSKLen = strlen(macptr);
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) APCli_WPAPSK_KEY=%s, Len=%d\n", i, pApCliEntry->PSK, pApCliEntry->PSKLen));
+
+ if ((pApCliEntry->AuthMode != Ndis802_11AuthModeWPAPSK) &&
+ (pApCliEntry->AuthMode != Ndis802_11AuthModeWPA2PSK))
+ {
+ retval = FALSE;
+ }
+
+ {
+ retval = RT_CfgSetWPAPSKKey(pAd, macptr, strlen(macptr), (PUCHAR)pApCliEntry->CfgSsid, (INT)pApCliEntry->CfgSsidLen, pApCliEntry->PMK);
+ }
+ if (retval == TRUE)
+ {
+ /* Start STA supplicant WPA state machine*/
+ DBGPRINT(RT_DEBUG_TRACE, ("Start AP-client WPAPSK state machine \n"));
+ /*pApCliEntry->WpaState = SS_START; */
+ }
+
+ /*RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (i + MIN_NET_DEVICE_FOR_APCLI)); */
+#ifdef DBG
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) PMK Material => \n", i));
+
+ for (j = 0; j < 32; j++)
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("%02x:", pApCliEntry->PMK[j]));
+ if ((j%16) == 15)
+ DBGPRINT(RT_DEBUG_OFF, ("\n"));
+ }
+ DBGPRINT(RT_DEBUG_OFF,("\n"));
+#endif
+ }
+ }
+
+ /*ApCliDefaultKeyID*/
+ if (RTMPGetKeyParameter("ApCliDefaultKeyID", tmpbuf, 255, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++)
+ {
+ pApCliEntry = &pAd->ApCfg.ApCliTab[i];
+
+ KeyIdx = simple_strtol(macptr, 0, 10);
+ if((KeyIdx >= 1 ) && (KeyIdx <= 4))
+ pApCliEntry->DefaultKeyId = (UCHAR) (KeyIdx - 1);
+ else
+ pApCliEntry->DefaultKeyId = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) DefaultKeyID(0~3)=%d\n", i, pApCliEntry->DefaultKeyId));
+ }
+ }
+
+ /*ApCliKeyXType, ApCliKeyXStr*/
+ for (idx=0; idx<4; idx++)
+ {
+ snprintf(tok_str, sizeof(tok_str), "ApCliKey%dType", idx+1);
+ /*ApCliKey1Type*/
+ if(RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++)
+ {
+ KeyType[i] = simple_strtol(macptr, 0, 10);
+ }
+
+ snprintf(tok_str, sizeof(tok_str), "ApCliKey%dStr", idx+1);
+ /*ApCliKey1Str*/
+ if(RTMPGetKeyParameter(tok_str, tmpbuf, 512, buffer, FALSE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++)
+ {
+ pApCliEntry = &pAd->ApCfg.ApCliTab[i];
+ KeyLen = strlen(macptr);
+ if(((KeyType[i] == 0) && (KeyLen != 10) && (KeyLen != 26)) ||
+ ((KeyType[i] != 0) && (KeyLen != 5) && (KeyLen != 13)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("I/F(apcli%d) Key%dStr is Invalid key length!\n", i, idx+1));
+ }
+ else
+ {
+ if (RT_CfgSetWepKey(pAd, macptr, &pApCliEntry->SharedKey[idx], idx) != TRUE)
+ DBGPRINT(RT_DEBUG_ERROR, ("RT_CfgSetWepKey fail!\n"));
+ }
+ }
+ }
+ }
+ }
+
+ /* ApCliTxMode*/
+ if (RTMPGetKeyParameter("ApCliTxMode", tmpbuf, 25, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++)
+ {
+ pApCliEntry = &pAd->ApCfg.ApCliTab[i];
+
+ pApCliEntry->DesiredTransmitSetting.field.FixedTxMode =
+ RT_CfgSetFixedTxPhyMode(macptr);
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Tx Mode = %d\n", i,
+ pApCliEntry->DesiredTransmitSetting.field.FixedTxMode));
+ }
+ }
+
+ /* ApCliTxMcs*/
+ if (RTMPGetKeyParameter("ApCliTxMcs", tmpbuf, 50, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++)
+ {
+ pApCliEntry = &pAd->ApCfg.ApCliTab[i];
+
+ pApCliEntry->DesiredTransmitSetting.field.MCS =
+ RT_CfgSetTxMCSProc(macptr, &pApCliEntry->bAutoTxRateSwitch);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Tx MCS = %s(%d)\n", i,
+ (pApCliEntry->DesiredTransmitSetting.field.MCS == MCS_AUTO ? "AUTO" : ""),
+ pApCliEntry->DesiredTransmitSetting.field.MCS));
+ }
+ }
+
+
+#ifdef WSC_AP_SUPPORT
+
+ /* Wsc4digitPinCode = TRUE use 4-digit Pin code, otherwise 8-digit Pin code */
+ if (RTMPGetKeyParameter("ApCli_Wsc4digitPinCode", tmpbuf, 32, buffer, TRUE))
+ {
+ if (simple_strtol(macptr, 0, 10) != 0) //Enable
+ pAd->ApCfg.ApCliTab[0].WscControl.WscEnrollee4digitPinCode = TRUE;
+ else //Disable
+ pAd->ApCfg.ApCliTab[0].WscControl.WscEnrollee4digitPinCode = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) ApCli_Wsc4digitPinCode=%d\n", i, pAd->ApCfg.ApCliTab[0].WscControl.WscEnrollee4digitPinCode));
+ }
+#endif /* WSC_AP_SUPPORT */
+
+
+#ifdef UAPSD_SUPPORT
+ /*APSDCapable*/
+ if(RTMPGetKeyParameter("ApCliAPSDCapable", tmpbuf, 10, buffer, TRUE))
+ {
+ pAd->ApCfg.FlgApCliIsUapsdInfoUpdated = TRUE;
+
+ for (i = 0, macptr = rstrtok(tmpbuf,";");
+ (macptr && i < MAX_APCLI_NUM);
+ macptr = rstrtok(NULL,";"), i++)
+ {
+ pApCliEntry = &pAd->ApCfg.ApCliTab[i];
+
+ pApCliEntry->UapsdInfo.bAPSDCapable = \
+ (UCHAR) simple_strtol(macptr, 0, 10);
+ DBGPRINT(RT_DEBUG_ERROR, ("ApCliAPSDCapable[%d]=%d\n", i,
+ pApCliEntry->UapsdInfo.bAPSDCapable));
+ }
+ }
+#endif /* UAPSD_SUPPORT */
+}
+#endif /* APCLI_SUPPORT */
+
+
+static void rtmp_read_acl_parms_from_file(IN PRTMP_ADAPTER pAd, PSTRING tmpbuf, PSTRING buffer)
+{
+ STRING tok_str[32];
+ PSTRING macptr;
+ INT i=0, j=0, idx;
+ UCHAR macAddress[MAC_ADDR_LEN];
+
+
+ memset(macAddress, 0, MAC_ADDR_LEN);
+ for (idx=0; idx<MAX_MBSSID_NUM(pAd); idx++)
+ {
+ memset(&pAd->ApCfg.MBSSID[idx].AccessControlList, 0, sizeof(RT_802_11_ACL));
+ /* AccessPolicyX*/
+ snprintf(tok_str, sizeof(tok_str), "AccessPolicy%d", idx);
+ if (RTMPGetKeyParameter(tok_str, tmpbuf, 10, buffer, TRUE))
+ {
+ switch (simple_strtol(tmpbuf, 0, 10))
+ {
+ case 1: /* Allow All, and the AccessControlList is positive now.*/
+ pAd->ApCfg.MBSSID[idx].AccessControlList.Policy = 1;
+ break;
+ case 2: /* Reject All, and the AccessControlList is negative now.*/
+ pAd->ApCfg.MBSSID[idx].AccessControlList.Policy = 2;
+ break;
+ case 0: /* Disable, don't care the AccessControlList.*/
+ default:
+ pAd->ApCfg.MBSSID[idx].AccessControlList.Policy = 0;
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("%s=%ld\n", tok_str, pAd->ApCfg.MBSSID[idx].AccessControlList.Policy));
+ }
+ /* AccessControlListX*/
+ snprintf(tok_str, sizeof(tok_str), "AccessControlList%d", idx);
+ if (RTMPGetKeyParameter(tok_str, tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE))
+ {
+ for (i=0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (strlen(macptr) != 17) /* Mac address acceptable format 01:02:03:04:05:06 length 17*/
+ continue;
+
+ ASSERT(pAd->ApCfg.MBSSID[idx].AccessControlList.Num <= MAX_NUM_OF_ACL_LIST);
+
+ for (j=0; j<ETH_LENGTH_OF_ADDRESS; j++)
+ {
+ AtoH(macptr, &macAddress[j], 1);
+ macptr=macptr+3;
+ }
+
+ if (pAd->ApCfg.MBSSID[idx].AccessControlList.Num == MAX_NUM_OF_ACL_LIST)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("The AccessControlList is full, and no more entry can join the list!\n"));
+ DBGPRINT(RT_DEBUG_WARN, ("The last entry of ACL is %02x:%02x:%02x:%02x:%02x:%02x\n",
+ macAddress[0],macAddress[1],macAddress[2],macAddress[3],macAddress[4],macAddress[5]));
+
+ break;
+ }
+
+ pAd->ApCfg.MBSSID[idx].AccessControlList.Num++;
+ NdisMoveMemory(pAd->ApCfg.MBSSID[idx].AccessControlList.Entry[(pAd->ApCfg.MBSSID[idx].AccessControlList.Num - 1)].Addr, macAddress, ETH_LENGTH_OF_ADDRESS);
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("%s=Get %ld Mac Address\n", tok_str, pAd->ApCfg.MBSSID[idx].AccessControlList.Num));
+ }
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ In kernel mode read parameters from file
+
+ Arguments:
+ src the location of the file.
+ dest put the parameters to the destination.
+ Length size to read.
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+static void rtmp_read_ap_wmm_parms_from_file(IN PRTMP_ADAPTER pAd, PSTRING tmpbuf, PSTRING buffer)
+{
+ PSTRING macptr;
+ INT i=0;
+
+ /*WmmCapable*/
+ if(RTMPGetKeyParameter("WmmCapable", tmpbuf, 32, buffer, TRUE))
+ {
+ BOOLEAN bEnableWmm = FALSE;
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i >= pAd->ApCfg.BssidNum)
+ {
+ break;
+ }
+
+ if(simple_strtol(macptr, 0, 10) != 0)
+ {
+ pAd->ApCfg.MBSSID[i].bWmmCapable = TRUE;
+ bEnableWmm = TRUE;
+ }
+ else
+ {
+ pAd->ApCfg.MBSSID[i].bWmmCapable = FALSE;
+ }
+
+ if (bEnableWmm)
+ {
+ pAd->CommonCfg.APEdcaParm.bValid = TRUE;
+ pAd->ApCfg.BssEdcaParm.bValid = TRUE;
+ }
+ else
+ {
+ pAd->CommonCfg.APEdcaParm.bValid = FALSE;
+ pAd->ApCfg.BssEdcaParm.bValid = FALSE;
+ }
+
+ pAd->ApCfg.MBSSID[i].bWmmCapableOrg = \
+ pAd->ApCfg.MBSSID[i].bWmmCapable;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WmmCapable=%d\n", i, pAd->ApCfg.MBSSID[i].bWmmCapable));
+ }
+ }
+ /*DLSCapable*/
+ if(RTMPGetKeyParameter("DLSCapable", tmpbuf, 32, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i >= pAd->ApCfg.BssidNum)
+ {
+ break;
+ }
+
+ if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/
+ {
+ pAd->ApCfg.MBSSID[i].bDLSCapable = TRUE;
+ }
+ else /*Disable*/
+ {
+ pAd->ApCfg.MBSSID[i].bDLSCapable = FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) DLSCapable=%d\n", i, pAd->ApCfg.MBSSID[i].bDLSCapable));
+ }
+ }
+ /*APAifsn*/
+ if(RTMPGetKeyParameter("APAifsn", tmpbuf, 32, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->CommonCfg.APEdcaParm.Aifsn[i] = (UCHAR) simple_strtol(macptr, 0, 10);;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("APAifsn[%d]=%d\n", i, pAd->CommonCfg.APEdcaParm.Aifsn[i]));
+ }
+ }
+ /*APCwmin*/
+ if(RTMPGetKeyParameter("APCwmin", tmpbuf, 32, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->CommonCfg.APEdcaParm.Cwmin[i] = (UCHAR) simple_strtol(macptr, 0, 10);;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("APCwmin[%d]=%d\n", i, pAd->CommonCfg.APEdcaParm.Cwmin[i]));
+ }
+ }
+ /*APCwmax*/
+ if(RTMPGetKeyParameter("APCwmax", tmpbuf, 32, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->CommonCfg.APEdcaParm.Cwmax[i] = (UCHAR) simple_strtol(macptr, 0, 10);;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("APCwmax[%d]=%d\n", i, pAd->CommonCfg.APEdcaParm.Cwmax[i]));
+ }
+ }
+ /*APTxop*/
+ if(RTMPGetKeyParameter("APTxop", tmpbuf, 32, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->CommonCfg.APEdcaParm.Txop[i] = (USHORT) simple_strtol(macptr, 0, 10);;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("APTxop[%d]=%d\n", i, pAd->CommonCfg.APEdcaParm.Txop[i]));
+ }
+ }
+ /*APACM*/
+ if(RTMPGetKeyParameter("APACM", tmpbuf, 32, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->CommonCfg.APEdcaParm.bACM[i] = (BOOLEAN) simple_strtol(macptr, 0, 10);;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("APACM[%d]=%d\n", i, pAd->CommonCfg.APEdcaParm.bACM[i]));
+ }
+ }
+ /*BSSAifsn*/
+ if(RTMPGetKeyParameter("BSSAifsn", tmpbuf, 32, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->ApCfg.BssEdcaParm.Aifsn[i] = (UCHAR) simple_strtol(macptr, 0, 10);;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BSSAifsn[%d]=%d\n", i, pAd->ApCfg.BssEdcaParm.Aifsn[i]));
+ }
+ }
+ /*BSSCwmin*/
+ if(RTMPGetKeyParameter("BSSCwmin", tmpbuf, 32, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->ApCfg.BssEdcaParm.Cwmin[i] = (UCHAR) simple_strtol(macptr, 0, 10);;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BSSCwmin[%d]=%d\n", i, pAd->ApCfg.BssEdcaParm.Cwmin[i]));
+ }
+ }
+ /*BSSCwmax*/
+ if(RTMPGetKeyParameter("BSSCwmax", tmpbuf, 32, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->ApCfg.BssEdcaParm.Cwmax[i] = (UCHAR) simple_strtol(macptr, 0, 10);;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BSSCwmax[%d]=%d\n", i, pAd->ApCfg.BssEdcaParm.Cwmax[i]));
+ }
+ }
+ /*BSSTxop*/
+ if(RTMPGetKeyParameter("BSSTxop", tmpbuf, 32, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->ApCfg.BssEdcaParm.Txop[i] = (USHORT) simple_strtol(macptr, 0, 10);;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BSSTxop[%d]=%d\n", i, pAd->ApCfg.BssEdcaParm.Txop[i]));
+ }
+ }
+ /*BSSACM*/
+ if(RTMPGetKeyParameter("BSSACM", tmpbuf, 32, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->ApCfg.BssEdcaParm.bACM[i] = (BOOLEAN) simple_strtol(macptr, 0, 10);;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BSSACM[%d]=%d\n", i, pAd->ApCfg.BssEdcaParm.bACM[i]));
+ }
+ }
+ /*AckPolicy*/
+ if(RTMPGetKeyParameter("AckPolicy", tmpbuf, 32, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->CommonCfg.AckPolicy[i] = (UCHAR) simple_strtol(macptr, 0, 10);;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AckPolicy[%d]=%d\n", i, pAd->CommonCfg.AckPolicy[i]));
+ }
+ }
+#ifdef UAPSD_SUPPORT
+ /*APSDCapable*/
+ if(RTMPGetKeyParameter("APSDCapable", tmpbuf, 10, buffer, TRUE))
+ {
+
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i < HW_BEACON_MAX_NUM)
+ {
+ pAd->ApCfg.MBSSID[i].UapsdInfo.bAPSDCapable = \
+ (UCHAR) simple_strtol(macptr, 0, 10);
+ DBGPRINT(RT_DEBUG_ERROR, ("APSDCapable[%d]=%d\n", i,
+ pAd->ApCfg.MBSSID[i].UapsdInfo.bAPSDCapable));
+ }
+ }
+
+ if (i == 1)
+ {
+ /*
+ Old format in UAPSD settings: only 1 parameter
+ i.e. UAPSD for all BSS is enabled or disabled.
+ */
+ for(i=1; i<HW_BEACON_MAX_NUM; i++)
+ {
+ pAd->ApCfg.MBSSID[i].UapsdInfo.bAPSDCapable =
+ pAd->ApCfg.MBSSID[0].UapsdInfo.bAPSDCapable;
+ DBGPRINT(RT_DEBUG_ERROR, ("APSDCapable[%d]=%d\n", i,
+ pAd->ApCfg.MBSSID[i].UapsdInfo.bAPSDCapable));
+ }
+ }
+
+#ifdef APCLI_SUPPORT
+ if (pAd->ApCfg.FlgApCliIsUapsdInfoUpdated == FALSE)
+ {
+ /*
+ Backward:
+ All UAPSD for AP Client interface is same as MBSS0
+ when we can not find "ApCliAPSDCapable".
+ When we find "ApCliAPSDCapable" hereafter, we will over-write.
+ */
+ for(i=0; i<MAX_APCLI_NUM; i++)
+ {
+ pAd->ApCfg.ApCliTab[i].UapsdInfo.bAPSDCapable = \
+ pAd->ApCfg.MBSSID[0].UapsdInfo.bAPSDCapable;
+ DBGPRINT(RT_DEBUG_ERROR, ("default ApCliAPSDCapable[%d]=%d\n",
+ i, pAd->ApCfg.ApCliTab[i].UapsdInfo.bAPSDCapable));
+ }
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* UAPSD_SUPPORT */
+}
+
+#ifdef DOT1X_SUPPORT
+/*
+ ========================================================================
+
+ Routine Description:
+ In kernel mode read parameters from file
+
+ Arguments:
+ src the location of the file.
+ dest put the parameters to the destination.
+ Length size to read.
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+static void rtmp_read_radius_parms_from_file(IN PRTMP_ADAPTER pAd, PSTRING tmpbuf, PSTRING buffer)
+{
+ STRING tok_str[16];
+ PSTRING macptr;
+ UINT32 ip_addr;
+ INT i=0;
+ BOOLEAN bUsePrevFormat = FALSE;
+ USHORT offset;
+ INT count[HW_BEACON_MAX_NUM];
+
+ /* own_ip_addr*/
+ if (RTMPGetKeyParameter("own_ip_addr", tmpbuf, 32, buffer, TRUE))
+ {
+ Set_OwnIPAddr_Proc(pAd, tmpbuf);
+ }
+
+
+ /* session_timeout_interval*/
+ if (RTMPGetKeyParameter("session_timeout_interval", tmpbuf, 32, buffer, TRUE))
+ {
+ pAd->ApCfg.session_timeout_interval = simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("session_timeout_interval=%d\n", pAd->ApCfg.session_timeout_interval));
+ }
+
+ /* quiet_interval*/
+ if (RTMPGetKeyParameter("quiet_interval", tmpbuf, 32, buffer, TRUE))
+ {
+ pAd->ApCfg.quiet_interval = simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("quiet_interval=%d\n", pAd->ApCfg.quiet_interval));
+ }
+
+ /* EAPifname*/
+ if (RTMPGetKeyParameter("EAPifname", tmpbuf, 256, buffer, TRUE))
+ {
+ Set_EAPIfName_Proc(pAd, tmpbuf);
+ }
+
+ /* PreAuthifname*/
+ if (RTMPGetKeyParameter("PreAuthifname", tmpbuf, 256, buffer, TRUE))
+ {
+ Set_PreAuthIfName_Proc(pAd, tmpbuf);
+ }
+
+ /*PreAuth*/
+ if(RTMPGetKeyParameter("PreAuth", tmpbuf, 10, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/
+ pAd->ApCfg.MBSSID[i].PreAuth = TRUE;
+ else /*Disable*/
+ pAd->ApCfg.MBSSID[i].PreAuth = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) PreAuth=%d\n", i, pAd->ApCfg.MBSSID[i].PreAuth));
+ }
+ }
+
+ /*IEEE8021X*/
+ if(RTMPGetKeyParameter("IEEE8021X", tmpbuf, 10, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/
+ pAd->ApCfg.MBSSID[i].IEEE8021X = TRUE;
+ else /*Disable*/
+ pAd->ApCfg.MBSSID[i].IEEE8021X = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), IEEE8021X=%d\n", i, pAd->ApCfg.MBSSID[i].IEEE8021X));
+ }
+ }
+
+ /* RADIUS_Server*/
+ offset = 0;
+ /*if (RTMPGetKeyParameter("RADIUS_Server", tmpbuf, 256, buffer, TRUE))*/
+ while (RTMPGetKeyParameterWithOffset("RADIUS_Server", tmpbuf, &offset, 256, buffer, TRUE))
+ {
+ for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_MBSSID_NUM(pAd)); macptr = rstrtok(NULL,";"), i++)
+ {
+ if (rtinet_aton(macptr, &ip_addr) && pAd->ApCfg.MBSSID[i].radius_srv_num < MAX_RADIUS_SRV_NUM)
+ {
+ INT srv_idx = pAd->ApCfg.MBSSID[i].radius_srv_num;
+
+ pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_ip = ip_addr;
+ pAd->ApCfg.MBSSID[i].radius_srv_num++;
+ DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), radius_ip(seq-%d)=%s(%x)\n", i, pAd->ApCfg.MBSSID[i].radius_srv_num, macptr, pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_ip));
+ }
+ }
+ }
+ /* RADIUS_Port*/
+ /*if (RTMPGetKeyParameter("RADIUS_Port", tmpbuf, 128, buffer, TRUE))*/
+ offset = 0;
+ memset(&count[0], 0, sizeof(count));
+ while (RTMPGetKeyParameterWithOffset("RADIUS_Port", tmpbuf, &offset, 128, buffer, TRUE))
+ {
+ for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_MBSSID_NUM(pAd)); macptr = rstrtok(NULL,";"), i++)
+ {
+ if (count[i] < pAd->ApCfg.MBSSID[i].radius_srv_num)
+ {
+ INT srv_idx = count[i];
+
+ pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_port = (UINT32) simple_strtol(macptr, 0, 10);
+ count[i] ++;
+ DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), radius_port(seq-%d)=%d\n", i, count[i], pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_port));
+ }
+ }
+ }
+ /* RADIUS_Key*/
+ /*if (RTMPGetKeyParameter("RADIUS_Key", tmpbuf, 640, buffer, FALSE))*/
+ offset = 0;
+ memset(&count[0], 0, sizeof(count));
+ while (RTMPGetKeyParameterWithOffset("RADIUS_Key", tmpbuf, &offset, 640, buffer, FALSE))
+ {
+ if (strlen(tmpbuf) > 0)
+ bUsePrevFormat = TRUE;
+
+ for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_MBSSID_NUM(pAd)); macptr = rstrtok(NULL,";"), i++)
+ {
+ if (strlen(macptr) > 0 && (count[i] < pAd->ApCfg.MBSSID[i].radius_srv_num))
+ {
+ INT srv_idx = count[i];
+
+ pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key_len = strlen(macptr);
+ NdisMoveMemory(pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key, macptr, strlen(macptr));
+ count[i] ++;
+ DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), radius_key(seq-%d)=%s, len=%d\n", i,
+ count[i],
+ pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key,
+ pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key_len));
+ }
+ }
+ }
+
+ /* NasIdX, X indicate the interface index(1~8) */
+ for (i = 0; i < pAd->ApCfg.BssidNum; i++)
+ {
+ snprintf(tok_str, sizeof(tok_str), "NasId%d", i + 1);
+ if (RTMPGetKeyParameter(tok_str, tmpbuf, 33, buffer, FALSE))
+ {
+ if (strlen(tmpbuf) > 0)
+ {
+ pAd->ApCfg.MBSSID[i].NasIdLen = strlen(tmpbuf);
+ NdisMoveMemory(pAd->ApCfg.MBSSID[i].NasId, tmpbuf, strlen(tmpbuf));
+ DBGPRINT(RT_DEBUG_TRACE, ("IF-ra%d NAS-ID=%s, len=%d\n", i,
+ pAd->ApCfg.MBSSID[i].NasId,
+ pAd->ApCfg.MBSSID[i].NasIdLen));
+ }
+ }
+ }
+
+ if (!bUsePrevFormat)
+ {
+ for (i = 0; i < MAX_MBSSID_NUM(pAd); i++)
+ {
+ INT srv_idx = 0;
+
+ snprintf(tok_str, sizeof(tok_str), "RADIUS_Key%d", i + 1);
+
+ /* RADIUS_KeyX (X=1~MAX_MBSSID_NUM)*/
+ /*if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE)) */
+ offset = 0;
+ while (RTMPGetKeyParameterWithOffset(tok_str, tmpbuf, &offset, 128, buffer, FALSE))
+ {
+ if (strlen(tmpbuf) > 0 && (srv_idx < pAd->ApCfg.MBSSID[i].radius_srv_num))
+ {
+ pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key_len = strlen(tmpbuf);
+ NdisMoveMemory(pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key, tmpbuf, strlen(tmpbuf));
+ DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), update radius_key(seq-%d)=%s, len=%d\n", i, srv_idx+1,
+ pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key,
+ pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key_len));
+ srv_idx ++;
+ }
+ }
+ }
+ }
+}
+#endif /* DOT1X_SUPPORT */
+
+static int rtmp_parse_wpapsk_buffer_from_file(IN PRTMP_ADAPTER pAd,IN PSTRING buffer,IN INT BSSIdx)
+{
+ PSTRING tmpbuf = buffer;
+ INT i = BSSIdx;
+ /*UCHAR keyMaterial[40];*/
+ ULONG len = strlen(tmpbuf);
+ int ret = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WPAPSK_KEY=%s\n", i, tmpbuf));
+
+ ret = RT_CfgSetWPAPSKKey(pAd, tmpbuf, len, (PUCHAR)pAd->ApCfg.MBSSID[i].Ssid, pAd->ApCfg.MBSSID[i].SsidLen, pAd->ApCfg.MBSSID[i].PMK);
+ if (ret == FALSE)
+ return FALSE;
+
+#ifdef WSC_AP_SUPPORT
+ NdisZeroMemory(pAd->ApCfg.MBSSID[i].WscControl.WpaPsk, 64);
+ pAd->ApCfg.MBSSID[i].WscControl.WpaPskLen = 0;
+ if ((len >= 8) && (len <= 64))
+ {
+ NdisMoveMemory(pAd->ApCfg.MBSSID[i].WscControl.WpaPsk, tmpbuf, len);
+ pAd->ApCfg.MBSSID[i].WscControl.WpaPskLen = len;
+ }
+#endif /* WSC_AP_SUPPORT */
+ return ret;
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+
+#ifdef DOT11_VHT_AC
+static void VHTParametersHook(
+ IN RTMP_ADAPTER *pAd,
+ IN PSTRING pValueStr,
+ IN PSTRING pInput)
+{
+ long Value;
+
+ /* Channel Width */
+ if (RTMPGetKeyParameter("VHT_BW", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+
+ if (Value == VHT_BW_80)
+ pAd->CommonCfg.vht_bw = VHT_BW_80;
+ else
+ pAd->CommonCfg.vht_bw = VHT_BW_2040;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("VHT: Channel Width = %s\n", (Value==VHT_BW_80) ? "80 MHz" : "20/40 MHz" ));
+ }
+}
+
+#endif /* DOT11_VHT_AC */
+
+#ifdef CUSTOMER_DEMO
+void demo_mode_cfg(RTMP_ADAPTER *pAd)
+{
+ int IdBss, i;
+ UCHAR cfg_mode;
+
+ pAd->CommonCfg.Channel = 40;
+ for (i = 0; i < pAd->ApCfg.BssidNum; i++)
+ {
+ cfg_mode = 14;
+ pAd->ApCfg.MBSSID[i].PhyMode = cfgmode_2_wmode(cfg_mode);
+ DBGPRINT(RT_DEBUG_TRACE, ("BSS%d PhyMode=%d\n", i, pAd->ApCfg.MBSSID[i].PhyMode));
+
+ if (i == 0)
+ {
+ /* for first time, update all phy mode is same as ra0 */
+ for(IdBss=1; IdBss<pAd->ApCfg.BssidNum; IdBss++)
+ pAd->ApCfg.MBSSID[IdBss].PhyMode = pAd->ApCfg.MBSSID[0].PhyMode;
+ /* set mode for 1st time */
+ RT_CfgSetWirelessMode(pAd, "14");
+ }
+ else
+ RT_CfgSetMbssWirelessMode(pAd, "14");
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("PhyMode=%d\n", pAd->CommonCfg.PhyMode));
+
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+ pAd->CommonCfg.vht_bw = VHT_BW_80;
+}
+#endif /* CUSTOMER_DEMO */
+
+
+#ifdef DOT11_N_SUPPORT
+static void HTParametersHook(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING pValueStr,
+ IN PSTRING pInput)
+{
+ long Value;
+#ifdef CONFIG_AP_SUPPORT
+ INT i=0;
+ PSTRING Bufptr;
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (RTMPGetKeyParameter("HT_PROTECT", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.bHTProtect = FALSE;
+ }
+ else
+ {
+ pAd->CommonCfg.bHTProtect = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Protection = %s\n", (Value==0) ? "Disable" : "Enable"));
+ }
+
+
+ if (RTMPGetKeyParameter("HT_MIMOPSMode", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value > MMPS_ENABLE)
+ {
+ pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE;
+ }
+ else
+ {
+ /*TODO: add mimo power saving mechanism*/
+ pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE;
+ /*pAd->CommonCfg.BACapability.field.MMPSmode = Value;*/
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPS Mode = %d\n", (INT) Value));
+ }
+
+ if (RTMPGetKeyParameter("HT_BADecline", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.bBADecline = FALSE;
+ }
+ else
+ {
+ pAd->CommonCfg.bBADecline = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Decline = %s\n", (Value==0) ? "Disable" : "Enable"));
+ }
+
+
+ if (RTMPGetKeyParameter("HT_AutoBA", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.BACapability.field.AutoBA = FALSE;
+ pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE;
+ }
+ else
+ {
+ pAd->CommonCfg.BACapability.field.AutoBA = TRUE;
+ pAd->CommonCfg.BACapability.field.Policy = IMMED_BA;
+ }
+ pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA;
+ pAd->CommonCfg.REGBACapability.field.Policy = pAd->CommonCfg.BACapability.field.Policy;
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Auto BA = %s\n", (Value==0) ? "Disable" : "Enable"));
+ }
+
+ /* Tx_+HTC frame*/
+ if (RTMPGetKeyParameter("HT_HTC", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->HTCEnable = FALSE;
+ }
+ else
+ {
+ pAd->HTCEnable = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx +HTC frame = %s\n", (Value==0) ? "Disable" : "Enable"));
+ }
+
+
+ /* Reverse Direction Mechanism*/
+ if (RTMPGetKeyParameter("HT_RDG", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.bRdg = FALSE;
+ }
+ else
+ {
+ pAd->HTCEnable = TRUE;
+ pAd->CommonCfg.bRdg = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: RDG = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)"));
+ }
+
+
+
+
+ /* Tx A-MSUD ?*/
+ if (RTMPGetKeyParameter("HT_AMSDU", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE;
+ }
+ else
+ {
+ pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx A-MSDU = %s\n", (Value==0) ? "Disable" : "Enable"));
+ }
+
+ /* MPDU Density*/
+ if (RTMPGetKeyParameter("HT_MpduDensity", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value <=7 && Value >= 0)
+ {
+ pAd->CommonCfg.BACapability.field.MpduDensity = Value;
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d\n", (INT) Value));
+ }
+ else
+ {
+ pAd->CommonCfg.BACapability.field.MpduDensity = 4;
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d (Default)\n", 4));
+ }
+ }
+
+ /* Max Rx BA Window Size*/
+ if (RTMPGetKeyParameter("HT_BAWinSize", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+
+#ifdef CONFIG_AP_SUPPORT
+ /* Intel IOT*/
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ Value = 64;
+#endif /* CONFIG_AP_SUPPORT */
+ if (Value >=1 && Value <= 64)
+ {
+ pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value;
+ pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value;
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = %d\n", (INT) Value));
+ }
+ else
+ {
+ pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64;
+ pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64;
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = 64 (Defualt)\n"));
+ }
+
+ }
+
+ /* Guard Interval*/
+ if (RTMPGetKeyParameter("HT_GI", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+
+ if (Value == GI_400)
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400;
+ }
+ else
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Guard Interval = %s\n", (Value==GI_400) ? "400" : "800" ));
+ }
+
+ /* HT Operation Mode : Mixed Mode , Green Field*/
+ if (RTMPGetKeyParameter("HT_OpMode", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+
+ if (Value == HTMODE_GF)
+ {
+
+ pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF;
+ }
+ else
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Operate Mode = %s\n", (Value==HTMODE_GF) ? "Green Field" : "Mixed Mode" ));
+ }
+
+ /* Fixed Tx mode : CCK, OFDM*/
+ if (RTMPGetKeyParameter("FixedTxMode", pValueStr, 25, pInput, TRUE))
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ for (i = 0, Bufptr = rstrtok(pValueStr,";"); (Bufptr && i < MAX_MBSSID_NUM(pAd)); Bufptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->ApCfg.MBSSID[i].DesiredTransmitSetting.field.FixedTxMode =
+ RT_CfgSetFixedTxPhyMode(Bufptr);
+ DBGPRINT(RT_DEBUG_TRACE, ("(IF-ra%d) Fixed Tx Mode = %d\n", i,
+ pAd->ApCfg.MBSSID[i].DesiredTransmitSetting.field.FixedTxMode));
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+
+ /* Channel Width */
+ if (RTMPGetKeyParameter("HT_BW", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == BW_40)
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
+ else
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+
+#ifdef MCAST_RATE_SPECIFIC
+ pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.RegTransmitSetting.field.BW;
+#endif /* MCAST_RATE_SPECIFIC */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Channel Width = %s\n", (Value==BW_40) ? "40 MHz" : "20 MHz" ));
+ }
+
+ if (RTMPGetKeyParameter("HT_EXTCHA", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+
+ if (Value == 0)
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+ else
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Ext Channel = %s\n", (Value==0) ? "BELOW" : "ABOVE" ));
+ }
+
+ /* MSC*/
+ if (RTMPGetKeyParameter("HT_MCS", pValueStr, 50, pInput, TRUE))
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ for (i = 0, Bufptr = rstrtok(pValueStr,";"); (Bufptr && i < MAX_MBSSID_NUM(pAd)); Bufptr = rstrtok(NULL,";"), i++)
+ {
+ Value = simple_strtol(Bufptr, 0, 10);
+ if ((Value >= 0 && Value <= 23) || (Value == 32))
+ {
+ pAd->ApCfg.MBSSID[i].DesiredTransmitSetting.field.MCS = Value;
+ }
+ else
+ {
+ pAd->ApCfg.MBSSID[i].DesiredTransmitSetting.field.MCS = MCS_AUTO;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("(IF-ra%d) HT: MCS = %s(%d)\n", i,
+ (pAd->ApCfg.MBSSID[i].DesiredTransmitSetting.field.MCS == MCS_AUTO ? "AUTO" : "Fixed"),
+ pAd->ApCfg.MBSSID[i].DesiredTransmitSetting.field.MCS));
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+
+ /* STBC */
+ if (RTMPGetKeyParameter("HT_STBC", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == STBC_USE)
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE;
+ }
+ else
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: STBC = %d\n", pAd->CommonCfg.RegTransmitSetting.field.STBC));
+ }
+
+ /* 40_Mhz_Intolerant*/
+ if (RTMPGetKeyParameter("HT_40MHZ_INTOLERANT", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.bForty_Mhz_Intolerant = FALSE;
+ }
+ else
+ {
+ pAd->CommonCfg.bForty_Mhz_Intolerant = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: 40MHZ INTOLERANT = %d\n", pAd->CommonCfg.bForty_Mhz_Intolerant));
+ }
+ /*HT_TxStream*/
+ if(RTMPGetKeyParameter("HT_TxStream", pValueStr, 10, pInput, TRUE))
+ {
+ switch (simple_strtol(pValueStr, 0, 10))
+ {
+ case 1:
+ pAd->CommonCfg.TxStream = 1;
+ break;
+ case 2:
+ pAd->CommonCfg.TxStream = 2;
+ break;
+ case 3: /* 3*3*/
+ default:
+ pAd->CommonCfg.TxStream = 3;
+
+ if (pAd->MACVersion < RALINK_2883_VERSION)
+ pAd->CommonCfg.TxStream = 2; /* only 2 tx streams for RT2860 series*/
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx Stream = %d\n", pAd->CommonCfg.TxStream));
+ }
+ /*HT_RxStream*/
+ if(RTMPGetKeyParameter("HT_RxStream", pValueStr, 10, pInput, TRUE))
+ {
+ switch (simple_strtol(pValueStr, 0, 10))
+ {
+ case 1:
+ pAd->CommonCfg.RxStream = 1;
+ break;
+ case 2:
+ pAd->CommonCfg.RxStream = 2;
+ break;
+ case 3:
+ default:
+ pAd->CommonCfg.RxStream = 3;
+
+ if (pAd->MACVersion < RALINK_2883_VERSION)
+ pAd->CommonCfg.RxStream = 2; /* only 2 rx streams for RT2860 series*/
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Rx Stream = %d\n", pAd->CommonCfg.RxStream));
+ }
+#ifdef GREENAP_SUPPORT
+ /*Green AP*/
+ if(RTMPGetKeyParameter("GreenAP", pValueStr, 10, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->ApCfg.bGreenAPEnable = FALSE;
+ }
+ else
+ {
+ pAd->ApCfg.bGreenAPEnable = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Green AP= %d\n", pAd->ApCfg.bGreenAPEnable));
+ }
+#endif /* GREENAP_SUPPORT */
+ /* HT_DisallowTKIP*/
+ if (RTMPGetKeyParameter("HT_DisallowTKIP", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+
+ if (Value == 1)
+ {
+ pAd->CommonCfg.HT_DisallowTKIP = TRUE;
+ }
+ else
+ {
+ pAd->CommonCfg.HT_DisallowTKIP = FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Disallow TKIP mode = %s\n", (pAd->CommonCfg.HT_DisallowTKIP == TRUE) ? "ON" : "OFF" ));
+ }
+
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+ if (RTMPGetKeyParameter("OBSSScanParam", pValueStr, 32, pInput, TRUE))
+ {
+ int ObssScanValue, idx;
+ PSTRING macptr;
+ for (idx = 0, macptr = rstrtok(pValueStr,";"); macptr; macptr = rstrtok(NULL,";"), idx++)
+ {
+ ObssScanValue = simple_strtol(macptr, 0, 10);
+ switch (idx)
+ {
+ case 0:
+ if (ObssScanValue < 5 || ObssScanValue > 1000)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Invalid OBSSScanParam for Dot11OBssScanPassiveDwell(%d), should in range 5~1000\n", ObssScanValue));
+ }
+ else
+ {
+ pAd->CommonCfg.Dot11OBssScanPassiveDwell = ObssScanValue; /* Unit : TU. 5~1000*/
+ DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11OBssScanPassiveDwell=%d\n", ObssScanValue));
+ }
+ break;
+ case 1:
+ if (ObssScanValue < 10 || ObssScanValue > 1000)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Invalid OBSSScanParam for Dot11OBssScanActiveDwell(%d), should in range 10~1000\n", ObssScanValue));
+ }
+ else
+ {
+ pAd->CommonCfg.Dot11OBssScanActiveDwell = ObssScanValue; /* Unit : TU. 10~1000*/
+ DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11OBssScanActiveDwell=%d\n", ObssScanValue));
+ }
+ break;
+ case 2:
+ pAd->CommonCfg.Dot11BssWidthTriggerScanInt = ObssScanValue; /* Unit : Second*/
+ DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11BssWidthTriggerScanInt=%d\n", ObssScanValue));
+ break;
+ case 3:
+ if (ObssScanValue < 200 || ObssScanValue > 10000)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Invalid OBSSScanParam for Dot11OBssScanPassiveTotalPerChannel(%d), should in range 200~10000\n", ObssScanValue));
+ }
+ else
+ {
+ pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = ObssScanValue; /* Unit : TU. 200~10000*/
+ DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11OBssScanPassiveTotalPerChannel=%d\n", ObssScanValue));
+ }
+ break;
+ case 4:
+ if (ObssScanValue < 20 || ObssScanValue > 10000)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Invalid OBSSScanParam for Dot11OBssScanActiveTotalPerChannel(%d), should in range 20~10000\n", ObssScanValue));
+ }
+ else
+ {
+ pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = ObssScanValue; /* Unit : TU. 20~10000*/
+ DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11OBssScanActiveTotalPerChannel=%d\n", ObssScanValue));
+ }
+ break;
+ case 5:
+ pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = ObssScanValue;
+ DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11BssWidthChanTranDelayFactor=%d\n", ObssScanValue));
+ break;
+ case 6:
+ pAd->CommonCfg.Dot11OBssScanActivityThre = ObssScanValue; /* Unit : percentage*/
+ DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11BssWidthChanTranDelayFactor=%d\n", ObssScanValue));
+ break;
+ }
+ }
+
+ if (idx != 7)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Wrong OBSSScanParamtetrs format in dat file!!!!! Use default value.\n"));
+
+ pAd->CommonCfg.Dot11OBssScanPassiveDwell = dot11OBSSScanPassiveDwell; /* Unit : TU. 5~1000*/
+ pAd->CommonCfg.Dot11OBssScanActiveDwell = dot11OBSSScanActiveDwell; /* Unit : TU. 10~1000*/
+ pAd->CommonCfg.Dot11BssWidthTriggerScanInt = dot11BSSWidthTriggerScanInterval; /* Unit : Second */
+ pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = dot11OBSSScanPassiveTotalPerChannel; /* Unit : TU. 200~10000*/
+ pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = dot11OBSSScanActiveTotalPerChannel; /* Unit : TU. 20~10000*/
+ pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = dot11BSSWidthChannelTransactionDelayFactor;
+ pAd->CommonCfg.Dot11OBssScanActivityThre = dot11BSSScanActivityThreshold; /* Unit : percentage*/
+ }
+ pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor);
+ DBGPRINT(RT_DEBUG_TRACE, ("OBSSScanParam for Dot11BssWidthChanTranDelay=%ld\n", pAd->CommonCfg.Dot11BssWidthChanTranDelay));
+ }
+
+ if (RTMPGetKeyParameter("HT_BSSCoexistence", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ pAd->CommonCfg.bBssCoexEnable = ((Value == 1) ? TRUE : FALSE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: 20/40 BssCoexSupport = %s\n", (pAd->CommonCfg.bBssCoexEnable == TRUE) ? "ON" : "OFF" ));
+ }
+
+
+ if (RTMPGetKeyParameter("HT_BSSCoexApCntThr", pValueStr, 25, pInput, TRUE))
+ {
+ pAd->CommonCfg.BssCoexApCntThr = simple_strtol(pValueStr, 0, 10);;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: 20/40 BssCoexApCntThr = %d\n", pAd->CommonCfg.BssCoexApCntThr));
+ }
+
+#endif /* DOT11N_DRAFT3 */
+
+ if (RTMPGetKeyParameter("BurstMode", pValueStr, 25, pInput, TRUE))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ pAd->CommonCfg.bRalinkBurstMode = ((Value == 1) ? 1 : 0);
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: RaBurstMode= %d\n", pAd->CommonCfg.bRalinkBurstMode));
+ }
+#endif /* DOT11_N_SUPPORT */
+
+}
+#endif /* DOT11_N_SUPPORT */
+
+
+
+
+void RTMPSetCountryCode(RTMP_ADAPTER *pAd, PSTRING CountryCode)
+{
+ NdisMoveMemory(pAd->CommonCfg.CountryCode, CountryCode , 2);
+ pAd->CommonCfg.CountryCode[2] = ' ';
+ if (strlen((PSTRING) pAd->CommonCfg.CountryCode) != 0)
+ pAd->CommonCfg.bCountryFlag = TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("CountryCode=%s\n", pAd->CommonCfg.CountryCode));
+}
+
+
+NDIS_STATUS RTMPSetProfileParameters(
+ IN RTMP_ADAPTER *pAd,
+ IN PSTRING pBuffer)
+{
+ PSTRING tmpbuf;
+ ULONG RtsThresh;
+ ULONG FragThresh;
+ PSTRING macptr;
+ INT i = 0, retval;
+
+/* tmpbuf = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);*/
+ os_alloc_mem(NULL, (UCHAR **)&tmpbuf, MAX_PARAM_BUFFER_SIZE);
+ if(tmpbuf == NULL)
+ return NDIS_STATUS_FAILURE;
+
+ do
+ {
+ /* set file parameter to portcfg*/
+ if (RTMPGetKeyParameter("MacAddress", tmpbuf, 25, pBuffer, TRUE))
+ {
+ retval = RT_CfgSetMacAddress(pAd, tmpbuf);
+ if (retval)
+ DBGPRINT(RT_DEBUG_TRACE, ("MacAddress = %02x:%02x:%02x:%02x:%02x:%02x\n",
+ PRINT_MAC(pAd->CurrentAddress)));
+ }
+ /*CountryRegion*/
+ if(RTMPGetKeyParameter("CountryRegion", tmpbuf, 25, pBuffer, TRUE))
+ {
+ retval = RT_CfgSetCountryRegion(pAd, tmpbuf, BAND_24G);
+ DBGPRINT(RT_DEBUG_TRACE, ("CountryRegion=%d\n", pAd->CommonCfg.CountryRegion));
+ }
+ /*CountryRegionABand*/
+ if(RTMPGetKeyParameter("CountryRegionABand", tmpbuf, 25, pBuffer, TRUE))
+ {
+ retval = RT_CfgSetCountryRegion(pAd, tmpbuf, BAND_5G);
+ DBGPRINT(RT_DEBUG_TRACE, ("CountryRegionABand=%d\n", pAd->CommonCfg.CountryRegionForABand));
+ }
+#ifdef RTMP_EFUSE_SUPPORT
+ /*EfuseBufferMode*/
+ if(RTMPGetKeyParameter("EfuseBufferMode", tmpbuf, 25, pBuffer, TRUE))
+ {
+ pAd->bEEPROMFile = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("EfuseBufferMode=%d\n", pAd->bUseEfuse));
+ }
+#endif /* RTMP_EFUSE_SUPPORT */
+ /*CountryCode*/
+
+ if (pAd->CommonCfg.bCountryFlag == 0)
+ {
+ if(RTMPGetKeyParameter("CountryCode", tmpbuf, 25, pBuffer, TRUE))
+ RTMPSetCountryCode(pAd, tmpbuf);
+ }
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+ /*ChannelGeography*/
+ if(RTMPGetKeyParameter("ChannelGeography", tmpbuf, 25, pBuffer, TRUE))
+ {
+ UCHAR Geography = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+ if (Geography <= BOTH)
+ {
+ pAd->CommonCfg.Geography = Geography;
+ pAd->CommonCfg.CountryCode[2] =
+ (pAd->CommonCfg.Geography == BOTH) ? ' ' : ((pAd->CommonCfg.Geography == IDOR) ? 'I' : 'O');
+ DBGPRINT(RT_DEBUG_TRACE, ("ChannelGeography=%d\n", pAd->CommonCfg.Geography));
+ }
+ }
+ else
+ {
+ pAd->CommonCfg.Geography = BOTH;
+ pAd->CommonCfg.CountryCode[2] = ' ';
+ }
+#endif /* EXT_BUILD_CHANNEL_LIST */
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef MBSS_SUPPORT
+ /*BSSIDNum; This must read first of other multiSSID field, so list this field first in configuration file*/
+ if(RTMPGetKeyParameter("BssidNum", tmpbuf, 25, pBuffer, TRUE))
+ {
+ pAd->ApCfg.BssidNum = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+ if(pAd->ApCfg.BssidNum > MAX_MBSSID_NUM(pAd))
+ {
+ pAd->ApCfg.BssidNum = MAX_MBSSID_NUM(pAd);
+ DBGPRINT(RT_DEBUG_TRACE, ("BssidNum=%d(MAX_MBSSID_NUM is %d)\n", pAd->ApCfg.BssidNum,MAX_MBSSID_NUM(pAd)));
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("BssidNum=%d\n", pAd->ApCfg.BssidNum));
+ }
+
+ if (HW_BEACON_OFFSET > (HW_BEACON_MAX_SIZE(pAd) / pAd->ApCfg.BssidNum))
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("mbss> fatal error! beacon offset is error in driver! "
+ "Please re-assign HW_BEACON_OFFSET!\n"));
+ }
+#else
+ pAd->ApCfg.BssidNum = 1;
+#endif /* MBSS_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* SSID*/
+ if (TRUE)
+ {
+ STRING tok_str[16];
+ UCHAR BssidCountSupposed = 0;
+ BOOLEAN bSSIDxIsUsed = FALSE;
+
+ //PRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.BssidNum=%d\n", pAd->ApCfg.BssidNum));
+ for (i = 0; i < pAd->ApCfg.BssidNum; i++)
+ {
+ snprintf(tok_str, sizeof(tok_str), "SSID%d", i + 1);
+ if(RTMPGetKeyParameter(tok_str, tmpbuf, 33, pBuffer, FALSE))
+ {
+ NdisMoveMemory(pAd->ApCfg.MBSSID[i].Ssid, tmpbuf , strlen(tmpbuf));
+ pAd->ApCfg.MBSSID[i].Ssid[strlen(tmpbuf)] = '\0';
+ pAd->ApCfg.MBSSID[i].SsidLen = strlen((PSTRING) pAd->ApCfg.MBSSID[i].Ssid);
+ if (bSSIDxIsUsed == FALSE)
+ {
+ bSSIDxIsUsed = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("SSID[%d]=%s\n", i, pAd->ApCfg.MBSSID[i].Ssid));
+ }
+ }
+ if (bSSIDxIsUsed == FALSE)
+ {
+ if(RTMPGetKeyParameter("SSID", tmpbuf, 256, pBuffer, FALSE))
+ {
+ BssidCountSupposed = delimitcnt(tmpbuf, ";") + 1;
+ if (pAd->ApCfg.BssidNum != BssidCountSupposed)
+ {
+ DBGPRINT_ERR(("Your no. of SSIDs( = %d) does not match your BssidNum( = %d)!\n", BssidCountSupposed, pAd->ApCfg.BssidNum));
+ }
+ if (pAd->ApCfg.BssidNum > 1)
+ {
+ /* Anyway, we still do the legacy dissection of the whole SSID string.*/
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ int apidx = 0;
+
+ if (i < pAd->ApCfg.BssidNum)
+ {
+ apidx = i;
+ }
+ else
+ {
+ break;
+ }
+
+ NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].Ssid, macptr , strlen(macptr));
+ pAd->ApCfg.MBSSID[apidx].Ssid[strlen(macptr)] = '\0';
+ pAd->ApCfg.MBSSID[apidx].SsidLen = strlen((PSTRING) pAd->ApCfg.MBSSID[apidx].Ssid);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("SSID[%d]=%s\n", i, pAd->ApCfg.MBSSID[apidx].Ssid));
+ }
+ }
+ else
+ {
+ if ((strlen(tmpbuf) > 0) && (strlen(tmpbuf) <= 32))
+ {
+ NdisMoveMemory(pAd->ApCfg.MBSSID[BSS0].Ssid, tmpbuf , strlen(tmpbuf));
+ pAd->ApCfg.MBSSID[BSS0].Ssid[strlen(tmpbuf)] = '\0';
+ pAd->ApCfg.MBSSID[BSS0].SsidLen = strlen((PSTRING) pAd->ApCfg.MBSSID[BSS0].Ssid);
+ DBGPRINT(RT_DEBUG_TRACE, ("SSID=%s\n", pAd->ApCfg.MBSSID[BSS0].Ssid));
+ }
+ }
+ }
+ }
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /*Channel*/
+ if(RTMPGetKeyParameter("Channel", tmpbuf, 10, pBuffer, TRUE))
+ {
+ pAd->CommonCfg.Channel = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("Channel=%d\n", pAd->CommonCfg.Channel));
+ }
+
+ /*WirelessMode*/
+ /*Note: BssidNum must be put before WirelessMode in dat file*/
+ if(RTMPGetKeyParameter("WirelessMode", tmpbuf, 32, pBuffer, TRUE))
+ {
+ UCHAR cfg_mode;
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ cfg_mode = simple_strtol(macptr, 0, 10);
+#ifdef CONFIG_AP_SUPPORT
+#ifdef MBSS_SUPPORT
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ pAd->ApCfg.MBSSID[i].PhyMode = cfgmode_2_wmode(cfg_mode);
+ DBGPRINT(RT_DEBUG_TRACE, ("BSS%d PhyMode=%d\n", i, pAd->ApCfg.MBSSID[i].PhyMode));
+#endif /* MBSS_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (i == 0)
+ {
+#ifdef CONFIG_AP_SUPPORT
+#ifdef MBSS_SUPPORT
+ /* for first time, update all phy mode is same as ra0 */
+ {
+ UINT32 IdBss;
+ for(IdBss=1; IdBss<pAd->ApCfg.BssidNum; IdBss++)
+ pAd->ApCfg.MBSSID[IdBss].PhyMode = pAd->ApCfg.MBSSID[0].PhyMode;
+ }
+#endif /* MBSS_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ /* set mode for 1st time */
+ RT_CfgSetWirelessMode(pAd, macptr);
+ }
+#ifdef CONFIG_AP_SUPPORT
+#ifdef MBSS_SUPPORT
+ else
+ RT_CfgSetMbssWirelessMode(pAd, macptr);
+#endif /* MBSS_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("PhyMode=%d\n", pAd->CommonCfg.PhyMode));
+ }
+
+ /*BasicRate*/
+ if(RTMPGetKeyParameter("BasicRate", tmpbuf, 10, pBuffer, TRUE))
+ {
+ pAd->CommonCfg.BasicRateBitmap = (ULONG) simple_strtol(tmpbuf, 0, 10);
+ pAd->CommonCfg.BasicRateBitmapOld = (ULONG) simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("BasicRate=%ld\n", pAd->CommonCfg.BasicRateBitmap));
+ }
+ /*BeaconPeriod*/
+ if(RTMPGetKeyParameter("BeaconPeriod", tmpbuf, 10, pBuffer, TRUE))
+ {
+ USHORT bcn_val = (USHORT) simple_strtol(tmpbuf, 0, 10);
+
+ /* The acceptable is 20~1000 ms. Refer to WiFi test plan. */
+ if (bcn_val >= 20 && bcn_val <= 1000)
+ pAd->CommonCfg.BeaconPeriod = bcn_val;
+ else
+ pAd->CommonCfg.BeaconPeriod = 100; /* Default value*/
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BeaconPeriod=%d\n", pAd->CommonCfg.BeaconPeriod));
+ }
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef DFS_SUPPORT
+ /*DFSIndoor*/
+ {
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam;
+
+ if (RTMPGetKeyParameter("DfsIndoor", tmpbuf, 10, pBuffer, TRUE))
+ {
+ pAd->Dot11_H.bDFSIndoor = (USHORT) (simple_strtol(tmpbuf, 0, 10) != 0);
+ DBGPRINT(RT_DEBUG_TRACE, ("DfsIndoor=%d\n", pAd->Dot11_H.bDFSIndoor));
+ }
+ {
+ INT k=0;
+ /*SymRoundFromCfg*/
+ if (RTMPGetKeyParameter("SymRoundFromCfg", tmpbuf, 10, pBuffer, TRUE))
+ {
+ pRadarDetect->SymRoundFromCfg = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+ pRadarDetect->SymRoundCfgValid = 1;
+ DBGPRINT(RT_DEBUG_TRACE, ("SymRoundFromCfg=%d\n", pRadarDetect->SymRoundFromCfg));
+ }
+
+ /*BusyIdleFromCfg*/
+ if (RTMPGetKeyParameter("BusyIdleFromCfg", tmpbuf, 10, pBuffer, TRUE))
+ {
+ pRadarDetect->BusyIdleFromCfg = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+ pRadarDetect->BusyIdleCfgValid = 1;
+ DBGPRINT(RT_DEBUG_TRACE, ("BusyIdleFromCfg=%d\n", pRadarDetect->BusyIdleFromCfg));
+ }
+ /*DfsRssiHighFromCfg*/
+ if (RTMPGetKeyParameter("DfsRssiHighFromCfg", tmpbuf, 10, pBuffer, TRUE))
+ {
+ pRadarDetect->DfsRssiHighFromCfg = simple_strtol(tmpbuf, 0, 10);
+ pRadarDetect->DfsRssiHighCfgValid = 1;
+ DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiHighFromCfg=%d\n", pRadarDetect->DfsRssiHighFromCfg));
+ }
+
+ /*DfsRssiLowFromCfg*/
+ if (RTMPGetKeyParameter("DfsRssiLowFromCfg", tmpbuf, 10, pBuffer, TRUE))
+ {
+ pRadarDetect->DfsRssiLowFromCfg = simple_strtol(tmpbuf, 0, 10);
+ pRadarDetect->DfsRssiLowCfgValid = 1;
+ DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiLowFromCfg=%d\n", pRadarDetect->DfsRssiLowFromCfg));
+ }
+
+ /*DFSParamFromConfig*/
+ if (RTMPGetKeyParameter("DFSParamFromConfig", tmpbuf, 10, pBuffer, TRUE))
+ {
+ pRadarDetect->DFSParamFromConfig = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("DFSParamFromConfig=%d\n", pRadarDetect->DFSParamFromConfig));
+ }
+
+ /* DFSParam*/
+ for(k = 0; k < 4*pAd->chipCap.DfsEngineNum; k++)
+ {
+ STRING tok_str[32];
+ INT index ;
+ UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum;
+ index = (k%DfsEngineNum);
+ if (((k-k%DfsEngineNum)/DfsEngineNum) == 0)
+ snprintf(tok_str, sizeof(tok_str), "FCCParamCh%d", index);
+ else if (((k-k%DfsEngineNum)/DfsEngineNum) == 1)
+ snprintf(tok_str, sizeof(tok_str), "CEParamCh%d", index);
+ else if (((k-k%DfsEngineNum)/DfsEngineNum) == 2)
+ snprintf(tok_str, sizeof(tok_str), "JAPParamCh%d", index);
+ else if (((k-k%DfsEngineNum)/DfsEngineNum) == 3)
+ snprintf(tok_str, sizeof(tok_str), "JAPW53ParamCh%d", index);
+
+ if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, pBuffer, TRUE))
+ {
+ ULONG DfsParam;
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ DfsParam = simple_strtol(macptr, 0, 10);
+ switch (i)
+ {
+ case 0:
+ pDfsProgramParam->NewDFSTableEntry[k].mode = DfsParam;
+ break;
+ case 1:
+ pDfsProgramParam->NewDFSTableEntry[k].avgLen = DfsParam;
+ pDfsProgramParam->NewDFSTableEntry[k].valid = 1;
+ break;
+ case 2:
+ pDfsProgramParam->NewDFSTableEntry[k].ELow = DfsParam;
+ break;
+ case 3:
+ pDfsProgramParam->NewDFSTableEntry[k].EHigh = DfsParam;
+ break;
+ case 4:
+ pDfsProgramParam->NewDFSTableEntry[k].WLow = DfsParam;
+ break;
+ case 5:
+ pDfsProgramParam->NewDFSTableEntry[k].WHigh = DfsParam;
+ break;
+ case 6:
+ pDfsProgramParam->NewDFSTableEntry[k].EpsilonW = DfsParam;
+ break;
+ case 7:
+ pDfsProgramParam->NewDFSTableEntry[k].TLow = DfsParam;
+ break;
+ case 8:
+ pDfsProgramParam->NewDFSTableEntry[k].THigh = DfsParam;
+ break;
+ case 9:
+ pDfsProgramParam->NewDFSTableEntry[k].EpsilonT = DfsParam;
+ break;
+
+ case 10:
+ pDfsProgramParam->NewDFSTableEntry[k].BLow = DfsParam;
+ break;
+ case 11:
+ pDfsProgramParam->NewDFSTableEntry[k].BHigh = DfsParam;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+#endif /* DFS_SUPPORT */
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /*DtimPeriod*/
+ if(RTMPGetKeyParameter("DtimPeriod", tmpbuf, 10, pBuffer, TRUE))
+ {
+ pAd->ApCfg.DtimPeriod = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("DtimPeriod=%d\n", pAd->ApCfg.DtimPeriod));
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ /*TxPower*/
+ if(RTMPGetKeyParameter("TxPower", tmpbuf, 10, pBuffer, TRUE))
+ {
+ pAd->CommonCfg.TxPowerPercentage = (ULONG) simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("TxPower=%ld\n", pAd->CommonCfg.TxPowerPercentage));
+ }
+ /*BGProtection*/
+ if(RTMPGetKeyParameter("BGProtection", tmpbuf, 10, pBuffer, TRUE))
+ {
+ /*#if 0 #ifndef WIFI_TEST*/
+ /* pAd->CommonCfg.UseBGProtection = 2; disable b/g protection for throughput test*/
+ /*#else*/
+ switch (simple_strtol(tmpbuf, 0, 10))
+ {
+ case 1: /*Always On*/
+ pAd->CommonCfg.UseBGProtection = 1;
+ break;
+ case 2: /*Always OFF*/
+ pAd->CommonCfg.UseBGProtection = 2;
+ break;
+ case 0: /*AUTO*/
+ default:
+ pAd->CommonCfg.UseBGProtection = 0;
+ break;
+ }
+ /*#endif*/
+ DBGPRINT(RT_DEBUG_TRACE, ("BGProtection=%ld\n", pAd->CommonCfg.UseBGProtection));
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ /*OLBCDetection*/
+ if(RTMPGetKeyParameter("DisableOLBC", tmpbuf, 10, pBuffer, TRUE))
+ {
+ switch (simple_strtol(tmpbuf, 0, 10))
+ {
+ case 1: /*disable OLBC Detection*/
+ pAd->CommonCfg.DisableOLBCDetect = 1;
+ break;
+ case 0: /*enable OLBC Detection*/
+ pAd->CommonCfg.DisableOLBCDetect = 0;
+ break;
+ default:
+ pAd->CommonCfg.DisableOLBCDetect= 0;
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("OLBCDetection=%ld\n", pAd->CommonCfg.DisableOLBCDetect));
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ /*TxPreamble*/
+ if(RTMPGetKeyParameter("TxPreamble", tmpbuf, 10, pBuffer, TRUE))
+ {
+ switch (simple_strtol(tmpbuf, 0, 10))
+ {
+ case Rt802_11PreambleShort:
+ pAd->CommonCfg.TxPreamble = Rt802_11PreambleShort;
+ break;
+ case Rt802_11PreambleLong:
+ default:
+ pAd->CommonCfg.TxPreamble = Rt802_11PreambleLong;
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("TxPreamble=%ld\n", pAd->CommonCfg.TxPreamble));
+ }
+ /*RTSThreshold*/
+ if(RTMPGetKeyParameter("RTSThreshold", tmpbuf, 10, pBuffer, TRUE))
+ {
+ RtsThresh = simple_strtol(tmpbuf, 0, 10);
+ if( (RtsThresh >= 1) && (RtsThresh <= MAX_RTS_THRESHOLD) )
+ pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh;
+ else
+ pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTSThreshold=%d\n", pAd->CommonCfg.RtsThreshold));
+ }
+ /*FragThreshold*/
+ if(RTMPGetKeyParameter("FragThreshold", tmpbuf, 10, pBuffer, TRUE))
+ {
+ FragThresh = simple_strtol(tmpbuf, 0, 10);
+ pAd->CommonCfg.bUseZeroToDisableFragment = FALSE;
+
+ if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD)
+ { /*illegal FragThresh so we set it to default*/
+ pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;
+ pAd->CommonCfg.bUseZeroToDisableFragment = TRUE;
+ }
+ else if (FragThresh % 2 == 1)
+ {
+ /* The length of each fragment shall always be an even number of octets, except for the last fragment*/
+ /* of an MSDU or MMPDU, which may be either an even or an odd number of octets.*/
+ pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1);
+ }
+ else
+ {
+ pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh;
+ }
+ /*pAd->CommonCfg.AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;*/
+ DBGPRINT(RT_DEBUG_TRACE, ("FragThreshold=%d\n", pAd->CommonCfg.FragmentThreshold));
+ }
+ /*TxBurst*/
+ if(RTMPGetKeyParameter("TxBurst", tmpbuf, 10, pBuffer, TRUE))
+ {
+ /*#ifdef WIFI_TEST*/
+ /* pAd->CommonCfg.bEnableTxBurst = FALSE;*/
+ /*#else*/
+ if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/
+ pAd->CommonCfg.bEnableTxBurst = TRUE;
+ else /*Disable*/
+ pAd->CommonCfg.bEnableTxBurst = FALSE;
+ /*#endif*/
+ DBGPRINT(RT_DEBUG_TRACE, ("TxBurst=%d\n", pAd->CommonCfg.bEnableTxBurst));
+ }
+
+#ifdef AGGREGATION_SUPPORT
+ /*PktAggregate*/
+ if(RTMPGetKeyParameter("PktAggregate", tmpbuf, 10, pBuffer, TRUE))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/
+ pAd->CommonCfg.bAggregationCapable = TRUE;
+ else /*Disable*/
+ pAd->CommonCfg.bAggregationCapable = FALSE;
+#ifdef PIGGYBACK_SUPPORT
+ pAd->CommonCfg.bPiggyBackCapable = pAd->CommonCfg.bAggregationCapable;
+#endif /* PIGGYBACK_SUPPORT */
+ DBGPRINT(RT_DEBUG_TRACE, ("PktAggregate=%d\n", pAd->CommonCfg.bAggregationCapable));
+ }
+#else
+ pAd->CommonCfg.bAggregationCapable = FALSE;
+ pAd->CommonCfg.bPiggyBackCapable = FALSE;
+#endif /* AGGREGATION_SUPPORT */
+
+ /* WmmCapable*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ rtmp_read_ap_wmm_parms_from_file(pAd, tmpbuf, pBuffer);
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#if defined(P2P_SUPPORT) || defined(CONFIG_AP_SUPPORT)
+ /* IdleTimeout & StationKeepAlive shall be supported in P2P mode,
+ so moved out from CONFIG_AP_SUPPORT block
+ */
+ /* IdleTimeout*/
+ if(RTMPGetKeyParameter("IdleTimeout", tmpbuf, 10, pBuffer, TRUE))
+ {
+ ApCfg_Set_IdleTimeout_Proc(pAd, tmpbuf);
+ }
+
+ /*StationKeepAlive*/
+ if(RTMPGetKeyParameter("StationKeepAlive", tmpbuf, 32, pBuffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ int apidx = i;
+
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ pAd->ApCfg.MBSSID[apidx].StationKeepAliveTime = simple_strtol(macptr, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) StationKeepAliveTime=%d\n", i, pAd->ApCfg.MBSSID[apidx].StationKeepAliveTime));
+ }
+ }
+#endif /* defined(P2P_SUPPORT) || defined(CONFIG_AP_SUPPORT) */
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* MaxStaNum*/
+ if (RTMPGetKeyParameter("MaxStaNum", tmpbuf, 32, pBuffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ ApCfg_Set_MaxStaNum_Proc(pAd, i, macptr);
+ }
+ }
+
+ /*NoForwarding*/
+ if(RTMPGetKeyParameter("NoForwarding", tmpbuf, 32, pBuffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/
+ pAd->ApCfg.MBSSID[i].IsolateInterStaTraffic = TRUE;
+ else /*Disable*/
+ pAd->ApCfg.MBSSID[i].IsolateInterStaTraffic = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) NoForwarding=%ld\n", i, pAd->ApCfg.MBSSID[i].IsolateInterStaTraffic));
+ }
+ }
+ /*NoForwardingBTNBSSID*/
+ if(RTMPGetKeyParameter("NoForwardingBTNBSSID", tmpbuf, 10, pBuffer, TRUE))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/
+ pAd->ApCfg.IsolateInterStaTrafficBTNBSSID = TRUE;
+ else /*Disable*/
+ pAd->ApCfg.IsolateInterStaTrafficBTNBSSID = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("NoForwardingBTNBSSID=%ld\n", pAd->ApCfg.IsolateInterStaTrafficBTNBSSID));
+ }
+ /*HideSSID*/
+ if(RTMPGetKeyParameter("HideSSID", tmpbuf, 32, pBuffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ int apidx = i;
+
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/
+ {
+ pAd->ApCfg.MBSSID[apidx].bHideSsid = TRUE;
+#ifdef WSC_V2_SUPPORT
+ pAd->ApCfg.MBSSID[apidx].WscControl.WscV2Info.bWpsEnable = FALSE;
+#endif /* WSC_V2_SUPPORT */
+ }
+ else /*Disable*/
+ pAd->ApCfg.MBSSID[apidx].bHideSsid = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) HideSSID=%d\n", i, pAd->ApCfg.MBSSID[apidx].bHideSsid));
+ }
+ }
+
+ /*AutoChannelSelect*/
+ if(RTMPGetKeyParameter("AutoChannelSelect", tmpbuf, 10, pBuffer, TRUE))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) != 0) /*Enable*/
+ {
+ ChannelSel_Alg SelAlg=(ChannelSel_Alg)simple_strtol(tmpbuf, 0, 10);
+ if (SelAlg > 2 || SelAlg < 0)
+ {
+ pAd->ApCfg.bAutoChannelAtBootup = FALSE;
+ }
+ else /*Enable*/
+ {
+ pAd->ApCfg.bAutoChannelAtBootup = TRUE;
+ pAd->ApCfg.AutoChannelAlg = SelAlg;
+ }
+ }
+ else /*Disable*/
+ pAd->ApCfg.bAutoChannelAtBootup = FALSE;
+ DBGPRINT(RT_DEBUG_TRACE, ("AutoChannelAtBootup=%d\n", pAd->ApCfg.bAutoChannelAtBootup));
+ }
+ /*AutoChannelSkipList*/
+ if (RTMPGetKeyParameter("AutoChannelSkipList", tmpbuf, 50, pBuffer, FALSE))
+ {
+ pAd->ApCfg.AutoChannelSkipListNum = delimitcnt(tmpbuf, ";") + 1;
+ if ( pAd->ApCfg.AutoChannelSkipListNum > 10 )
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Your no. of AutoChannelSkipList( %d ) is larger than 10 (boundary)\n",pAd->ApCfg.AutoChannelSkipListNum));
+ pAd->ApCfg.AutoChannelSkipListNum = 10;
+ }
+
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr ; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i < pAd->ApCfg.AutoChannelSkipListNum )
+ {
+ pAd->ApCfg.AutoChannelSkipList[i] = simple_strtol(macptr, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, (" AutoChannelSkipList[%d]= %d \n", i, pAd->ApCfg.AutoChannelSkipList[i]));
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /*ShortSlot*/
+ if(RTMPGetKeyParameter("ShortSlot", tmpbuf, 10, pBuffer, TRUE))
+ {
+ RT_CfgSetShortSlot(pAd, tmpbuf);
+ DBGPRINT(RT_DEBUG_TRACE, ("ShortSlot=%d\n", pAd->CommonCfg.bUseShortSlotTime));
+ }
+
+#ifdef TXBF_SUPPORT
+ if (pAd->chipCap.FlgHwTxBfCap)
+ {
+#if defined(CONFIG_AP_SUPPORT) || defined(STA_ITXBF_SUPPORT)
+ /*ITxBfEn*/
+ if(RTMPGetKeyParameter("ITxBfEn", tmpbuf, 32, pBuffer, TRUE))
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn = (simple_strtol(tmpbuf, 0, 10) != 0);
+ DBGPRINT(RT_DEBUG_TRACE, ("ITxBfEn = %d\n", pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn));
+
+ rtmp_asic_set_bf(pAd);
+ }
+
+ /* ITxBfTimeout */
+ if(RTMPGetKeyParameter("ITxBfTimeout", tmpbuf, 32, pBuffer, TRUE))
+ {
+ pAd->CommonCfg.ITxBfTimeout = simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("ITxBfTimeout = %ld\n", pAd->CommonCfg.ITxBfTimeout));
+ }
+#endif /* defined(CONFIG_AP_SUPPORT) || defined(STA_ITXBF_SUPPORT) */
+
+ /* ETxBfEnCond*/
+ if(RTMPGetKeyParameter("ETxBfEnCond", tmpbuf, 32, pBuffer, TRUE))
+ {
+ pAd->CommonCfg.ETxBfEnCond = simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("ETxBfEnCond = %ld\n", pAd->CommonCfg.ETxBfEnCond));
+
+ if (pAd->CommonCfg.ETxBfEnCond)
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.TxBF = TRUE;
+ }
+ else
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.TxBF = FALSE;
+ }
+ rtmp_asic_set_bf(pAd);
+ }
+
+ /* ETxBfTimeout*/
+ if(RTMPGetKeyParameter("ETxBfTimeout", tmpbuf, 32, pBuffer, TRUE))
+ {
+ pAd->CommonCfg.ETxBfTimeout = simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("ETxBfTimeout = %ld\n", pAd->CommonCfg.ETxBfTimeout));
+ }
+
+ /* ETxBfNoncompress*/
+ if(RTMPGetKeyParameter("ETxBfNoncompress", tmpbuf, 32, pBuffer, TRUE))
+ {
+ pAd->CommonCfg.ETxBfNoncompress = simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("ETxBfNoncompress = %d\n", pAd->CommonCfg.ETxBfNoncompress));
+ }
+
+ /* ETxBfIncapable */
+ if(RTMPGetKeyParameter("ETxBfIncapable", tmpbuf, 32, pBuffer, TRUE))
+ {
+ pAd->CommonCfg.ETxBfIncapable = simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("ETxBfIncapable = %d\n", pAd->CommonCfg.ETxBfIncapable));
+ }
+ }
+#endif /* TXBF_SUPPORT */
+
+
+#ifdef PRE_ANT_SWITCH
+ /*PreAntSwitch*/
+ if(RTMPGetKeyParameter("PreAntSwitch", tmpbuf, 32, pBuffer, TRUE))
+ {
+ pAd->CommonCfg.PreAntSwitch = (simple_strtol(tmpbuf, 0, 10) != 0);
+ DBGPRINT(RT_DEBUG_TRACE, ("PreAntSwitch = %d\n", pAd->CommonCfg.PreAntSwitch));
+ }
+#endif /* PRE_ANT_SWITCH */
+
+
+
+#ifdef STREAM_MODE_SUPPORT
+ /* StreamMode*/
+ if (pAd->chipCap.FlgHwStreamMode)
+ {
+ if(RTMPGetKeyParameter("StreamMode", tmpbuf, 32, pBuffer, TRUE))
+ {
+ pAd->CommonCfg.StreamMode = (simple_strtol(tmpbuf, 0, 10) & 0x03);
+ DBGPRINT(RT_DEBUG_TRACE, ("StreamMode= %d\n", pAd->CommonCfg.StreamMode));
+ }
+
+ /* StreamModeMac*/
+ for (i = 0; i < STREAM_MODE_STA_NUM; i++)
+ {
+ STRING tok_str[32];
+
+ sprintf(tok_str, "StreamModeMac%d", i);
+
+ if (RTMPGetKeyParameter(tok_str, tmpbuf, MAX_PARAM_BUFFER_SIZE, pBuffer, TRUE))
+ {
+ int j;
+ if(strlen(tmpbuf) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17*/
+ continue;
+
+ for (j=0; j<ETH_LENGTH_OF_ADDRESS; j++)
+ {
+ AtoH(tmpbuf, &pAd->CommonCfg.StreamModeMac[i][j], 1);
+ tmpbuf=tmpbuf+3;
+ }
+ }
+ }
+
+ if (NdisEqualMemory(ZERO_MAC_ADDR, &pAd->CommonCfg.StreamModeMac[0][0], MAC_ADDR_LEN))
+ {
+ /* set default broadcast mac to entry 0 if user not set it */
+ NdisMoveMemory(&pAd->CommonCfg.StreamModeMac[0][0], BROADCAST_ADDR, MAC_ADDR_LEN);
+ }
+ }
+#endif /* STREAM_MODE_SUPPORT */
+
+#ifdef DBG_CTRL_SUPPORT
+ /*DebugFlags*/
+ if(RTMPGetKeyParameter("DebugFlags", tmpbuf, 32, pBuffer, TRUE))
+ {
+ pAd->CommonCfg.DebugFlags = simple_strtol(tmpbuf, 0, 16);
+ DBGPRINT(RT_DEBUG_TRACE, ("DebugFlags = 0x%02lx\n", pAd->CommonCfg.DebugFlags));
+ }
+#endif /* DBG_CTRL_SUPPORT */
+
+ /*IEEE80211H*/
+ if(RTMPGetKeyParameter("IEEE80211H", tmpbuf, 10, pBuffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/
+ pAd->CommonCfg.bIEEE80211H = TRUE;
+ else /*Disable*/
+ pAd->CommonCfg.bIEEE80211H = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("IEEE80211H=%d\n", pAd->CommonCfg.bIEEE80211H));
+ }
+ }
+
+#ifdef DFS_SUPPORT
+ {
+ /*CSPeriod*/
+ if(RTMPGetKeyParameter("CSPeriod", tmpbuf, 10, pBuffer, TRUE))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) != 0)
+ pAd->Dot11_H.CSPeriod = simple_strtol(tmpbuf, 0, 10);
+ else
+ pAd->Dot11_H.CSPeriod = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("CSPeriod=%d\n", pAd->Dot11_H.CSPeriod));
+ }
+
+ }
+#endif /* DFS_SUPPORT */
+
+ /*RDRegion*/
+ if(RTMPGetKeyParameter("RDRegion", tmpbuf, 128, pBuffer, TRUE))
+ {
+ if ((strncmp(tmpbuf, "JAP_W53", 7) == 0) || (strncmp(tmpbuf, "jap_w53", 7) == 0))
+ {
+ pAd->CommonCfg.RDDurRegion = JAP_W53;
+ /*pRadarDetect->DfsSessionTime = 15;*/
+ }
+ else if ((strncmp(tmpbuf, "JAP_W56", 7) == 0) || (strncmp(tmpbuf, "jap_w56", 7) == 0))
+ {
+ pAd->CommonCfg.RDDurRegion = JAP_W56;
+ /*pRadarDetect->DfsSessionTime = 13;*/
+ }
+ else if ((strncmp(tmpbuf, "JAP", 3) == 0) || (strncmp(tmpbuf, "jap", 3) == 0))
+ {
+ pAd->CommonCfg.RDDurRegion = JAP;
+ /*pRadarDetect->DfsSessionTime = 5;*/
+ }
+ else if ((strncmp(tmpbuf, "FCC", 3) == 0) || (strncmp(tmpbuf, "fcc", 3) == 0))
+ {
+ pAd->CommonCfg.RDDurRegion = FCC;
+ /*pRadarDetect->DfsSessionTime = 5;*/
+ }
+ else if ((strncmp(tmpbuf, "CE", 2) == 0) || (strncmp(tmpbuf, "ce", 2) == 0))
+ {
+ pAd->CommonCfg.RDDurRegion = CE;
+ /*pRadarDetect->DfsSessionTime = 13;*/
+ }
+ else
+ {
+ pAd->CommonCfg.RDDurRegion = CE;
+ /*pRadarDetect->DfsSessionTime = 13;*/
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RDRegion=%d\n", pAd->CommonCfg.RDDurRegion));
+ }
+ else
+ {
+ pAd->CommonCfg.RDDurRegion = CE;
+ /*pRadarDetect->DfsSessionTime = 13;*/
+ }
+
+#ifdef SYSTEM_LOG_SUPPORT
+ /*WirelessEvent*/
+ if(RTMPGetKeyParameter("WirelessEvent", tmpbuf, 10, pBuffer, TRUE))
+ {
+ BOOLEAN FlgIsWEntSup = FALSE;
+
+ if(simple_strtol(tmpbuf, 0, 10) != 0)
+ FlgIsWEntSup = TRUE;
+
+ RtmpOsWlanEventSet(pAd, &pAd->CommonCfg.bWirelessEvent, FlgIsWEntSup);
+ DBGPRINT(RT_DEBUG_TRACE, ("WirelessEvent=%d\n", pAd->CommonCfg.bWirelessEvent));
+ }
+#endif /* SYSTEM_LOG_SUPPORT */
+
+
+ /*AuthMode*/
+ if(RTMPGetKeyParameter("AuthMode", tmpbuf, 128, pBuffer, TRUE))
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < pAd->ApCfg.BssidNum); macptr = rstrtok(NULL,";"), i++)
+ {
+ ApCfg_Set_AuthMode_Proc(pAd, i, macptr);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ /*EncrypType*/
+ if(RTMPGetKeyParameter("EncrypType", tmpbuf, 128, pBuffer, TRUE))
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /*
+ We need to reset the WepStatus of all interfaces as 1 (Ndis802_11WEPDisabled) first.
+ Or it may have problem when some interface enabled but didn't configure it.
+ */
+ for ( i= 0; i<pAd->ApCfg.BssidNum; i++)
+ pAd->ApCfg.MBSSID[i].WepStatus = Ndis802_11WEPDisabled;
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ int apidx;
+
+ if (i<pAd->ApCfg.BssidNum)
+ {
+ apidx = i;
+ }
+ else
+ {
+ break;
+ }
+
+ if ((strncmp(macptr, "NONE", 4) == 0) || (strncmp(macptr, "none", 4) == 0))
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPDisabled;
+ else if ((strncmp(macptr, "WEP", 3) == 0) || (strncmp(macptr, "wep", 3) == 0))
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPEnabled;
+ else if ((strncmp(macptr, "TKIPAES", 7) == 0) || (strncmp(macptr, "tkipaes", 7) == 0))
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption4Enabled;
+ else if ((strncmp(macptr, "TKIP", 4) == 0) || (strncmp(macptr, "tkip", 4) == 0))
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption2Enabled;
+ else if ((strncmp(macptr, "AES", 3) == 0) || (strncmp(macptr, "aes", 3) == 0))
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption3Enabled;
+#ifdef WAPI_SUPPORT
+ else if ((strncmp(macptr, "SMS4", 4) == 0) || (strncmp(macptr, "sms4", 4) == 0))
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11EncryptionSMS4Enabled;
+#endif /* WAPI_SUPPORT */
+ else
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPDisabled;
+
+ /* decide the group key encryption type*/
+ if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled)
+ pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus = Ndis802_11Encryption2Enabled;
+ else
+ pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus = pAd->ApCfg.MBSSID[apidx].WepStatus;
+
+ /* move to ap.c::APStartUp to process*/
+ /*RTMPMakeRSNIE(pAd, pAd->ApCfg.MBSSID[apidx].AuthMode, pAd->ApCfg.MBSSID[apidx].WepStatus, apidx);*/
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) EncrypType=%d\n", i, pAd->ApCfg.MBSSID[apidx].WepStatus));
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* WpaMixPairCipher*/
+ if(RTMPGetKeyParameter("WpaMixPairCipher", tmpbuf, 256, pBuffer, TRUE))
+ {
+ /*
+ In WPA-WPA2 mix mode, it provides a more flexible cipher combination.
+ - WPA-AES and WPA2-TKIP
+ - WPA-AES and WPA2-TKIPAES
+ - WPA-TKIP and WPA2-AES
+ - WPA-TKIP and WPA2-TKIPAES
+ - WPA-TKIPAES and WPA2-AES
+ - WPA-TKIPAES and WPA2-TKIP
+ - WPA-TKIPAES and WPA2-TKIPAES (default)
+ */
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (pAd->ApCfg.MBSSID[i].AuthMode != Ndis802_11AuthModeWPA1WPA2 &&
+ pAd->ApCfg.MBSSID[i].AuthMode != Ndis802_11AuthModeWPA1PSKWPA2PSK)
+ continue;
+
+ if (pAd->ApCfg.MBSSID[i].WepStatus != Ndis802_11Encryption4Enabled)
+ continue;
+
+ if ((strncmp(macptr, "WPA_AES_WPA2_TKIPAES", 20) == 0) || (strncmp(macptr, "wpa_aes_wpa2_tkipaes", 20) == 0))
+ pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_AES_WPA2_TKIPAES;
+ else if ((strncmp(macptr, "WPA_AES_WPA2_TKIP", 17) == 0) || (strncmp(macptr, "wpa_aes_wpa2_tkip", 17) == 0))
+ pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_AES_WPA2_TKIP;
+ else if ((strncmp(macptr, "WPA_TKIP_WPA2_AES", 17) == 0) || (strncmp(macptr, "wpa_tkip_wpa2_aes", 17) == 0))
+ pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_TKIP_WPA2_AES;
+ else if ((strncmp(macptr, "WPA_TKIP_WPA2_TKIPAES", 21) == 0) || (strncmp(macptr, "wpa_tkip_wpa2_tkipaes", 21) == 0))
+ pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_TKIP_WPA2_TKIPAES;
+ else if ((strncmp(macptr, "WPA_TKIPAES_WPA2_AES", 20) == 0) || (strncmp(macptr, "wpa_tkipaes_wpa2_aes", 20) == 0))
+ pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_TKIPAES_WPA2_AES;
+ else if ((strncmp(macptr, "WPA_TKIPAES_WPA2_TKIPAES", 24) == 0) || (strncmp(macptr, "wpa_tkipaes_wpa2_tkipaes", 24) == 0))
+ pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES;
+ else if ((strncmp(macptr, "WPA_TKIPAES_WPA2_TKIP", 21) == 0) || (strncmp(macptr, "wpa_tkipaes_wpa2_tkip", 21) == 0))
+ pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIP;
+ else /*Default*/
+ pAd->ApCfg.MBSSID[i].WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES;
+
+ DBGPRINT(RT_DEBUG_OFF, ("I/F(ra%d) MixWPACipher=0x%02x\n", i, pAd->ApCfg.MBSSID[i].WpaMixPairCipher));
+ }
+ }
+
+ /*RekeyMethod*/
+ if(RTMPGetKeyParameter("RekeyMethod", tmpbuf, 128, pBuffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ PRT_WPA_REKEY pRekeyInfo = &pAd->ApCfg.MBSSID[i].WPAREKEY;
+
+ if ((strcmp(macptr, "TIME") == 0) || (strcmp(macptr, "time") == 0))
+ pRekeyInfo->ReKeyMethod = TIME_REKEY;
+ else if ((strcmp(macptr, "PKT") == 0) || (strcmp(macptr, "pkt") == 0))
+ pRekeyInfo->ReKeyMethod = PKT_REKEY;
+ else if ((strcmp(macptr, "DISABLE") == 0) || (strcmp(macptr, "disable") == 0))
+ pRekeyInfo->ReKeyMethod = DISABLE_REKEY;
+ else
+ pRekeyInfo->ReKeyMethod = DISABLE_REKEY;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) ReKeyMethod=%ld\n", i, pRekeyInfo->ReKeyMethod));
+ }
+
+ /* Apply to remaining MBSS*/
+ if (i == 1)
+ {
+ for (i = 1; i < pAd->ApCfg.BssidNum; i++)
+ {
+ pAd->ApCfg.MBSSID[i].WPAREKEY.ReKeyMethod =
+ pAd->ApCfg.MBSSID[0].WPAREKEY.ReKeyMethod;
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) ReKeyMethod=%ld\n",
+ i, pAd->ApCfg.MBSSID[i].WPAREKEY.ReKeyMethod));
+ }
+ }
+ }
+ /*RekeyInterval*/
+ if(RTMPGetKeyParameter("RekeyInterval", tmpbuf, 255, pBuffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ ULONG value_interval;
+ PRT_WPA_REKEY pRekeyInfo = &pAd->ApCfg.MBSSID[i].WPAREKEY;
+
+ value_interval = simple_strtol(macptr, 0, 10);
+
+ if((value_interval >= 10) && (value_interval < MAX_REKEY_INTER))
+ pRekeyInfo->ReKeyInterval = value_interval;
+ else /*Default*/
+ pRekeyInfo->ReKeyInterval = 3600;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) ReKeyInterval=%ld\n",
+ i, pRekeyInfo->ReKeyInterval));
+ }
+
+ /* Apply to remaining MBSS*/
+ if (i == 1)
+ {
+ for (i = 1; i < pAd->ApCfg.BssidNum; i++)
+ {
+ pAd->ApCfg.MBSSID[i].WPAREKEY.ReKeyInterval =
+ pAd->ApCfg.MBSSID[0].WPAREKEY.ReKeyInterval;
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) ReKeyInterval=%ld\n",
+ i, pAd->ApCfg.MBSSID[i].WPAREKEY.ReKeyInterval));
+ }
+ }
+
+ }
+ /*PMKCachePeriod*/
+ if(RTMPGetKeyParameter("PMKCachePeriod", tmpbuf, 255, pBuffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->ApCfg.MBSSID[i].PMKCachePeriod =
+ simple_strtol(macptr, 0, 10) * 60 * OS_HZ;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) PMKCachePeriod=%ld\n",
+ i, pAd->ApCfg.MBSSID[i].PMKCachePeriod));
+ }
+
+ /* Apply to remaining MBSS*/
+ if (i == 1)
+ {
+ for (i = 1; i < pAd->ApCfg.BssidNum; i++)
+ {
+ pAd->ApCfg.MBSSID[i].PMKCachePeriod =
+ pAd->ApCfg.MBSSID[0].PMKCachePeriod;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) PMKCachePeriod=%ld\n",
+ i, pAd->ApCfg.MBSSID[i].PMKCachePeriod));
+ }
+ }
+ }
+
+ /*WPAPSK_KEY*/
+ if(TRUE)
+ {
+ STRING tok_str[16];
+ BOOLEAN bWPAPSKxIsUsed = FALSE;
+
+ //DBGPRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.BssidNum=%d\n", pAd->ApCfg.BssidNum));
+ for (i = 0; i < pAd->ApCfg.BssidNum; i++)
+ {
+ snprintf(tok_str, sizeof(tok_str), "WPAPSK%d", i + 1);
+ if(RTMPGetKeyParameter(tok_str, tmpbuf, 65, pBuffer, FALSE))
+ {
+ rtmp_parse_wpapsk_buffer_from_file(pAd, tmpbuf, i);
+
+ if (bWPAPSKxIsUsed == FALSE)
+ {
+ bWPAPSKxIsUsed = TRUE;
+ }
+ }
+ }
+ if (bWPAPSKxIsUsed == FALSE)
+ {
+ if (RTMPGetKeyParameter("WPAPSK", tmpbuf, 512, pBuffer, FALSE))
+ {
+ if (pAd->ApCfg.BssidNum == 1)
+ {
+ rtmp_parse_wpapsk_buffer_from_file(pAd, tmpbuf, BSS0);
+ }
+ else
+ {
+ /* Anyway, we still do the legacy dissection of the whole WPAPSK passphrase.*/
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ rtmp_parse_wpapsk_buffer_from_file(pAd, macptr, i);
+ }
+
+ }
+ }
+ }
+
+#ifdef DBG
+ for (i = 0; i < pAd->ApCfg.BssidNum; i++)
+ {
+ int j;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WPAPSK Key => \n", i));
+ for (j = 0; j < 32; j++)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%02x:", pAd->ApCfg.MBSSID[i].PMK[j]));
+ if ((j%16) == 15)
+ DBGPRINT(RT_DEBUG_TRACE, ("\n"));
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("\n"));
+ }
+#endif
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /*DefaultKeyID, KeyType, KeyStr*/
+ rtmp_read_key_parms_from_file(pAd, tmpbuf, pBuffer);
+
+#ifdef WAPI_SUPPORT
+ rtmp_read_wapi_parms_from_file(pAd, tmpbuf, pBuffer);
+#endif /* WAPI_SUPPORT */
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /*Access Control List*/
+ rtmp_read_acl_parms_from_file(pAd, tmpbuf, pBuffer);
+
+#ifdef APCLI_SUPPORT
+ rtmp_read_ap_client_from_file(pAd, tmpbuf, pBuffer);
+#endif /* APCLI_SUPPORT */
+
+#ifdef IGMP_SNOOP_SUPPORT
+ /* Igmp Snooping information*/
+ rtmp_read_igmp_snoop_from_file(pAd, tmpbuf, pBuffer);
+#endif /* IGMP_SNOOP_SUPPORT */
+
+#ifdef WDS_SUPPORT
+ rtmp_read_wds_from_file(pAd, tmpbuf, pBuffer);
+#endif /* WDS_SUPPORT */
+
+#ifdef DOT1X_SUPPORT
+ rtmp_read_radius_parms_from_file(pAd, tmpbuf, pBuffer);
+#endif /* DOT1X_SUPPORT */
+
+#ifdef IDS_SUPPORT
+ rtmp_read_ids_from_file(pAd, tmpbuf, pBuffer);
+#endif /* IDS_SUPPORT */
+ rtmp_read_multest_from_file(pAd, tmpbuf, pBuffer);
+ }
+
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef DOT11_N_SUPPORT
+ HTParametersHook(pAd, tmpbuf, pBuffer);
+#endif /* DOT11_N_SUPPORT */
+
+#ifdef DOT11_VHT_AC
+ VHTParametersHook(pAd, tmpbuf, pBuffer);
+#endif /* DOT11_VHT_AC */
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef WSC_AP_SUPPORT
+ STRING tok_str[16] = {0};
+ for (i = 0; i < pAd->ApCfg.BssidNum; i++)
+ {
+ snprintf(tok_str, sizeof(tok_str), "WscDefaultSSID%d", i + 1);
+ if(RTMPGetKeyParameter(tok_str, tmpbuf, 33, pBuffer, FALSE))
+ {
+ NdisZeroMemory(&pAd->ApCfg.MBSSID[i].WscControl.WscDefaultSsid, sizeof(NDIS_802_11_SSID));
+ NdisMoveMemory(pAd->ApCfg.MBSSID[i].WscControl.WscDefaultSsid.Ssid, tmpbuf , strlen(tmpbuf));
+ pAd->ApCfg.MBSSID[i].WscControl.WscDefaultSsid.SsidLength = strlen(tmpbuf);
+ DBGPRINT(RT_DEBUG_TRACE, ("WscDefaultSSID[%d]=%s\n", i, pAd->ApCfg.MBSSID[i].WscControl.WscDefaultSsid.Ssid));
+ }
+ }
+
+ /*WscConfMode*/
+ if(RTMPGetKeyParameter("WscConfMode", tmpbuf, 10, pBuffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ INT WscConfMode = simple_strtol(macptr, 0, 10);
+
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ if (WscConfMode > 0 && WscConfMode < 8)
+ {
+ pAd->ApCfg.MBSSID[i].WscControl.WscConfMode = WscConfMode;
+ }
+ else
+ {
+ pAd->ApCfg.MBSSID[i].WscControl.WscConfMode = WSC_DISABLE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WscConfMode=%d\n", i, pAd->ApCfg.MBSSID[i].WscControl.WscConfMode));
+ }
+ }
+
+ /*WscConfStatus*/
+ if(RTMPGetKeyParameter("WscConfStatus", tmpbuf, 10, pBuffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ pAd->ApCfg.MBSSID[i].WscControl.WscConfStatus = (INT) simple_strtol(macptr, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WscConfStatus=%d\n", i, pAd->ApCfg.MBSSID[i].WscControl.WscConfStatus));
+ }
+ }
+ /*WscConfMethods*/
+ if(RTMPGetKeyParameter("WscConfMethods", tmpbuf, 32, pBuffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ pAd->ApCfg.MBSSID[i].WscControl.WscConfigMethods = (USHORT)simple_strtol(macptr, 0, 16);
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WscConfMethods=0x%x\n", i, pAd->ApCfg.MBSSID[i].WscControl.WscConfigMethods));
+ }
+ }
+
+ /*WscKeyASCII (0:Hex, 1:ASCII(random length), others: ASCII length, default 8)*/
+ if (RTMPGetKeyParameter("WscKeyASCII", tmpbuf, 10, pBuffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ INT Value;
+
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ Value = (INT) simple_strtol(tmpbuf, 0, 10);
+ if(Value==0 || Value==1)
+ pAd->ApCfg.MBSSID[i].WscControl.WscKeyASCII = Value;
+ else if(Value >= 8 && Value <=63)
+ pAd->ApCfg.MBSSID[i].WscControl.WscKeyASCII = Value;
+ else
+ pAd->ApCfg.MBSSID[i].WscControl.WscKeyASCII = 8;
+ DBGPRINT(RT_DEBUG_WARN, ("WscKeyASCII=%d\n", pAd->ApCfg.MBSSID[i].WscControl.WscKeyASCII));
+ }
+ }
+
+ if (RTMPGetKeyParameter("WscSecurityMode", tmpbuf, 50, pBuffer, TRUE))
+ {
+ for (i= 0; i<pAd->ApCfg.BssidNum; i++)
+ pAd->ApCfg.MBSSID[i].WscSecurityMode = WPAPSKTKIP;
+
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ INT tmpMode = 0;
+
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ tmpMode = (INT) simple_strtol(macptr, 0, 10);
+ if (tmpMode <= WPAPSKTKIP)
+ pAd->ApCfg.MBSSID[i].WscSecurityMode = tmpMode;
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetProfileParameters I/F(ra%d) WscSecurityMode=%d\n",
+ i, pAd->ApCfg.MBSSID[i].WscSecurityMode));
+ }
+ }
+
+ /* WCNTest*/
+ if(RTMPGetKeyParameter("WCNTest", tmpbuf, 10, pBuffer, TRUE))
+ {
+ BOOLEAN bEn = FALSE;
+
+ if ((strncmp(tmpbuf, "0", 1) == 0))
+ bEn = FALSE;
+ else
+ bEn = TRUE;
+
+ for (i = 0; i < pAd->ApCfg.BssidNum; i++)
+ {
+ pAd->ApCfg.MBSSID[i].WscControl.bWCNTest = bEn;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("WCNTest=%d\n", bEn));
+ }
+
+ /*WSC UUID Str*/
+ for (i = 0; i < pAd->ApCfg.BssidNum; i++)
+ {
+ PWSC_CTRL pWpsCtrl = &pAd->ApCfg.MBSSID[i].WscControl;
+ snprintf(tok_str, sizeof(tok_str), "WSC_UUID_Str%d", i + 1);
+ if(RTMPGetKeyParameter(tok_str, tmpbuf, 40, pBuffer, FALSE))
+ {
+ NdisMoveMemory(&pWpsCtrl->Wsc_Uuid_Str[0], tmpbuf , strlen(tmpbuf));
+ DBGPRINT(RT_DEBUG_TRACE, ("UUID_Str[%d]=%s\n", i+1, pWpsCtrl->Wsc_Uuid_Str));
+ }
+ }
+
+ /*WSC UUID Hex*/
+ for (i = 0; i < pAd->ApCfg.BssidNum; i++)
+ {
+ PWSC_CTRL pWpsCtrl = &pAd->ApCfg.MBSSID[i].WscControl;
+ snprintf(tok_str, sizeof(tok_str), "WSC_UUID_E%d", i + 1);
+ if(RTMPGetKeyParameter(tok_str, tmpbuf, 40, pBuffer, FALSE))
+ {
+ AtoH(tmpbuf, &pWpsCtrl->Wsc_Uuid_E[0], UUID_LEN_HEX);
+ DBGPRINT(RT_DEBUG_TRACE, ("Wsc_Uuid_E[%d]", i+1));
+ hex_dump("", &pWpsCtrl->Wsc_Uuid_E[0], UUID_LEN_HEX);
+ }
+ }
+
+
+#endif /* WSC_AP_SUPPORT */
+
+
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CARRIER_DETECTION_SUPPORT
+ /*CarrierDetect*/
+ if(RTMPGetKeyParameter("CarrierDetect", tmpbuf, 128, pBuffer, TRUE))
+ {
+ if ((strncmp(tmpbuf, "0", 1) == 0))
+ pAd->CommonCfg.CarrierDetect.Enable = FALSE;
+ else if ((strncmp(tmpbuf, "1", 1) == 0))
+ pAd->CommonCfg.CarrierDetect.Enable = TRUE;
+ else
+ pAd->CommonCfg.CarrierDetect.Enable = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("CarrierDetect.Enable=%d\n", pAd->CommonCfg.CarrierDetect.Enable));
+ }
+ else
+ pAd->CommonCfg.CarrierDetect.Enable = FALSE;
+#endif /* CARRIER_DETECTION_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef MCAST_RATE_SPECIFIC
+ /* McastPhyMode*/
+ if (RTMPGetKeyParameter("McastPhyMode", tmpbuf, 32, pBuffer, TRUE))
+ {
+ UCHAR PhyMode = simple_strtol(tmpbuf, 0, 10);
+ pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.RegTransmitSetting.field.BW;
+ switch (PhyMode)
+ {
+ case MCAST_DISABLE: /* disable*/
+ NdisMoveMemory(&pAd->CommonCfg.MCastPhyMode,
+ &pAd->MacTab.Content[MCAST_WCID].HTPhyMode, sizeof(HTTRANSMIT_SETTING));
+ break;
+
+ case MCAST_CCK: /* CCK*/
+ pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_CCK;
+ pAd->CommonCfg.MCastPhyMode.field.BW = BW_20;
+ break;
+
+ case MCAST_OFDM: /* OFDM*/
+ pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_OFDM;
+ break;
+#ifdef DOT11_N_SUPPORT
+ case MCAST_HTMIX: /* HTMIX*/
+ pAd->CommonCfg.MCastPhyMode.field.MODE = MODE_HTMIX;
+ break;
+#endif /* DOT11_N_SUPPORT */
+
+ default:
+ DBGPRINT(RT_DEBUG_OFF, ("unknow Muticast PhyMode %d.\n", PhyMode));
+ DBGPRINT(RT_DEBUG_OFF, ("0:Disable 1:CCK, 2:OFDM, 3:HTMIX.\n"));
+ break;
+ }
+ }
+ else
+ NdisMoveMemory(&pAd->CommonCfg.MCastPhyMode,
+ &pAd->MacTab.Content[MCAST_WCID].HTPhyMode, sizeof(HTTRANSMIT_SETTING));
+
+ /* McastMcs*/
+ if (RTMPGetKeyParameter("McastMcs", tmpbuf, 32, pBuffer, TRUE))
+ {
+ UCHAR Mcs = simple_strtol(tmpbuf, 0, 10);
+ switch(pAd->CommonCfg.MCastPhyMode.field.MODE)
+ {
+ case MODE_CCK:
+ if ((Mcs <= 3) || (Mcs >= 8 && Mcs <= 11))
+ pAd->CommonCfg.MCastPhyMode.field.MCS = Mcs;
+ else
+ DBGPRINT(RT_DEBUG_OFF, ("MCS must in range of 0 ~ 3 and 8 ~ 11 for CCK Mode.\n"));
+ break;
+
+ case MODE_OFDM:
+ if (Mcs > 7)
+ DBGPRINT(RT_DEBUG_OFF, ("MCS must in range from 0 to 7 for CCK Mode.\n"));
+ else
+ pAd->CommonCfg.MCastPhyMode.field.MCS = Mcs;
+ break;
+
+ default:
+ pAd->CommonCfg.MCastPhyMode.field.MCS = Mcs;
+ break;
+ }
+ }
+ else
+ pAd->CommonCfg.MCastPhyMode.field.MCS = 0;
+#endif /* MCAST_RATE_SPECIFIC */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef WSC_INCLUDED
+
+ rtmp_read_wsc_user_parms_from_file(pAd, tmpbuf, pBuffer);
+
+ /* Wsc4digitPinCode = TRUE use 4-digit Pin code, otherwise 8-digit Pin code */
+ if (RTMPGetKeyParameter("Wsc4digitPinCode", tmpbuf, 32, pBuffer, TRUE))
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+
+ if (simple_strtol(macptr, 0, 10) != 0) //Enable
+ pAd->ApCfg.MBSSID[i].WscControl.WscEnrollee4digitPinCode = TRUE;
+ else //Disable
+ pAd->ApCfg.MBSSID[i].WscControl.WscEnrollee4digitPinCode = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Wsc4digitPinCode=%d\n", i, pAd->ApCfg.MBSSID[i].WscControl.WscEnrollee4digitPinCode));
+ }
+
+ }
+#endif // CONFIG_AP_SUPPORT //
+ }
+
+ if (RTMPGetKeyParameter("WscVendorPinCode", tmpbuf, 256, pBuffer, TRUE))
+ {
+ PWSC_CTRL pWscContrl;
+ int bSetOk;
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ pWscContrl = &pAd->ApCfg.MBSSID[BSS0].WscControl;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ bSetOk = RT_CfgSetWscPinCode(pAd, tmpbuf, pWscContrl);
+ if (bSetOk)
+ DBGPRINT(RT_DEBUG_TRACE, ("%s - WscVendorPinCode= (%d)\n", __FUNCTION__, bSetOk));
+ else
+ DBGPRINT(RT_DEBUG_ERROR, ("%s - WscVendorPinCode: invalid pin code(%s)\n", __FUNCTION__, tmpbuf));
+ }
+#ifdef WSC_V2_SUPPORT
+ if (RTMPGetKeyParameter("WscV2Support", tmpbuf, 32, pBuffer, TRUE))
+ {
+ UCHAR bEnable;
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if (i >= pAd->ApCfg.BssidNum)
+ break;
+ bEnable = (UCHAR)simple_strtol(macptr, 0, 10);
+ pAd->ApCfg.MBSSID[i].WscControl.WscV2Info.bEnableWpsV2 = bEnable;
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WscV2Support=%d\n", i, bEnable));
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+#endif /* WSC_V2_SUPPORT */
+
+
+#endif /* WSC_INCLUDED */
+
+#ifdef CONFIG_AP_SUPPORT
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+ /* EntryLifeCheck is used to check */
+ if (RTMPGetKeyParameter("EntryLifeCheck", tmpbuf, 256, pBuffer, TRUE))
+ {
+ long LifeCheckCnt = simple_strtol(tmpbuf, 0, 10);
+ if ((LifeCheckCnt <= 65535) && (LifeCheckCnt != 0))
+ pAd->ApCfg.EntryLifeCheck = LifeCheckCnt;
+ else
+ pAd->ApCfg.EntryLifeCheck = MAC_ENTRY_LIFE_CHECK_CNT;
+
+ DBGPRINT(RT_DEBUG_ERROR, ("EntryLifeCheck=%ld\n", pAd->ApCfg.EntryLifeCheck));
+ }
+
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef SINGLE_SKU
+ if(RTMPGetKeyParameter("AntGain", tmpbuf, 10, pBuffer, TRUE))
+ {
+ UCHAR AntGain = simple_strtol(tmpbuf, 0, 10);
+ pAd->CommonCfg.AntGain= AntGain;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AntGain=%d\n", pAd->CommonCfg.AntGain));
+ }
+ if(RTMPGetKeyParameter("BandedgeDelta", tmpbuf, 10, pBuffer, TRUE))
+ {
+ UCHAR Bandedge = simple_strtol(tmpbuf, 0, 10);
+ pAd->CommonCfg.BandedgeDelta = Bandedge;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BandedgeDelta=%d\n", pAd->CommonCfg.BandedgeDelta));
+ }
+#endif /* SINGLE_SKU */
+
+
+
+
+#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT)
+ /* set GPIO pin for wake-up signal */
+ if (RTMPGetKeyParameter("WOW_GPIO", tmpbuf, 10, pBuffer, TRUE))
+ Set_WOW_GPIO(pAd, tmpbuf);
+
+ /* set WOW enable/disable */
+ if (RTMPGetKeyParameter("WOW_Enable", tmpbuf, 10, pBuffer, TRUE))
+ Set_WOW_Enable(pAd, tmpbuf);
+
+ /* set delay time for WOW really enable */
+ if (RTMPGetKeyParameter("WOW_Delay", tmpbuf, 10, pBuffer, TRUE))
+ Set_WOW_Delay(pAd, tmpbuf);
+
+ /* set GPIO pulse hold time */
+ if (RTMPGetKeyParameter("WOW_Hold", tmpbuf, 10, pBuffer, TRUE))
+ Set_WOW_Hold(pAd, tmpbuf);
+
+ /* set wakeup signal type */
+ if (RTMPGetKeyParameter("WOW_InBand", tmpbuf, 10, pBuffer, TRUE))
+ Set_WOW_InBand(pAd, tmpbuf);
+#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */
+
+#ifdef MICROWAVE_OVEN_SUPPORT
+ if (RTMPGetKeyParameter("MO_FalseCCATh", tmpbuf, 10, pBuffer, TRUE))
+ {
+ Set_MO_FalseCCATh_Proc(pAd, tmpbuf);
+ }
+#endif /* MICROWAVE_OVEN_SUPPORT */
+
+ }while(0);
+
+#ifdef CUSTOMER_DEMO
+ demo_mode_cfg(pAd);
+#endif /* CUSTOMER_DEMO */
+
+ os_free_mem(NULL, tmpbuf);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+#ifdef MULTIPLE_CARD_SUPPORT
+/* record whether the card in the card list is used in the card file*/
+UINT8 MC_CardUsed[MAX_NUM_OF_MULTIPLE_CARD];
+/* record used card mac address in the card list*/
+static UINT8 MC_CardMac[MAX_NUM_OF_MULTIPLE_CARD][6];
+
+/*
+========================================================================
+Routine Description:
+ Get card profile path.
+
+Arguments:
+ pAd
+
+Return Value:
+ TRUE - Find a card profile
+ FALSE - use default profile
+
+Note:
+========================================================================
+*/
+BOOLEAN RTMP_CardInfoRead(
+ IN PRTMP_ADAPTER pAd)
+{
+#define MC_SELECT_CARDID 0 /* use CARD ID (0 ~ 31) to identify different cards */
+#define MC_SELECT_MAC 1 /* use CARD MAC to identify different cards */
+#define MC_SELECT_CARDTYPE 2 /* use CARD type (abgn or bgn) to identify different cards */
+
+#define LETTER_CASE_TRANSLATE(txt_p, card_id) \
+ { UINT32 _len; char _char; \
+ for(_len=0; _len<strlen(card_id); _len++) { \
+ _char = *(txt_p + _len); \
+ if (('A' <= _char) && (_char <= 'Z')) \
+ *(txt_p+_len) = 'a'+(_char-'A'); \
+ } }
+
+ RTMP_OS_FD srcf;
+ INT retval;
+ PSTRING buffer, tmpbuf;
+ STRING card_id_buf[30], RFIC_word[30];
+ BOOLEAN flg_match_ok = FALSE;
+ INT32 card_select_method;
+ INT32 card_free_id, card_nouse_id, card_same_mac_id, card_match_id;
+ EEPROM_ANTENNA_STRUC antenna;
+ USHORT addr01, addr23, addr45;
+ UINT8 mac[6];
+ UINT32 data, card_index;
+ UCHAR *start_ptr;
+ RTMP_OS_FS_INFO osFSInfo;
+
+ /* init*/
+ os_alloc_mem(NULL, (UCHAR **)&buffer, MAX_INI_BUFFER_SIZE);
+ if (buffer == NULL)
+ return FALSE;
+
+ os_alloc_mem(NULL, (UCHAR **)&tmpbuf, MAX_PARAM_BUFFER_SIZE);
+ if(tmpbuf == NULL)
+ {
+ os_free_mem(NULL, buffer);
+ return NDIS_STATUS_FAILURE;
+ }
+
+ /* get RF IC type*/
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &data);
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, antenna.word);
+
+ if ((antenna.field.RfIcType == RFIC_2850) ||
+ (antenna.field.RfIcType == RFIC_2750) ||
+ (antenna.field.RfIcType == RFIC_2853) ||
+ (antenna.field.RfIcType == RFIC_3853) ||
+ (antenna.field.RfIcType == RFIC_5592))
+ {
+ /* ABGN card */
+ strcpy(RFIC_word, "abgn");
+ }
+ else
+ {
+ /* BGN card */
+ strcpy(RFIC_word, "bgn");
+ }
+
+ /* get MAC address*/
+ RT28xx_EEPROM_READ16(pAd, 0x04, addr01);
+ RT28xx_EEPROM_READ16(pAd, 0x06, addr23);
+ RT28xx_EEPROM_READ16(pAd, 0x08, addr45);
+
+ mac[0] = (UCHAR)(addr01 & 0xff);
+ mac[1] = (UCHAR)(addr01 >> 8);
+ mac[2] = (UCHAR)(addr23 & 0xff);
+ mac[3] = (UCHAR)(addr23 >> 8);
+ mac[4] = (UCHAR)(addr45 & 0xff);
+ mac[5] = (UCHAR)(addr45 >> 8);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("mac addr=%02x:%02x:%02x:%02x:%02x:%02x!\n", PRINT_MAC(mac)));
+
+ RtmpOSFSInfoChange(&osFSInfo, TRUE);
+ /* open card information file*/
+ srcf = RtmpOSFileOpen(CARD_INFO_PATH, O_RDONLY, 0);
+ if (IS_FILE_OPEN_ERR(srcf))
+ {
+ /* card information file does not exist */
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("--> Error opening %s\n", CARD_INFO_PATH));
+ goto free_resource;
+ }
+
+ /* card information file exists so reading the card information */
+ memset(buffer, 0x00, MAX_INI_BUFFER_SIZE);
+ retval = RtmpOSFileRead(srcf, buffer, MAX_INI_BUFFER_SIZE);
+ if (retval < 0)
+ {
+ /* read fail */
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("--> Read %s error %d\n", CARD_INFO_PATH, -retval));
+ }
+ else
+ {
+ /* get card selection method */
+ memset(tmpbuf, 0x00, MAX_PARAM_BUFFER_SIZE);
+ card_select_method = MC_SELECT_CARDTYPE; /* default*/
+
+ if (RTMPGetKeyParameter("SELECT", tmpbuf, 256, buffer, TRUE))
+ {
+ if (strcmp(tmpbuf, "CARDID") == 0)
+ card_select_method = MC_SELECT_CARDID;
+ else if (strcmp(tmpbuf, "MAC") == 0)
+ card_select_method = MC_SELECT_MAC;
+ else if (strcmp(tmpbuf, "CARDTYPE") == 0)
+ card_select_method = MC_SELECT_CARDTYPE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("MC> Card Selection = %d\n", card_select_method));
+
+ /* init*/
+ card_free_id = -1;
+ card_nouse_id = -1;
+ card_same_mac_id = -1;
+ card_match_id = -1;
+
+ /* search current card information records*/
+ for(card_index=0;
+ card_index<MAX_NUM_OF_MULTIPLE_CARD;
+ card_index++)
+ {
+ if ((*(UINT32 *)&MC_CardMac[card_index][0] == 0) &&
+ (*(UINT16 *)&MC_CardMac[card_index][4] == 0))
+ {
+ /* MAC is all-0 so the entry is available*/
+ MC_CardUsed[card_index] = 0;
+
+ if (card_free_id < 0)
+ card_free_id = card_index; /* 1st free entry*/
+ }
+ else
+ {
+ if (memcmp(MC_CardMac[card_index], mac, 6) == 0)
+ {
+ /* we find the entry with same MAC*/
+ if (card_same_mac_id < 0)
+ card_same_mac_id = card_index; /* 1st same entry*/
+ }
+ else
+ {
+ /* MAC is not all-0 but used flag == 0*/
+ if ((MC_CardUsed[card_index] == 0) &&
+ (card_nouse_id < 0))
+ {
+ card_nouse_id = card_index; /* 1st available entry*/
+ }
+ }
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("MC> Free = %d, Same = %d, NOUSE = %d\n",
+ card_free_id, card_same_mac_id, card_nouse_id));
+
+ if ((card_same_mac_id >= 0) &&
+ ((card_select_method == MC_SELECT_CARDID) ||
+ (card_select_method == MC_SELECT_CARDTYPE)))
+ {
+ /* same MAC entry is found*/
+ card_match_id = card_same_mac_id;
+
+ if (card_select_method == MC_SELECT_CARDTYPE)
+ {
+ /* for CARDTYPE*/
+ snprintf(card_id_buf, sizeof(card_id_buf), "%02dCARDTYPE%s",
+ card_match_id, RFIC_word);
+
+ if ((start_ptr = (PUCHAR)rtstrstruncasecmp(buffer, card_id_buf)) != NULL)
+ {
+ /* we found the card ID*/
+ LETTER_CASE_TRANSLATE(start_ptr, card_id_buf);
+ }
+ }
+ }
+ else
+ {
+ /* the card is 1st plug-in, try to find the match card profile*/
+ switch(card_select_method)
+ {
+ case MC_SELECT_CARDID: /* CARDID*/
+ default:
+ if (card_free_id >= 0)
+ card_match_id = card_free_id;
+ else
+ card_match_id = card_nouse_id;
+ break;
+
+ case MC_SELECT_MAC: /* MAC*/
+ snprintf(card_id_buf, sizeof(card_id_buf), "MAC%02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1], mac[2],
+ mac[3], mac[4], mac[5]);
+
+ /* try to find the key word in the card file */
+ if ((start_ptr = (PUCHAR)rtstrstruncasecmp(buffer, card_id_buf)) != NULL)
+ {
+ LETTER_CASE_TRANSLATE(start_ptr, card_id_buf);
+
+ /* get the row ID (2 ASCII characters) */
+ start_ptr -= 2;
+ card_id_buf[0] = *(start_ptr);
+ card_id_buf[1] = *(start_ptr+1);
+ card_id_buf[2] = 0x00;
+
+ card_match_id = simple_strtol(card_id_buf, 0, 10);
+ }
+ break;
+
+ case MC_SELECT_CARDTYPE: /* CARDTYPE*/
+ card_nouse_id = -1;
+
+ for(card_index=0;
+ card_index<MAX_NUM_OF_MULTIPLE_CARD;
+ card_index++)
+ {
+ snprintf(card_id_buf, sizeof(card_id_buf), "%02dCARDTYPE%s",
+ card_index, RFIC_word);
+
+ if ((start_ptr = (PUCHAR)rtstrstruncasecmp(buffer,
+ card_id_buf)) != NULL)
+ {
+ LETTER_CASE_TRANSLATE(start_ptr, card_id_buf);
+
+ if (MC_CardUsed[card_index] == 0)
+ {
+ /* current the card profile is not used */
+ if ((*(UINT32 *)&MC_CardMac[card_index][0] == 0) &&
+ (*(UINT16 *)&MC_CardMac[card_index][4] == 0))
+ {
+ /* find it and no previous card use it*/
+ card_match_id = card_index;
+ break;
+ }
+ else
+ {
+ /* ever a card use it*/
+ if (card_nouse_id < 0)
+ card_nouse_id = card_index;
+ }
+ }
+ }
+ }
+
+ /* if not find a free one, use the available one*/
+ if (card_match_id < 0)
+ card_match_id = card_nouse_id;
+ break;
+ }
+ }
+
+ if (card_match_id >= 0)
+ {
+ /* make up search keyword*/
+ switch(card_select_method)
+ {
+ case MC_SELECT_CARDID: /* CARDID*/
+ snprintf(card_id_buf, sizeof(card_id_buf), "%02dCARDID", card_match_id);
+ break;
+
+ case MC_SELECT_MAC: /* MAC*/
+ snprintf(card_id_buf, sizeof(card_id_buf),
+ "%02dmac%02x:%02x:%02x:%02x:%02x:%02x",
+ card_match_id,
+ mac[0], mac[1], mac[2],
+ mac[3], mac[4], mac[5]);
+ break;
+
+ case MC_SELECT_CARDTYPE: /* CARDTYPE*/
+ default:
+ snprintf(card_id_buf, sizeof(card_id_buf), "%02dcardtype%s",
+ card_match_id, RFIC_word);
+ break;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Search Keyword = %s\n", card_id_buf));
+
+ /* read card file path*/
+ if (RTMPGetKeyParameter(card_id_buf, tmpbuf, 256, buffer, TRUE))
+ {
+ if (strlen(tmpbuf) < sizeof(pAd->MC_FileName))
+ {
+ /* backup card information*/
+ pAd->MC_RowID = card_match_id; /* base 0 */
+ MC_CardUsed[card_match_id] = 1;
+ memcpy(MC_CardMac[card_match_id], mac, sizeof(mac));
+
+ /* backup card file path*/
+ NdisMoveMemory(pAd->MC_FileName, tmpbuf , strlen(tmpbuf));
+ pAd->MC_FileName[strlen(tmpbuf)] = '\0';
+ flg_match_ok = TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("Card Profile Name = %s\n", pAd->MC_FileName));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("Card Profile Name length too large!\n"));
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("Can not find search key word in card.dat!\n"));
+ }
+
+ if ((flg_match_ok != TRUE) &&
+ (card_match_id < MAX_NUM_OF_MULTIPLE_CARD))
+ {
+ MC_CardUsed[card_match_id] = 0;
+ memset(MC_CardMac[card_match_id], 0, sizeof(mac));
+ }
+ } /* if (card_match_id >= 0)*/
+ }
+
+
+/* close file*/
+retval = RtmpOSFileClose(srcf);
+
+free_resource:
+RtmpOSFSInfoChange(&osFSInfo, FALSE);
+/* kfree(buffer);*/
+/* kfree(tmpbuf);*/
+os_free_mem(NULL, buffer);
+os_free_mem(NULL, tmpbuf);
+
+return flg_match_ok;
+}
+#endif /* MULTIPLE_CARD_SUPPORT */
+
+
+#ifdef WSC_INCLUDED
+void rtmp_read_wsc_user_parms(
+ PWSC_CTRL pWscControl,
+ STRING *tmpbuf,
+ STRING *buffer)
+{
+ if(RTMPGetKeyParameter("WscManufacturer", tmpbuf, WSC_MANUFACTURE_LEN, buffer,TRUE))
+ {
+ NdisZeroMemory(pWscControl->RegData.SelfInfo.Manufacturer, WSC_MANUFACTURE_LEN);
+ NdisMoveMemory(pWscControl->RegData.SelfInfo.Manufacturer, tmpbuf, strlen(tmpbuf));
+ if(pWscControl->RegData.SelfInfo.Manufacturer[0] != 0x00)
+ RTMP_SET_FLAG(pWscControl, 0x01);
+ }
+
+ /*WSC_User_ModelName*/
+ if(RTMPGetKeyParameter("WscModelName", tmpbuf, WSC_MODELNAME_LEN, buffer,TRUE))
+ {
+ NdisZeroMemory(pWscControl->RegData.SelfInfo.ModelName, WSC_MODELNAME_LEN);
+ NdisMoveMemory(pWscControl->RegData.SelfInfo.ModelName, tmpbuf, strlen(tmpbuf));
+ if(pWscControl->RegData.SelfInfo.ModelName[0] != 0x00)
+ RTMP_SET_FLAG(pWscControl, 0x02);
+ }
+
+ /*WSC_User_DeviceName*/
+ if(RTMPGetKeyParameter("WscDeviceName", tmpbuf, WSC_DEVICENAME_LEN, buffer,TRUE))
+ {
+ NdisZeroMemory(pWscControl->RegData.SelfInfo.DeviceName, WSC_DEVICENAME_LEN);
+ NdisMoveMemory(pWscControl->RegData.SelfInfo.DeviceName, tmpbuf, strlen(tmpbuf));
+ if(pWscControl->RegData.SelfInfo.DeviceName[0] != 0x00)
+ RTMP_SET_FLAG(pWscControl, 0x04);
+ }
+
+ /*WSC_User_ModelNumber*/
+ if(RTMPGetKeyParameter("WscModelNumber", tmpbuf, WSC_MODELNUNBER_LEN, buffer,TRUE))
+ {
+ NdisZeroMemory(pWscControl->RegData.SelfInfo.ModelNumber, WSC_MODELNUNBER_LEN);
+ NdisMoveMemory(pWscControl->RegData.SelfInfo.ModelNumber, tmpbuf, strlen(tmpbuf));
+ if(pWscControl->RegData.SelfInfo.ModelNumber[0] != 0x00)
+ RTMP_SET_FLAG(pWscControl, 0x08);
+ }
+
+ /*WSC_User_SerialNumber*/
+ if(RTMPGetKeyParameter("WscSerialNumber", tmpbuf, WSC_SERIALNUNBER_LEN, buffer,TRUE))
+ {
+ NdisZeroMemory(pWscControl->RegData.SelfInfo.SerialNumber, WSC_SERIALNUNBER_LEN);
+ NdisMoveMemory(pWscControl->RegData.SelfInfo.SerialNumber, tmpbuf, strlen(tmpbuf));
+ if(pWscControl->RegData.SelfInfo.SerialNumber[0] != 0x00)
+ RTMP_SET_FLAG(pWscControl, 0x10);
+ }
+}
+
+void rtmp_read_wsc_user_parms_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer)
+{
+ PWSC_CTRL pWscControl;
+
+#ifdef WSC_AP_SUPPORT
+ int i=0;
+ for(i = 0; i < MAX_MBSSID_NUM(pAd); i++)
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[i].WscControl;
+ rtmp_read_wsc_user_parms(pWscControl, tmpbuf, buffer);
+}
+#ifdef APCLI_SUPPORT
+ pWscControl = &pAd->ApCfg.ApCliTab[0].WscControl;
+ rtmp_read_wsc_user_parms(pWscControl, tmpbuf, buffer);
+#endif /* APCLI_SUPPORT */
+#endif /* WSC_AP_SUPPORT */
+
+#ifdef WSC_STA_SUPPORT
+ pWscControl = &pAd->StaCfg.WscControl;
+ rtmp_read_wsc_user_parms(pWscControl, tmpbuf, buffer);
+#endif /* WSC_STA_SUPPORT */
+
+}
+#endif/*WSC_INCLUDED*/
+
+
+VOID rtmp_read_multest_from_file(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING tmpbuf,
+ IN PSTRING buffer)
+{
+ PSTRING macptr;
+ INT i=0, j;
+ STRING tok_str[16];
+ BOOLEAN bUsePrevFormat = FALSE;
+ UCHAR macAddress[MAC_ADDR_LEN];
+ UCHAR keyMaterial[40];
+ UCHAR KeyLen, CipherAlg = CIPHER_NONE, KeyIdx;
+ PRT_802_11_WDS_ENTRY pWdsEntry;
+
+ /*WdsPhyMode */
+ if (RTMPGetKeyParameter("WdsPhyMode", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE))
+ {
+ for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++)
+ {
+ if ((strncmp(macptr, "CCK", 3) == 0) || (strncmp(macptr, "cck", 3) == 0))
+ pAd->MulTestTab.WdsEntry[i].PhyMode = MODE_CCK;
+ else if ((strncmp(macptr, "OFDM", 4) == 0) || (strncmp(macptr, "ofdm", 4) == 0))
+ pAd->MulTestTab.WdsEntry[i].PhyMode = MODE_OFDM;
+#ifdef DOT11_N_SUPPORT
+ else if ((strncmp(macptr, "HTMIX", 5) == 0) || (strncmp(macptr, "htmix", 5) == 0))
+ pAd->MulTestTab.WdsEntry[i].PhyMode = MODE_HTMIX;
+ else if ((strncmp(macptr, "GREENFIELD", 10) == 0) || (strncmp(macptr, "greenfield", 10) == 0))
+ pAd->MulTestTab.WdsEntry[i].PhyMode = MODE_HTGREENFIELD;
+#endif /* DOT11_N_SUPPORT */
+ else
+ pAd->MulTestTab.WdsEntry[i].PhyMode = 0xff;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("If/wds%d - WdsPhyMode=%d\n", i, pAd->MulTestTab.WdsEntry[i].PhyMode));
+ }
+ }
+
+ /*WdsList */
+ if (RTMPGetKeyParameter("WdsList", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE))
+ {
+ for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++)
+ {
+ if(strlen(macptr) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */
+ continue;
+ if(strcmp(macptr,"00:00:00:00:00:00") == 0)
+ continue;
+ if(i >= MAX_WDS_ENTRY)
+ break;
+
+ for (j=0; j<ETH_LENGTH_OF_ADDRESS; j++)
+ {
+ AtoH(macptr, &macAddress[j], 1);
+ macptr=macptr+3;
+ }
+
+ {
+ INT iii;
+ LONG WdsTabIdx = -1;
+
+ for (iii = 0; iii < MAX_WDS_ENTRY; iii++)
+ {
+ if (pAd->MulTestTab.WdsEntry[iii].Valid == FALSE)
+ {
+ pAd->MulTestTab.WdsEntry[iii].Valid = TRUE;
+ pAd->MulTestTab.Size ++;
+ COPY_MAC_ADDR(pAd->MulTestTab.WdsEntry[iii].PeerWdsAddr, macAddress);
+ WdsTabIdx = iii;
+ break;
+ }
+ else if (MAC_ADDR_EQUAL(pAd->MulTestTab.WdsEntry[iii].PeerWdsAddr, macAddress))
+ {
+ WdsTabIdx = iii;
+ break;
+ }
+ }
+
+ if (iii == MAX_WDS_ENTRY)
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Unable to allocate MulTestEntry.\n", __FUNCTION__));
+ }
+ }
+ }
+
+ /*WdsEncrypType */
+ if (RTMPGetKeyParameter("WdsEncrypType", tmpbuf, 128, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++)
+ {
+ if ((strncmp(macptr, "NONE", 4) == 0) || (strncmp(macptr, "none", 4) == 0))
+ pAd->MulTestTab.WdsEntry[i].WepStatus = Ndis802_11WEPDisabled;
+ else if ((strncmp(macptr, "WEP", 3) == 0) || (strncmp(macptr, "wep", 3) == 0))
+ pAd->MulTestTab.WdsEntry[i].WepStatus = Ndis802_11WEPEnabled;
+ else if ((strncmp(macptr, "TKIP", 4) == 0) || (strncmp(macptr, "tkip", 4) == 0))
+ pAd->MulTestTab.WdsEntry[i].WepStatus = Ndis802_11Encryption2Enabled;
+ else if ((strncmp(macptr, "AES", 3) == 0) || (strncmp(macptr, "aes", 3) == 0))
+ pAd->MulTestTab.WdsEntry[i].WepStatus = Ndis802_11Encryption3Enabled;
+#ifdef WAPI_SUPPORT
+ else if ((strncmp(macptr, "SMS4", 4) == 0) || (strncmp(macptr, "sms4", 4) == 0))
+ pAd->MulTestTab.WdsEntry[i].WepStatus = Ndis802_11EncryptionSMS4Enabled;
+#endif /* WAPI_SUPPORT */
+ else
+ pAd->MulTestTab.WdsEntry[i].WepStatus = Ndis802_11WEPDisabled;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WdsEncrypType[%d]=%d(%s)\n", i, pAd->MulTestTab.WdsEntry[i].WepStatus, GetEncryptType(pAd->MulTestTab.WdsEntry[i].WepStatus)));
+ }
+
+ /* Previous WDS only supports single encryption type. */
+ /* For backward compatible, other wds link encryption type shall be the same with the first. */
+ if (i == 1)
+ {
+ for (j = 1; j < MAX_WDS_ENTRY; j++)
+ {
+ pAd->MulTestTab.WdsEntry[j].WepStatus = pAd->MulTestTab.WdsEntry[0].WepStatus;
+ DBGPRINT(RT_DEBUG_TRACE, ("@WdsEncrypType[%d]=%d(%s)\n", j, pAd->MulTestTab.WdsEntry[i].WepStatus, GetEncryptType(pAd->MulTestTab.WdsEntry[i].WepStatus)));
+ }
+ }
+ }
+
+ /* WdsKey */
+ /* This is a previous parameter and it only stores WPA key material, not WEP key */
+ if (RTMPGetKeyParameter("WdsKey", tmpbuf, 255, buffer, FALSE))
+ {
+ for (i = 0; i < MAX_WDS_ENTRY; i++)
+ NdisZeroMemory(&pAd->MulTestTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY));
+
+ if (strlen(tmpbuf) > 0)
+ bUsePrevFormat = TRUE;
+
+ /* check if the wds-0 link key material is valid */
+ if (((pAd->MulTestTab.WdsEntry[0].WepStatus == Ndis802_11Encryption2Enabled)
+ || (pAd->MulTestTab.WdsEntry[0].WepStatus == Ndis802_11Encryption3Enabled))
+ && (strlen(tmpbuf) >= 8) && (strlen(tmpbuf) <= 64))
+ {
+ RT_CfgSetWPAPSKKey(pAd, tmpbuf, strlen(tmpbuf), (PUCHAR)RALINK_PASSPHRASE, sizeof(RALINK_PASSPHRASE), keyMaterial);
+ if (pAd->MulTestTab.WdsEntry[0].WepStatus == Ndis802_11Encryption3Enabled)
+ pAd->MulTestTab.WdsEntry[0].WdsKey.CipherAlg = CIPHER_AES;
+ else
+ pAd->MulTestTab.WdsEntry[0].WdsKey.CipherAlg = CIPHER_TKIP;
+
+ NdisMoveMemory(&pAd->MulTestTab.WdsEntry[0].WdsKey.Key, keyMaterial, 16);
+ pAd->MulTestTab.WdsEntry[0].WdsKey.KeyLen = 16;
+ NdisMoveMemory(&pAd->MulTestTab.WdsEntry[0].WdsKey.RxMic, keyMaterial+16, 8);
+ NdisMoveMemory(&pAd->MulTestTab.WdsEntry[0].WdsKey.TxMic, keyMaterial+16, 8);
+ }
+
+ /* Previous WDS only supports single key-material. */
+ /* For backward compatible, other wds link key-material shall be the same with the first. */
+ if (pAd->MulTestTab.WdsEntry[0].WdsKey.KeyLen == 16)
+ {
+ for (j = 1; j < MAX_WDS_ENTRY; j++)
+ {
+ NdisMoveMemory(&pAd->MulTestTab.WdsEntry[j].WdsKey, &pAd->MulTestTab.WdsEntry[0].WdsKey, sizeof(CIPHER_KEY));
+ }
+ }
+
+ }
+
+ /* The parameters can provide different key information for each WDS-Link */
+ /* no matter WEP or WPA */
+ if (!bUsePrevFormat)
+ {
+ for (i = 0; i < MAX_WDS_ENTRY; i++)
+ {
+ AP_WDS_KeyNameMakeUp(tok_str, sizeof(tok_str), i);
+
+ /* WdsXKey (X=0~MAX_WDS_ENTRY-1) */
+ if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE))
+ {
+ if (pAd->MulTestTab.WdsEntry[i].WepStatus == Ndis802_11Encryption1Enabled)
+ {
+ /* Ascii type */
+ if (strlen(tmpbuf) == 5 || strlen(tmpbuf) == 13)
+ {
+ KeyLen = strlen(tmpbuf);
+ pAd->MulTestTab.WdsEntry[i].WdsKey.KeyLen = KeyLen;
+ NdisMoveMemory(pAd->MulTestTab.WdsEntry[i].WdsKey.Key, tmpbuf, KeyLen);
+ if (KeyLen == 5)
+ CipherAlg = CIPHER_WEP64;
+ else
+ CipherAlg = CIPHER_WEP128;
+
+ pAd->MulTestTab.WdsEntry[i].WdsKey.CipherAlg = CipherAlg;
+ DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d Key=%s ,type=Ascii, CipherAlg(%s)\n", i, tmpbuf, (CipherAlg == CIPHER_WEP64 ? "wep64" : "wep128")));
+ }
+ /* Hex type */
+ else if (strlen(tmpbuf) == 10 || strlen(tmpbuf) == 26)
+ {
+ KeyLen = strlen(tmpbuf);
+ pAd->MulTestTab.WdsEntry[i].WdsKey.KeyLen = KeyLen / 2;
+ AtoH(tmpbuf, pAd->MulTestTab.WdsEntry[i].WdsKey.Key, KeyLen / 2);
+ if (KeyLen == 10)
+ CipherAlg = CIPHER_WEP64;
+ else
+ CipherAlg = CIPHER_WEP128;
+
+ pAd->MulTestTab.WdsEntry[i].WdsKey.CipherAlg = CipherAlg;
+ DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d Key=%s ,type=Hex, CipherAlg(%s)\n", i, tmpbuf, (CipherAlg == CIPHER_WEP64 ? "wep64" : "wep128")));
+ }
+ /* Invalid type */
+ else
+ {
+ pAd->MulTestTab.WdsEntry[i].WepStatus = Ndis802_11EncryptionDisabled;
+ NdisZeroMemory(&pAd->MulTestTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY));
+ DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d has invalid key for WEP, reset encryption to OPEN\n", i));
+ }
+ }
+ else if ((pAd->MulTestTab.WdsEntry[i].WepStatus == Ndis802_11Encryption2Enabled)
+ || (pAd->MulTestTab.WdsEntry[i].WepStatus == Ndis802_11Encryption3Enabled)
+#ifdef WAPI_SUPPORT
+ || (pAd->MulTestTab.WdsEntry[i].WepStatus == Ndis802_11EncryptionSMS4Enabled)
+#endif /* WAPI_SUPPORT */
+ )
+ {
+ if ((strlen(tmpbuf) >= 8) && (strlen(tmpbuf) <= 64))
+ {
+ RT_CfgSetWPAPSKKey(pAd, tmpbuf, strlen(tmpbuf), (PUCHAR) RALINK_PASSPHRASE, sizeof(RALINK_PASSPHRASE), keyMaterial);
+
+ if (pAd->MulTestTab.WdsEntry[i].WepStatus == Ndis802_11Encryption3Enabled)
+ {
+ pAd->MulTestTab.WdsEntry[i].WdsKey.CipherAlg = CIPHER_AES;
+ CipherAlg = CIPHER_AES;
+ }
+#ifdef WAPI_SUPPORT
+ else if (pAd->MulTestTab.WdsEntry[i].WepStatus == Ndis802_11EncryptionSMS4Enabled)
+ {
+ pAd->MulTestTab.WdsEntry[i].WdsKey.CipherAlg = CIPHER_SMS4;
+ CipherAlg = CIPHER_SMS4;
+ }
+#endif /* WAPI_SUPPORT */
+ else
+ {
+ pAd->MulTestTab.WdsEntry[i].WdsKey.CipherAlg = CIPHER_TKIP;
+ CipherAlg = CIPHER_TKIP;
+ }
+
+ NdisMoveMemory(&pAd->MulTestTab.WdsEntry[i].WdsKey.Key, keyMaterial, 16);
+ pAd->MulTestTab.WdsEntry[i].WdsKey.KeyLen = 16;
+ NdisMoveMemory(&pAd->MulTestTab.WdsEntry[i].WdsKey.RxMic, keyMaterial+16, 8);
+ NdisMoveMemory(&pAd->MulTestTab.WdsEntry[i].WdsKey.TxMic, keyMaterial+16, 8);
+ DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d Key=%s, CipherAlg(%s)\n", i, tmpbuf, (CipherAlg == CIPHER_AES ? "AES" : "TKIP")));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d has invalid key for WPA, reset encryption to OPEN\n", i));
+ pAd->MulTestTab.WdsEntry[i].WepStatus = Ndis802_11EncryptionDisabled;
+ NdisZeroMemory(&pAd->MulTestTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY));
+ }
+
+ }
+ else
+ {
+ pAd->MulTestTab.WdsEntry[i].WepStatus = Ndis802_11EncryptionDisabled;
+ NdisZeroMemory(&pAd->MulTestTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY));
+ }
+ }
+ }
+ }
+
+ /* WdsDefaultKeyID */
+ if(RTMPGetKeyParameter("WdsDefaultKeyID", tmpbuf, 10, buffer, TRUE))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++)
+ {
+ KeyIdx = (UCHAR) simple_strtol(macptr, 0, 10);
+ if((KeyIdx >= 1 ) && (KeyIdx <= 4))
+ pAd->MulTestTab.WdsEntry[i].KeyIdx = (UCHAR) (KeyIdx - 1);
+ else
+ pAd->MulTestTab.WdsEntry[i].KeyIdx = 0;
+
+ if ((pAd->MulTestTab.WdsEntry[i].WepStatus == Ndis802_11Encryption2Enabled)
+ || (pAd->MulTestTab.WdsEntry[i].WepStatus == Ndis802_11Encryption3Enabled))
+ pAd->MulTestTab.WdsEntry[i].KeyIdx = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d - WdsDefaultKeyID(0~3)=%d\n", i, pAd->MulTestTab.WdsEntry[i].KeyIdx));
+ }
+ }
+}
+
+
+#ifdef SINGLE_SKU_V2
+NDIS_STATUS RTMPSetSingleSKUParameters(
+ IN RTMP_ADAPTER *pAd)
+{
+ PSTRING buffer;
+ PSTRING readline, token;
+ RTMP_OS_FD srcf;
+ INT retval;
+ PSTRING ptr;
+ int index, i;
+ CH_POWER *StartCh = NULL;
+ UCHAR MaxPwr;
+ UCHAR channel, *temp;
+ RTMP_OS_FS_INFO osFSInfo;
+
+ initList(&pAd->SingleSkuPwrList);
+
+ /* init*/
+ os_alloc_mem(NULL, (UCHAR **)&buffer, MAX_INI_BUFFER_SIZE);
+ if (buffer == NULL)
+ return FALSE;
+
+ RtmpOSFSInfoChange(&osFSInfo, TRUE);
+ /* open card information file*/
+ srcf = RtmpOSFileOpen(SINGLE_SKU_TABLE_FILE_NAME, O_RDONLY, 0);
+ if (IS_FILE_OPEN_ERR(srcf))
+ {
+ /* card information file does not exist */
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("--> Error opening %s\n", SINGLE_SKU_TABLE_FILE_NAME));
+ goto free_resource;
+ }
+
+#ifdef RTMP_INTERNAL_TX_ALC
+ if (pAd->TxPowerCtrl.bInternalTxALC != TRUE)
+#endif /* RTMP_INTERNAL_TX_ALC */
+ MT7601_InitPAModeTable(pAd);
+
+ /* card information file exists so reading the card information */
+ NdisZeroMemory(buffer, MAX_INI_BUFFER_SIZE);
+ retval = RtmpOSFileRead(srcf, buffer, MAX_INI_BUFFER_SIZE);
+ if (retval < 0)
+ {
+ /* read fail */
+ DBGPRINT(RT_DEBUG_TRACE,("--> Read %s error %d\n", SINGLE_SKU_TABLE_FILE_NAME, -retval));
+ }
+ else
+ {
+
+ for ( readline = ptr = buffer, index=0; (ptr = strchr(readline, '\n')) != NULL; readline = ptr + 1, index++ )
+ {
+ *ptr = '\0';
+
+ if ( readline[0] == '#' )
+ continue;
+
+ if ( !strncmp(readline, "ch", 2) )
+ {
+
+ CH_POWER *pwr;
+
+ os_alloc_mem(NULL, (UCHAR **)&pwr, sizeof(*pwr));
+ NdisZeroMemory(pwr, sizeof(*pwr));
+
+ token= rstrtok(readline +2 ," ");
+ channel = simple_strtol(token, 0, 10);
+ pwr->StartChannel = channel;
+
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_CCK_LENGTH ; i++ )
+ {
+ token = rstrtok(NULL ," ");
+ if ( token == NULL )
+ break;
+ pwr->PwrCCK[i] = simple_strtol(token, 0, 10) * 2;
+ }
+
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_OFDM_LENGTH ; i++ )
+ {
+ token = rstrtok(NULL ," ");
+ if ( token == NULL )
+ break;
+ pwr->PwrOFDM[i] = simple_strtol(token, 0, 10) *2;
+ }
+
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ )
+ {
+ token = rstrtok(NULL ," ");
+ if ( token == NULL )
+ break;
+ pwr->PwrHT20[i] = simple_strtol(token, 0, 10) *2;
+ }
+
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ )
+ {
+ token = rstrtok(NULL ," ");
+ if ( token == NULL )
+ break;
+ pwr->PwrHT40[i] = simple_strtol(token, 0, 10) *2;
+ }
+
+
+ if ( StartCh == NULL )
+ {
+ StartCh = pwr;
+ insertTailList(&pAd->SingleSkuPwrList, (PLIST_ENTRY)pwr);
+ }
+ else
+ {
+ BOOLEAN isSame = TRUE;
+
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_CCK_LENGTH ; i++ )
+ {
+ if ( StartCh->PwrCCK[i] != pwr->PwrCCK[i] )
+ {
+ isSame = FALSE;
+ break;
+ }
+ }
+
+ if ( isSame == TRUE )
+ {
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_OFDM_LENGTH ; i++ )
+ {
+ if ( StartCh->PwrOFDM[i] != pwr->PwrOFDM[i] )
+ {
+ isSame = FALSE;
+ break;
+ }
+ }
+ }
+
+ if ( isSame == TRUE )
+ {
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ )
+ {
+ if ( StartCh->PwrHT20[i] != pwr->PwrHT20[i] )
+ {
+ isSame = FALSE;
+ break;
+ }
+ }
+ }
+
+ if ( isSame == TRUE )
+ {
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ )
+ {
+ if ( StartCh->PwrHT40[i] != pwr->PwrHT40[i] )
+ {
+ isSame = FALSE;
+ break;
+ }
+ }
+ }
+
+ if ( isSame == TRUE )
+ {
+ os_free_mem(NULL, pwr);
+ }
+ else
+ {
+ StartCh = pwr;
+ insertTailList(&pAd->SingleSkuPwrList, (PLIST_ENTRY)StartCh);
+ pwr = NULL;
+ }
+
+
+ }
+
+
+ StartCh->num ++;
+ os_alloc_mem(pAd, (PUCHAR *)&temp, StartCh->num);
+ if ( StartCh->Channel != NULL )
+ {
+ NdisMoveMemory(temp, StartCh->Channel, StartCh->num-1);
+ os_free_mem(pAd, StartCh->Channel);
+ }
+ StartCh->Channel = temp;
+ StartCh->Channel[StartCh->num-1] = channel;
+ }
+ }
+
+
+ }
+
+ {
+ CH_POWER *ch;
+ ch = pAd->SingleSkuPwrList.pHead;
+ while ( ch )
+ {
+ int i;
+ DBGPRINT(RT_DEBUG_TRACE,("start ch = %d, ch->num = %d\n", ch->StartChannel, ch->num));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Channel: "));
+ for ( i = 0 ; i < ch->num ; i++ )
+ DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->Channel[i]));
+ DBGPRINT(RT_DEBUG_TRACE,("\n"));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("CCK: "));
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_CCK_LENGTH ; i++ )
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->PwrCCK[i]));
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("\n"));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("OFDM: "));
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_OFDM_LENGTH ; i++ )
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->PwrOFDM[i]));
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("\n"));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT20: "));
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ )
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%d ", ch->PwrHT20[i]));
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("\n"));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT40: "));
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ )
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->PwrHT40[i]));
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("\n"));
+
+ ch = ch->pNext;
+ }
+ }
+
+ /* close file*/
+ retval = RtmpOSFileClose(srcf);
+
+free_resource:
+ RtmpOSFSInfoChange(&osFSInfo, FALSE);
+
+ os_free_mem(NULL, buffer);
+
+}
+
+
+UCHAR GetSkuChannelBasePwr(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR channel)
+{
+ CH_POWER *ch;
+ UCHAR start_ch;
+ UCHAR base_pwr = pAd->DefaultTargetPwr;
+ UINT8 i, j;
+
+ ch = pAd->SingleSkuPwrList.pHead;
+ while (ch )
+ {
+ start_ch = ch->StartChannel;
+
+ if ( channel >= start_ch )
+ {
+ for ( j = 0; j < ch->num; j++ )
+ {
+ if ( channel == ch->Channel[j] )
+ {
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_CCK_LENGTH ; i++ )
+ {
+ if ( base_pwr > ch->PwrCCK[i] )
+ base_pwr = ch->PwrCCK[i];
+ }
+
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_OFDM_LENGTH ; i++ )
+ {
+ if ( base_pwr > ch->PwrOFDM[i] )
+ base_pwr = ch->PwrOFDM[i];
+ }
+
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ )
+ {
+ if ( base_pwr > ch->PwrHT20[i] )
+ base_pwr = ch->PwrHT20[i];
+ }
+
+ if (pAd->CommonCfg.BBPCurrentBW == BW_40)
+ {
+ for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ )
+ {
+ if ( ch->PwrHT40[i] == 0 )
+ break;
+
+ if ( base_pwr > ch->PwrHT40[i] )
+ base_pwr = ch->PwrHT40[i];
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ ch = ch->pNext;
+ }
+
+ return base_pwr;
+
+}
+
+#define SKU_PHYMODE_CCK_1M_2M 0
+#define SKU_PHYMODE_CCK_5M_11M 1
+#define SKU_PHYMODE_OFDM_6M_9M 2
+#define SKU_PHYMODE_OFDM_12M_18M 3
+#define SKU_PHYMODE_OFDM_24M_36M 4
+#define SKU_PHYMODE_OFDM_48M_54M 5
+#define SKU_PHYMODE_HT_MCS0_MCS1 6
+#define SKU_PHYMODE_HT_MCS2_MCS3 7
+#define SKU_PHYMODE_HT_MCS4_MCS5 8
+#define SKU_PHYMODE_HT_MCS6_MCS7 9
+#define SKU_PHYMODE_HT_MCS8_MCS9 10
+#define SKU_PHYMODE_HT_MCS10_MCS11 11
+#define SKU_PHYMODE_HT_MCS12_MCS13 12
+#define SKU_PHYMODE_HT_MCS14_MCS15 13
+#define SKU_PHYMODE_STBC_MCS0_MCS1 14
+#define SKU_PHYMODE_STBC_MCS2_MCS3 15
+#define SKU_PHYMODE_STBC_MCS4_MCS5 16
+#define SKU_PHYMODE_STBC_MCS6_MCS7 17
+
+
+VOID InitSkuRateDiffTable(
+ IN PRTMP_ADAPTER pAd )
+{
+ USHORT i, value;
+ CHAR BasePwr, Pwr;
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + 4, value);
+ BasePwr = (value >> 8) & 0xFF;
+ BasePwr = (BasePwr > 0x1F ) ? BasePwr - 0x40: BasePwr;
+
+ for ( i = 0 ; i < 9; i++ )
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*2, value);
+ Pwr = value & 0xFF ;
+ Pwr = (Pwr > 0x1F ) ? Pwr - 0x40: Pwr;
+ pAd->SingleSkuRatePwrDiff[i *2] = Pwr - BasePwr;
+ Pwr = (value >> 8) & 0xFF;
+ Pwr = (Pwr > 0x1F ) ? Pwr - 0x40: Pwr;
+ pAd->SingleSkuRatePwrDiff[i *2 + 1] = Pwr - BasePwr;
+ }
+}
+
+INT32 GetSkuPAModePwr(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR PAMode)
+{
+ INT32 pa_mode_pwr = 0;
+
+ switch ( PAMode )
+ {
+ case SKU_PHYMODE_CCK_1M_2M:
+ pa_mode_pwr = RF_PA_MODE_CCK_1M;
+ break;
+ case SKU_PHYMODE_CCK_5M_11M:
+ pa_mode_pwr = RF_PA_MODE_CCK_5M;
+ break;
+ case SKU_PHYMODE_OFDM_6M_9M:
+ pa_mode_pwr = RF_PA_MODE_OFDM_6M;
+ break;
+ case SKU_PHYMODE_OFDM_12M_18M:
+ pa_mode_pwr = RF_PA_MODE_OFDM_12M;
+ break;
+ case SKU_PHYMODE_OFDM_24M_36M:
+ pa_mode_pwr = RF_PA_MODE_OFDM_24M;
+ break;
+ case SKU_PHYMODE_OFDM_48M_54M:
+ pa_mode_pwr = RF_PA_MODE_OFDM_48M;
+ break;
+ case SKU_PHYMODE_HT_MCS0_MCS1:
+ case SKU_PHYMODE_STBC_MCS0_MCS1:
+ pa_mode_pwr = RF_PA_MODE_HT_MCS0;
+ break;
+ case SKU_PHYMODE_HT_MCS2_MCS3:
+ case SKU_PHYMODE_STBC_MCS2_MCS3:
+ pa_mode_pwr = RF_PA_MODE_HT_MCS2;
+ break;
+ case SKU_PHYMODE_HT_MCS4_MCS5:
+ case SKU_PHYMODE_STBC_MCS4_MCS5:
+ pa_mode_pwr = RF_PA_MODE_HT_MCS4;
+ break;
+ case SKU_PHYMODE_HT_MCS6_MCS7:
+ case SKU_PHYMODE_STBC_MCS6_MCS7:
+ pa_mode_pwr = RF_PA_MODE_HT_MCS6;
+ break;
+ case SKU_PHYMODE_HT_MCS8_MCS9:
+ pa_mode_pwr = RF_PA_MODE_HT_MCS8;
+ break;
+ case SKU_PHYMODE_HT_MCS10_MCS11:
+ pa_mode_pwr = RF_PA_MODE_HT_MCS10;
+ break;
+ case SKU_PHYMODE_HT_MCS12_MCS13:
+ pa_mode_pwr = RF_PA_MODE_HT_MCS12;
+ break;
+ case SKU_PHYMODE_HT_MCS14_MCS15:
+ pa_mode_pwr = RF_PA_MODE_HT_MCS14;
+ break;
+ default:
+ break;
+ }
+
+ return pa_mode_pwr;
+}
+
+
+UCHAR GetSkuRatePwr(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR phymode,
+ IN UCHAR channel,
+ IN UCHAR bw)
+{
+ UINT8 i;
+ CH_POWER *ch;
+ UCHAR start_ch;
+ UCHAR rate_pwr = pAd->DefaultTargetPwr;
+ UCHAR max_pwr;
+ INT32 pwr_diff;
+
+ ch = pAd->SingleSkuPwrList.pHead;
+ while (ch )
+ {
+ start_ch = ch->StartChannel;
+
+ if ( channel >= start_ch )
+ {
+ for ( i = 0; i < ch->num; i++ )
+ {
+ if ( channel == ch->Channel[i] )
+ {
+ switch ( phymode )
+ {
+ case SKU_PHYMODE_CCK_1M_2M:
+ rate_pwr = ch->PwrCCK[0];
+ break;
+ case SKU_PHYMODE_CCK_5M_11M:
+ rate_pwr = ch->PwrCCK[2];
+ break;
+ case SKU_PHYMODE_OFDM_6M_9M:
+ rate_pwr = ch->PwrOFDM[0];
+ break;
+ case SKU_PHYMODE_OFDM_12M_18M:
+ rate_pwr = ch->PwrOFDM[2];
+ break;
+ case SKU_PHYMODE_OFDM_24M_36M:
+ rate_pwr = ch->PwrOFDM[4];
+ break;
+ case SKU_PHYMODE_OFDM_48M_54M:
+ rate_pwr = ch->PwrOFDM[6];
+ break;
+ case SKU_PHYMODE_HT_MCS0_MCS1:
+ case SKU_PHYMODE_STBC_MCS0_MCS1:
+ if ( bw == BW_20 )
+ rate_pwr = ch->PwrHT20[0];
+ else if ( bw == BW_40 )
+ rate_pwr = ch->PwrHT40[0];
+ break;
+ case SKU_PHYMODE_HT_MCS2_MCS3:
+ case SKU_PHYMODE_STBC_MCS2_MCS3:
+ if ( bw == BW_20 )
+ rate_pwr = ch->PwrHT20[2];
+ else if ( bw == BW_40 )
+ rate_pwr = ch->PwrHT40[2];
+ break;
+ case SKU_PHYMODE_HT_MCS4_MCS5:
+ case SKU_PHYMODE_STBC_MCS4_MCS5:
+ if ( bw == BW_20 )
+ rate_pwr = ch->PwrHT20[4];
+ else if ( bw == BW_40 )
+ rate_pwr = ch->PwrHT40[4];
+ break;
+ case SKU_PHYMODE_HT_MCS6_MCS7:
+ case SKU_PHYMODE_STBC_MCS6_MCS7:
+ if ( bw == BW_20 )
+ rate_pwr = ch->PwrHT20[6];
+ else if ( bw == BW_40 )
+ rate_pwr = ch->PwrHT40[6];
+ break;
+ case SKU_PHYMODE_HT_MCS8_MCS9:
+ if ( bw == BW_20 )
+ rate_pwr = ch->PwrHT20[8];
+ else if ( bw == BW_40 )
+ rate_pwr = ch->PwrHT40[8];
+ break;
+ case SKU_PHYMODE_HT_MCS10_MCS11:
+ if ( bw == BW_20 )
+ rate_pwr = ch->PwrHT20[10];
+ else if ( bw == BW_40 )
+ rate_pwr = ch->PwrHT40[10];
+ break;
+ case SKU_PHYMODE_HT_MCS12_MCS13:
+ if ( bw == BW_20 )
+ rate_pwr = ch->PwrHT20[12];
+ else if ( bw == BW_40 )
+ rate_pwr = ch->PwrHT40[12];
+ break;
+ case SKU_PHYMODE_HT_MCS14_MCS15:
+ if ( bw == BW_20 )
+ rate_pwr = ch->PwrHT20[14];
+ else if ( bw == BW_40 )
+ rate_pwr = ch->PwrHT40[14];
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ }
+
+ ch = ch->pNext;
+ }
+
+ pwr_diff = GetSkuPAModePwr(pAd, phymode) + (pAd->SingleSkuRatePwrDiff[phymode] << 12) + 2048;
+ pwr_diff = pwr_diff >> 12;
+ max_pwr = pAd->DefaultTargetPwr + pwr_diff;
+
+ if ( rate_pwr > max_pwr )
+ rate_pwr = max_pwr;
+
+ return rate_pwr;
+
+}
+
+
+VOID UpdateSkuRatePwr(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR channel,
+ IN UCHAR bw,
+ IN CHAR base_pwr)
+{
+ INT32 sku_rate_pwr;
+ INT32 rate_pwr;
+ INT32 mcs_digital_pwr, pa_mode_pwr, diff_pwr;
+ UINT32 data, Adata, Gdata;
+ UCHAR BBPR4, BBPR178;
+ UCHAR i;
+ CHAR rate_table[18];
+
+ printk("channel = %d, bw = %d\n", channel, bw);
+
+ for ( i = 0 ; i < 18; i++ )
+ {
+ sku_rate_pwr = GetSkuRatePwr(pAd, i, channel, bw);
+ printk("sku_rate_pwr = %d", sku_rate_pwr);
+ sku_rate_pwr = sku_rate_pwr << 12; // sku_rate_power * 4096
+ printk("\tsku_rate_pwr = %d\n", sku_rate_pwr);
+
+ if ( i < SKU_PHYMODE_CCK_5M_11M )
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPR4);
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R178, &BBPR178);
+ if ( BBPR4 & 0x20 )
+ {
+ if ( BBPR178 == 0 )
+ {
+ mcs_digital_pwr = 9830; // 8192 * 1.2
+ }
+ else
+ {
+ mcs_digital_pwr = 18022; // 8192 * 2.2
+ }
+ }
+ else
+ {
+ if ( BBPR178 == 0 )
+ {
+ mcs_digital_pwr = 24576; // 8192 * 3
+ }
+ else
+ {
+ mcs_digital_pwr = 819; /// 8192 * 0.1
+ }
+
+ }
+ }
+ else
+ {
+ mcs_digital_pwr = 0;
+ }
+
+ pa_mode_pwr = GetSkuPAModePwr(pAd, i);
+
+ printk("base_pwr = %d", base_pwr);
+ rate_pwr = base_pwr << 12;
+ printk("\t base_pwr = %d\n", rate_pwr);
+ printk("mcs_digital_pwr = %d\n", mcs_digital_pwr);
+ printk("pa_mode_pwr = %d\n", pa_mode_pwr);
+ rate_pwr = rate_pwr + mcs_digital_pwr + pa_mode_pwr;
+ printk("rate_pwr = %d\n", rate_pwr);
+ diff_pwr = sku_rate_pwr - rate_pwr;
+ printk("diff_pwr = %d", diff_pwr);
+ diff_pwr = diff_pwr >> 12;
+ printk("\tdiff_pwr = %d\n", diff_pwr);
+
+ rate_table[i] = diff_pwr -1;
+ }
+
+ for ( i = 0 ; i < 5; i++ )
+ {
+ data = 0;
+ Adata = 0;
+ Gdata = 0;
+
+ data = (rate_table[i*4] & 0x3F )+ ((rate_table[i*4 + 1] &0x3F) << 8);
+ Adata = ((rate_table[i*4] + pAd->chipCap.Apwrdelta ) & 0x3F )+ ( ((rate_table[i*4 + 1] + pAd->chipCap.Apwrdelta) & 0x3F) << 8);
+ Gdata = ((rate_table[i*4] + pAd->chipCap.Gpwrdelta ) & 0x3F ) + ( ((rate_table[i*4 + 1] + pAd->chipCap.Gpwrdelta) & 0x3F) << 8);
+
+ if ( i != 4 )
+ {
+ data |= ((rate_table[i*4 + 2] &0x3F) << 16 )+ ((rate_table[i*4 + 3] & 0x3F) << 24);
+ Adata |= ( ((rate_table[i*4 + 2] + pAd->chipCap.Apwrdelta ) & 0x3F) << 16) + ( ((rate_table[i*4 + 3] + pAd->chipCap.Apwrdelta) & 0x3F) << 24);
+ Gdata |= ( ((rate_table[i*4 + 2] + pAd->chipCap.Gpwrdelta ) & 0x3F) << 16) + ( ((rate_table[i*4 + 3] + pAd->chipCap.Gpwrdelta) & 0x3F) << 24);
+ }
+
+ /* For 20M/40M Power Delta issue */
+ pAd->Tx20MPwrCfgABand[i] = data;
+ pAd->Tx20MPwrCfgGBand[i] = data;
+ pAd->Tx40MPwrCfgABand[i] = Adata;
+ pAd->Tx40MPwrCfgGBand[i] = Gdata;
+
+ RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, data);
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%08x, Adata = %08x, Gdata = %08x \n", data, Adata, Gdata));
+ }
+
+ /* Extra set MAC registers to compensate Tx power if any */
+ RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(pAd);
+
+}
+
+
+#endif /* SINGLE_SKU_V2 */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_radar.c b/cleopatre/devkit/mt7601udrv/common/cmm_radar.c
new file mode 100644
index 0000000000..c13f1e07e3
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_radar.c
@@ -0,0 +1,329 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ cmm_radar.c
+
+ Abstract:
+ CS/DFS common functions.
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+*/
+#include "rt_config.h"
+
+/*----- 802.11H -----*/
+
+/* Periodic Radar detection, switch channel will occur in RTMPHandleTBTTInterrupt()*/
+/* Before switch channel, driver needs doing channel switch announcement.*/
+VOID RadarDetectPeriodic(
+ IN PRTMP_ADAPTER pAd)
+{
+ /* need to check channel availability, after switch channel*/
+ if (pAd->Dot11_H.RDMode != RD_SILENCE_MODE)
+ return;
+
+ /* channel availability check time is 60sec, use 65 for assurance*/
+ if (pAd->Dot11_H.RDCount++ > pAd->Dot11_H.ChMovingTime)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Not found radar signal, start send beacon and radar detection in service monitor\n\n"));
+ AsicEnableBssSync(pAd);
+ pAd->Dot11_H.RDMode = RD_NORMAL_MODE;
+ return;
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Radar channel check routine
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ TRUE need to do radar detect
+ FALSE need not to do radar detect
+
+ ========================================================================
+*/
+BOOLEAN RadarChannelCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Ch)
+{
+ INT i;
+ BOOLEAN result = FALSE;
+
+ for (i=0; i<pAd->ChannelListNum; i++)
+ {
+ if (Ch == pAd->ChannelList[i].Channel)
+ {
+ result = pAd->ChannelList[i].DfsReq;
+ break;
+ }
+ }
+
+ return result;
+}
+
+ULONG JapRadarType(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG i;
+ const UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
+
+ if (pAd->CommonCfg.RDDurRegion != JAP)
+ {
+ return pAd->CommonCfg.RDDurRegion;
+ }
+
+ for (i=0; i<15; i++)
+ {
+ if (pAd->CommonCfg.Channel == Channel[i])
+ {
+ break;
+ }
+ }
+
+ if (i < 4)
+ return JAP_W53;
+ else if (i < 15)
+ return JAP_W56;
+ else
+ return JAP; /* W52*/
+
+}
+
+#ifdef CONFIG_AP_SUPPORT
+/*
+ ========================================================================
+
+ Routine Description:
+ Channel switching count down process upon radar detection
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ ========================================================================
+*/
+VOID ChannelSwitchingCountDownProc(
+ IN PRTMP_ADAPTER pAd)
+{
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():Channel Switching...(%d/%d)\n",
+ __FUNCTION__, pAd->Dot11_H.CSCount, pAd->Dot11_H.CSPeriod));
+
+ pAd->Dot11_H.CSCount++;
+ if (pAd->Dot11_H.CSCount >= pAd->Dot11_H.CSPeriod)
+ {
+#ifdef DFS_SUPPORT
+ pAd->CommonCfg.RadarDetect.DFSAPRestart = 1;
+ schedule_dfs_task(pAd);
+#else
+ APStop(pAd);
+ APStartUp(pAd);
+#endif /* !DFS_SUPPORT */
+ }
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+/*
+ ==========================================================================
+ Description:
+ Set channel switch Period
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_CSPeriod_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ pAd->Dot11_H.CSPeriod = (USHORT) simple_strtol(arg, 0, 10);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_CSPeriod_Proc::(CSPeriod=%d)\n", pAd->Dot11_H.CSPeriod));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ change channel moving time for DFS testing.
+
+ Arguments:
+ pAdapter Pointer to our adapter
+ wrq Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ Usage:
+ 1.) iwpriv ra0 set ChMovTime=[value]
+ ==========================================================================
+*/
+INT Set_ChMovingTime_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UINT8 Value;
+
+ Value = (UINT8) simple_strtol(arg, 0, 10);
+
+ pAd->Dot11_H.ChMovingTime = Value;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: %d\n", __FUNCTION__,
+ pAd->Dot11_H.ChMovingTime));
+
+ return TRUE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Reset channel block status.
+ Arguments:
+ pAd Pointer to our adapter
+ arg Not used
+
+ Return Value:
+ None
+
+ Note:
+ Usage:
+ 1.) iwpriv ra0 set ChMovTime=[value]
+ ==========================================================================
+*/
+INT Set_BlockChReset_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ INT i;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Reset channel block status.\n", __FUNCTION__));
+
+ for (i=0; i<pAd->ChannelListNum; i++)
+ pAd->ChannelList[i].RemainingTimeForUse = 0;
+
+ return TRUE;
+}
+
+
+#if defined(DFS_SUPPORT) || defined(CARRIER_DETECTION_SUPPORT)
+
+INT Set_RadarShow_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+#ifdef DFS_SUPPORT
+ int i;
+ UINT8 idx;
+ PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
+ PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam;
+ PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam;
+
+ printk("DFSUseTasklet = %d\n", pRadarDetect->use_tasklet);
+ printk("McuRadarDebug = %x\n", (unsigned int)pRadarDetect->McuRadarDebug);
+ printk("PollTime = %d\n", pRadarDetect->PollTime);
+ printk("ChEnable = %d (0x%x)\n", pDfsProgramParam->ChEnable, pDfsProgramParam->ChEnable);
+ printk("DeltaDelay = %d\n", pDfsProgramParam->DeltaDelay);
+ printk("Fcc5Thrd = %d\n", pDfsSwParam->fcc_5_threshold);
+ printk("PeriodErr = %d\n", pDfsSwParam->dfs_period_err);
+ printk("MaxPeriod = %d\n", (unsigned int)pDfsSwParam->dfs_max_period);
+ printk("Ch0LErr = %d\n", pDfsSwParam->dfs_width_ch0_err_L);
+ printk("Ch0HErr = %d\n", pDfsSwParam->dfs_width_ch0_err_H);
+ printk("Ch1Shift = %d\n", pDfsSwParam->dfs_width_diff_ch1_Shift);
+ printk("Ch2Shift = %d\n", pDfsSwParam->dfs_width_diff_ch2_Shift);
+ /*printk("CeSwCheck = %d\n", pAd->CommonCfg.ce_sw_check);*/
+ /*printk("CEStagCheck = %d\n", pAd->CommonCfg.ce_staggered_check);*/
+ /*printk("HWDFSDisabled = %d\n", pAd->CommonCfg.hw_dfs_disabled);*/
+ printk("DfsRssiHigh = %d\n", pRadarDetect->DfsRssiHigh);
+ printk("DfsRssiLow = %d\n", pRadarDetect->DfsRssiLow);
+ printk("DfsSwDisable = %u\n", pRadarDetect->bDfsSwDisable);
+ printk("CheckLoop = %d\n", pDfsSwParam->dfs_check_loop);
+ printk("DeclareThres = %d\n", pDfsSwParam->dfs_declare_thres);
+ for (i =0; i < pRadarDetect->fdf_num; i++)
+ {
+ printk("ChBusyThrd[%d] = %d\n", i, pRadarDetect->ch_busy_threshold[i]);
+ printk("RssiThrd[%d] = %d\n", i, pRadarDetect->rssi_threshold[i]);
+ }
+ for (idx=0; idx < pAd->chipCap.DfsEngineNum; idx++)
+ printk("sw_idx[%u] = %u\n", idx, pDfsSwParam->sw_idx[idx]);
+ for (idx=0; idx < pAd->chipCap.DfsEngineNum; idx++)
+ printk("hw_idx[%u] = %u\n", idx, pDfsSwParam->hw_idx[idx]);
+#ifdef DFS_DEBUG
+ printk("Total[0] = %lu\n", pDfsSwParam->TotalEntries[0]);
+ printk("Total[1] = %lu\n", pDfsSwParam->TotalEntries[1]);
+ printk("Total[2] = %lu\n", pDfsSwParam->TotalEntries[2]);
+ printk("Total[3] = %lu\n", pDfsSwParam->TotalEntries[3]);
+
+ pDfsSwParam->TotalEntries[0] = pDfsSwParam->TotalEntries[1] = pDfsSwParam->TotalEntries[2] = pDfsSwParam->TotalEntries[3] = 0;
+
+ printk("T_Matched_2 = %lu\n", pDfsSwParam->T_Matched_2);
+ printk("T_Matched_3 = %lu\n", pDfsSwParam->T_Matched_3);
+ printk("T_Matched_4 = %lu\n", pDfsSwParam->T_Matched_4);
+ printk("T_Matched_5 = %lu\n", pDfsSwParam->T_Matched_5);
+#endif /* DFS_DEBUG */
+
+ printk("pAd->Dot11_H.ChMovingTime = %d\n", pAd->Dot11_H.ChMovingTime);
+ printk("pAd->Dot11_H.RDMode = %d\n", pAd->Dot11_H.RDMode);
+#endif /* DFS_SUPPORT */
+
+#ifdef CARRIER_DETECTION_SUPPORT
+ printk("pAd->CommonCfg.CarrierDetect.CD_State = %d\n", pAd->CommonCfg.CarrierDetect.CD_State);
+ printk("pAd->CommonCfg.CarrierDetect.criteria = %d\n", pAd->CommonCfg.CarrierDetect.criteria);
+ printk("pAd->CommonCfg.CarrierDetect.Delta = %d\n", pAd->CommonCfg.CarrierDetect.delta);
+ printk("pAd->CommonCfg.CarrierDetect.DivFlag = %d\n", pAd->CommonCfg.CarrierDetect.div_flag);
+ printk("pAd->CommonCfg.CarrierDetect.Threshold = %d(0x%x)\n", pAd->CommonCfg.CarrierDetect.threshold, pAd->CommonCfg.CarrierDetect.threshold);
+#endif /* CARRIER_DETECTION_SUPPORT */
+
+ return TRUE;
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Control CCK_MRC Status
+ Arguments:
+ pAd Pointer to our adapter
+ Return Value:
+
+ ========================================================================
+*/
+VOID CckMrcStatusCtrl(IN PRTMP_ADAPTER pAd)
+{
+}
+
+
+/*
+ ========================================================================
+ Routine Description:
+ Enhance DFS/CS when using GLRT.
+ Arguments:
+ pAd Pointer to our adapter
+ Return Value:
+
+ ========================================================================
+*/
+VOID RadarGLRTCompensate(IN PRTMP_ADAPTER pAd)
+{
+}
+#endif /*defined(DFS_SUPPORT) || defined(CARRIER_DETECTION_SUPPORT) */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_sanity.c b/cleopatre/devkit/mt7601udrv/common/cmm_sanity.c
new file mode 100644
index 0000000000..86053effc3
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_sanity.c
@@ -0,0 +1,2162 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ sanity.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John Chang 2004-09-01 add WMM support
+*/
+#include "rt_config.h"
+
+extern UCHAR CISCO_OUI[];
+
+extern UCHAR WPA_OUI[];
+extern UCHAR RSN_OUI[];
+extern UCHAR WME_INFO_ELEM[];
+extern UCHAR WME_PARM_ELEM[];
+extern UCHAR RALINK_OUI[];
+extern UCHAR BROADCOM_OUI[];
+extern UCHAR WPS_OUI[];
+
+
+
+typedef struct wsc_ie_probreq_data
+{
+ UCHAR ssid[32];
+ UCHAR macAddr[6];
+ UCHAR data[2];
+} WSC_IE_PROBREQ_DATA;
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN MlmeAddBAReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2)
+{
+ PMLME_ADDBA_REQ_STRUCT pInfo;
+
+ pInfo = (MLME_ADDBA_REQ_STRUCT *)Msg;
+
+ if ((MsgLen != sizeof(MLME_ADDBA_REQ_STRUCT)))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - message lenght not correct.\n"));
+ return FALSE;
+ }
+
+ if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - The peer Mac is not associated yet.\n"));
+ return FALSE;
+ }
+
+ /*
+ if ((pInfo->BaBufSize > MAX_RX_REORDERBUF) || (pInfo->BaBufSize < 2))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - Rx Reordering buffer too big or too small\n"));
+ return FALSE;
+ }
+ */
+
+ if ((pInfo->pAddr[0]&0x01) == 0x01)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - broadcast address not support BA\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN MlmeDelBAReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen)
+{
+ MLME_DELBA_REQ_STRUCT *pInfo;
+ pInfo = (MLME_DELBA_REQ_STRUCT *)Msg;
+
+ if ((MsgLen != sizeof(MLME_DELBA_REQ_STRUCT)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - message lenght not correct.\n"));
+ return FALSE;
+ }
+
+ if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer Mac is not associated yet.\n"));
+ return FALSE;
+ }
+
+ if ((pInfo->TID & 0xf0))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer TID is incorrect.\n"));
+ return FALSE;
+ }
+
+ if (NdisEqualMemory(pAd->MacTab.Content[pInfo->Wcid].Addr, pInfo->Addr, MAC_ADDR_LEN) == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - the peer addr dosen't exist.\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN PeerAddBAReqActionSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pMsg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2)
+{
+ PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;
+ PFRAME_ADDBA_REQ pAddFrame;
+ pAddFrame = (PFRAME_ADDBA_REQ)(pMsg);
+ if (MsgLen < (sizeof(FRAME_ADDBA_REQ)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request frame length size = %ld incorrect\n", MsgLen));
+ return FALSE;
+ }
+ /* we support immediate BA.*/
+#ifdef UNALIGNMENT_SUPPORT
+ {
+ BA_PARM tmpBaParm;
+
+ NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&pAddFrame->BaParm), sizeof(BA_PARM));
+ *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm));
+ NdisMoveMemory((PUCHAR)(&pAddFrame->BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM));
+ }
+#else
+ *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm));
+#endif
+ pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue);
+ pAddFrame->BaStartSeq.word = cpu2le16(pAddFrame->BaStartSeq.word);
+
+ COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+
+ if (pAddFrame->BaParm.BAPolicy != IMMED_BA)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy));
+ DBGPRINT(RT_DEBUG_ERROR,("ADDBA Request. tid=%x, Bufsize=%x, AMSDUSupported=%x \n", pAddFrame->BaParm.TID, pAddFrame->BaParm.BufSize, pAddFrame->BaParm.AMSDUSupported));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN PeerAddBARspActionSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pMsg,
+ IN ULONG MsgLen)
+{
+ /*PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;*/
+ PFRAME_ADDBA_RSP pAddFrame;
+
+ pAddFrame = (PFRAME_ADDBA_RSP)(pMsg);
+ if (MsgLen < (sizeof(FRAME_ADDBA_RSP)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response frame length size = %ld incorrect\n", MsgLen));
+ return FALSE;
+ }
+ /* we support immediate BA.*/
+#ifdef UNALIGNMENT_SUPPORT
+ {
+ BA_PARM tmpBaParm;
+
+ NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&pAddFrame->BaParm), sizeof(BA_PARM));
+ *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm));
+ NdisMoveMemory((PUCHAR)(&pAddFrame->BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM));
+ }
+#else
+ *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm));
+#endif
+ pAddFrame->StatusCode = cpu2le16(pAddFrame->StatusCode);
+ pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue);
+
+ if (pAddFrame->BaParm.BAPolicy != IMMED_BA)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Response Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy));
+ return FALSE;
+ }
+
+ return TRUE;
+
+}
+
+BOOLEAN PeerDelBAActionSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN VOID *pMsg,
+ IN ULONG MsgLen )
+{
+ /*PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;*/
+ PFRAME_DELBA_REQ pDelFrame;
+ if (MsgLen != (sizeof(FRAME_DELBA_REQ)))
+ return FALSE;
+
+ if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+ return FALSE;
+
+ pDelFrame = (PFRAME_DELBA_REQ)(pMsg);
+
+ *(USHORT *)(&pDelFrame->DelbaParm) = cpu2le16(*(USHORT *)(&pDelFrame->DelbaParm));
+ pDelFrame->ReasonCode = cpu2le16(pDelFrame->ReasonCode);
+
+ return TRUE;
+}
+
+
+BOOLEAN PeerBeaconAndProbeRspSanity_Old(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ IN UCHAR MsgChannel,
+ OUT PUCHAR pAddr2,
+ OUT PUCHAR pBssid,
+ OUT CHAR Ssid[],
+ OUT UCHAR *pSsidLen,
+ OUT UCHAR *pBssType,
+ OUT USHORT *pBeaconPeriod,
+ OUT UCHAR *pChannel,
+ OUT UCHAR *pNewChannel,
+ OUT LARGE_INTEGER *pTimestamp,
+ OUT CF_PARM *pCfParm,
+ OUT USHORT *pAtimWin,
+ OUT USHORT *pCapabilityInfo,
+ OUT UCHAR *pErp,
+ OUT UCHAR *pDtimCount,
+ OUT UCHAR *pDtimPeriod,
+ OUT UCHAR *pBcastFlag,
+ OUT UCHAR *pMessageToMe,
+ OUT UCHAR SupRate[],
+ OUT UCHAR *pSupRateLen,
+ OUT UCHAR ExtRate[],
+ OUT UCHAR *pExtRateLen,
+ OUT UCHAR *pCkipFlag,
+ OUT UCHAR *pAironetCellPowerLimit,
+ OUT PEDCA_PARM pEdcaParm,
+ OUT PQBSS_LOAD_PARM pQbssLoad,
+ OUT PQOS_CAPABILITY_PARM pQosCapability,
+ OUT ULONG *pRalinkIe,
+ OUT UCHAR *pHtCapabilityLen,
+ OUT HT_CAPABILITY_IE *pHtCapability,
+ OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo,
+ OUT UCHAR *AddHtInfoLen,
+ OUT ADD_HT_INFO_IE *AddHtInfo,
+ OUT UCHAR *NewExtChannelOffset, /* Ht extension channel offset(above or below)*/
+ OUT USHORT *LengthVIE,
+ OUT PNDIS_802_11_VARIABLE_IEs pVIE)
+{
+ UCHAR *Ptr;
+ PFRAME_802_11 pFrame;
+ PEID_STRUCT pEid;
+ UCHAR SubType;
+ UCHAR Sanity;
+ /*UCHAR ECWMin, ECWMax;*/
+ /*MAC_CSR9_STRUC Csr9;*/
+ ULONG Length = 0;
+ UCHAR *pPeerWscIe = NULL;
+ INT PeerWscIeLen = 0;
+ UCHAR LatchRfChannel = 0;
+
+
+ /*
+ For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel
+ 1. If the AP is 11n enabled, then check the control channel.
+ 2. If the AP didn't have any info about channel, use the channel we received this
+ frame as the channel. (May inaccuracy!!)
+ */
+ UCHAR CtrlChannel = 0;
+
+
+ os_alloc_mem(NULL, &pPeerWscIe, 512);
+ /* Add for 3 necessary EID field check*/
+ Sanity = 0;
+
+ *pAtimWin = 0;
+ *pErp = 0;
+ *pDtimCount = 0;
+ *pDtimPeriod = 0;
+ *pBcastFlag = 0;
+ *pMessageToMe = 0;
+ *pExtRateLen = 0;
+ *pCkipFlag = 0; /* Default of CkipFlag is 0*/
+ *pAironetCellPowerLimit = 0xFF; /* Default of AironetCellPowerLimit is 0xFF*/
+ *LengthVIE = 0; /* Set the length of VIE to init value 0*/
+ *pHtCapabilityLen = 0; /* Set the length of VIE to init value 0*/
+ *AddHtInfoLen = 0; /* Set the length of VIE to init value 0*/
+ NdisZeroMemory(pExtCapInfo, sizeof(EXT_CAP_INFO_ELEMENT));
+ *pRalinkIe = 0;
+ *pNewChannel = 0;
+ *NewExtChannelOffset = 0xff; /*Default 0xff means no such IE*/
+ pCfParm->bValid = FALSE; /* default: no IE_CF found*/
+ pQbssLoad->bValid = FALSE; /* default: no IE_QBSS_LOAD found*/
+ pEdcaParm->bValid = FALSE; /* default: no IE_EDCA_PARAMETER found*/
+ pQosCapability->bValid = FALSE; /* default: no IE_QOS_CAPABILITY found*/
+
+ pFrame = (PFRAME_802_11)Msg;
+
+ /* get subtype from header*/
+ SubType = (UCHAR)pFrame->Hdr.FC.SubType;
+
+ /* get Addr2 and BSSID from header*/
+ COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+ COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3);
+
+/* hex_dump("Beacon", Msg, MsgLen);*/
+
+ Ptr = pFrame->Octet;
+ Length += LENGTH_802_11;
+
+ /* get timestamp from payload and advance the pointer*/
+ NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN);
+
+ pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart);
+ pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart);
+
+ Ptr += TIMESTAMP_LEN;
+ Length += TIMESTAMP_LEN;
+
+ /* get beacon interval from payload and advance the pointer*/
+ NdisMoveMemory(pBeaconPeriod, Ptr, 2);
+ Ptr += 2;
+ Length += 2;
+
+ /* get capability info from payload and advance the pointer*/
+ NdisMoveMemory(pCapabilityInfo, Ptr, 2);
+ Ptr += 2;
+ Length += 2;
+
+ if (CAP_IS_ESS_ON(*pCapabilityInfo))
+ *pBssType = BSS_INFRA;
+ else
+ *pBssType = BSS_ADHOC;
+
+ pEid = (PEID_STRUCT) Ptr;
+
+ /* get variable fields from payload and advance the pointer*/
+ while ((Length + 2 + pEid->Len) <= MsgLen)
+ {
+
+ /* Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow.*/
+ if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s() - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n",
+ __FUNCTION__, (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN));
+ break;
+ }
+
+ switch(pEid->Eid)
+ {
+ case IE_SSID:
+ /* Already has one SSID EID in this beacon, ignore the second one*/
+ if (Sanity & 0x1)
+ break;
+ if(pEid->Len <= MAX_LEN_OF_SSID)
+ {
+ NdisMoveMemory(Ssid, pEid->Octet, pEid->Len);
+ *pSsidLen = pEid->Len;
+ Sanity |= 0x1;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_SSID (len=%d)\n", __FUNCTION__, pEid->Len));
+ goto SanityCheck;
+ }
+ break;
+
+ case IE_SUPP_RATES:
+ if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
+ {
+ Sanity |= 0x2;
+ NdisMoveMemory(SupRate, pEid->Octet, pEid->Len);
+ *pSupRateLen = pEid->Len;
+
+ /*
+ TODO: 2004-09-14 not a good design here, cause it exclude extra
+ rates from ScanTab. We should report as is. And filter out
+ unsupported rates in MlmeAux
+ */
+ /* Check against the supported rates*/
+ /* RTMPCheckRates(pAd, SupRate, pSupRateLen);*/
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_SUPP_RATES (len=%d)\n",__FUNCTION__, pEid->Len));
+ goto SanityCheck;
+ }
+ break;
+
+ case IE_HT_CAP:
+ if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension.!!*/
+ {
+ NdisMoveMemory(pHtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE));
+ *pHtCapabilityLen = SIZE_HT_CAP_IE; /* Nnow we only support 26 bytes.*/
+
+ *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
+#ifdef UNALIGNMENT_SUPPORT
+ {
+ EXT_HT_CAP_INFO extHtCapInfo;
+ NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO));
+ *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo));
+ NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO));
+ }
+#else
+ *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
+#endif /* UNALIGNMENT_SUPPORT */
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_HT_CAP. pEid->Len = %d\n", __FUNCTION__, pEid->Len));
+ }
+
+ break;
+ case IE_ADD_HT:
+ if (pEid->Len >= sizeof(ADD_HT_INFO_IE))
+ {
+ /*
+ This IE allows extension, but we can ignore extra bytes beyond our
+ knowledge , so only copy first sizeof(ADD_HT_INFO_IE)
+ */
+ NdisMoveMemory(AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE));
+ *AddHtInfoLen = SIZE_ADD_HT_INFO_IE;
+
+ CtrlChannel = AddHtInfo->ControlChan;
+
+ *(USHORT *)(&AddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo2));
+ *(USHORT *)(&AddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo3));
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_ADD_HT. \n", __FUNCTION__));
+ }
+
+ break;
+ case IE_SECONDARY_CH_OFFSET:
+ if (pEid->Len == 1)
+ {
+ *NewExtChannelOffset = pEid->Octet[0];
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_SECONDARY_CH_OFFSET. \n", __FUNCTION__));
+ }
+
+ break;
+ case IE_FH_PARM:
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(IE_FH_PARM) \n", __FUNCTION__));
+ break;
+
+ case IE_DS_PARM:
+ if(pEid->Len == 1)
+ {
+ *pChannel = *pEid->Octet;
+ Sanity |= 0x4;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_DS_PARM (len=%d)\n",__FUNCTION__,pEid->Len));
+ goto SanityCheck;
+ }
+ break;
+
+ case IE_CF_PARM:
+ if(pEid->Len == 6)
+ {
+ pCfParm->bValid = TRUE;
+ pCfParm->CfpCount = pEid->Octet[0];
+ pCfParm->CfpPeriod = pEid->Octet[1];
+ pCfParm->CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3];
+ pCfParm->CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5];
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_CF_PARM\n", __FUNCTION__));
+ if (pPeerWscIe)
+ os_free_mem(NULL, pPeerWscIe);
+ return FALSE;
+ }
+ break;
+
+ case IE_IBSS_PARM:
+ if(pEid->Len == 2)
+ {
+ NdisMoveMemory(pAtimWin, pEid->Octet, pEid->Len);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_IBSS_PARM\n", __FUNCTION__));
+ if (pPeerWscIe)
+ os_free_mem(NULL, pPeerWscIe);
+ return FALSE;
+ }
+ break;
+
+ case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
+ if(pEid->Len == 3)
+ {
+ *pNewChannel = pEid->Octet[1]; /*extract new channel number*/
+ }
+ break;
+
+ /*
+ New for WPA
+ CCX v2 has the same IE, we need to parse that too
+ Wifi WMM use the same IE vale, need to parse that too
+ */
+ /* case IE_WPA:*/
+ case IE_VENDOR_SPECIFIC:
+ /* Check the OUI version, filter out non-standard usage*/
+ if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7))
+ {
+ if (pEid->Octet[3] != 0)
+ *pRalinkIe = pEid->Octet[3];
+ else
+ *pRalinkIe = 0xf0000000; /* Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag.*/
+ }
+ else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
+ {
+ /* Copy to pVIE which will report to bssid list.*/
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ }
+ else if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24))
+ {
+ PUCHAR ptr;
+ int i;
+
+ /* parsing EDCA parameters*/
+ pEdcaParm->bValid = TRUE;
+ pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/
+ pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/
+ pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/
+ pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f;
+ pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0;
+ ptr = &pEid->Octet[8];
+ for (i=0; i<4; i++)
+ {
+ UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX*/
+ pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM*/
+ pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN*/
+ pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; /* b0~4 is Cwmin*/
+ pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; /* b5~8 is Cwmax*/
+ pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); /* in unit of 32-us*/
+ ptr += 4; /* point to next AC*/
+ }
+ }
+ else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7))
+ {
+ /* parsing EDCA parameters*/
+ pEdcaParm->bValid = TRUE;
+ pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/
+ pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/
+ pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/
+ pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f;
+ pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0;
+
+ /* use default EDCA parameter*/
+ pEdcaParm->bACM[QID_AC_BE] = 0;
+ pEdcaParm->Aifsn[QID_AC_BE] = 3;
+ pEdcaParm->Cwmin[QID_AC_BE] = CW_MIN_IN_BITS;
+ pEdcaParm->Cwmax[QID_AC_BE] = CW_MAX_IN_BITS;
+ pEdcaParm->Txop[QID_AC_BE] = 0;
+
+ pEdcaParm->bACM[QID_AC_BK] = 0;
+ pEdcaParm->Aifsn[QID_AC_BK] = 7;
+ pEdcaParm->Cwmin[QID_AC_BK] = CW_MIN_IN_BITS;
+ pEdcaParm->Cwmax[QID_AC_BK] = CW_MAX_IN_BITS;
+ pEdcaParm->Txop[QID_AC_BK] = 0;
+
+ pEdcaParm->bACM[QID_AC_VI] = 0;
+ pEdcaParm->Aifsn[QID_AC_VI] = 2;
+ pEdcaParm->Cwmin[QID_AC_VI] = CW_MIN_IN_BITS-1;
+ pEdcaParm->Cwmax[QID_AC_VI] = CW_MAX_IN_BITS;
+ pEdcaParm->Txop[QID_AC_VI] = 96; /* AC_VI: 96*32us ~= 3ms*/
+
+ pEdcaParm->bACM[QID_AC_VO] = 0;
+ pEdcaParm->Aifsn[QID_AC_VO] = 2;
+ pEdcaParm->Cwmin[QID_AC_VO] = CW_MIN_IN_BITS-2;
+ pEdcaParm->Cwmax[QID_AC_VO] = CW_MAX_IN_BITS-1;
+ pEdcaParm->Txop[QID_AC_VO] = 48; /* AC_VO: 48*32us ~= 1.5ms*/
+ }
+ else if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4)
+ )
+ {
+ if (PeerWscIeLen >= 512)
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: PeerWscIeLen = %d (>= 512)\n", __FUNCTION__, PeerWscIeLen));
+ if (pPeerWscIe && (PeerWscIeLen < 512))
+ {
+ NdisMoveMemory(pPeerWscIe+PeerWscIeLen, pEid->Octet+4, pEid->Len-4);
+ PeerWscIeLen += (pEid->Len - 4);
+ }
+
+
+
+ }
+
+
+ break;
+
+ case IE_EXT_SUPP_RATES:
+ if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
+ {
+ NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len);
+ *pExtRateLen = pEid->Len;
+
+ /*
+ TODO: 2004-09-14 not a good design here, cause it exclude extra rates
+ from ScanTab. We should report as is. And filter out unsupported
+ rates in MlmeAux
+ */
+ /* Check against the supported rates*/
+ /* RTMPCheckRates(pAd, ExtRate, pExtRateLen);*/
+ }
+ break;
+
+ case IE_ERP:
+ if (pEid->Len == 1)
+ {
+ *pErp = (UCHAR)pEid->Octet[0];
+ }
+ break;
+
+ case IE_AIRONET_CKIP:
+ /*
+ 0. Check Aironet IE length, it must be larger or equal to 28
+ Cisco AP350 used length as 28
+ Cisco AP12XX used length as 30
+ */
+ if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2))
+ break;
+
+ /* 1. Copy CKIP flag byte to buffer for process*/
+ *pCkipFlag = *(pEid->Octet + 8);
+ break;
+
+ case IE_AP_TX_POWER:
+ /* AP Control of Client Transmit Power*/
+ /*0. Check Aironet IE length, it must be 6*/
+ if (pEid->Len != 0x06)
+ break;
+
+ /* Get cell power limit in dBm*/
+ if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1)
+ *pAironetCellPowerLimit = *(pEid->Octet + 4);
+ break;
+
+ /* WPA2 & 802.11i RSN*/
+ case IE_RSN:
+ /* There is no OUI for version anymore, check the group cipher OUI before copying*/
+ if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
+ {
+ /* Copy to pVIE which will report to microsoft bssid list.*/
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ }
+ break;
+#ifdef WAPI_SUPPORT
+ /* WAPI information element*/
+ case IE_WAPI:
+ if (RTMPEqualMemory(pEid->Octet + 4, WAPI_OUI, 3))
+ {
+ /* Copy to pVIE*/
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ }
+ break;
+#endif /* WAPI_SUPPORT */
+
+
+ case IE_QBSS_LOAD:
+ if (pEid->Len == 5)
+ {
+ pQbssLoad->bValid = TRUE;
+ pQbssLoad->StaNum = pEid->Octet[0] + pEid->Octet[1] * 256;
+ pQbssLoad->ChannelUtilization = pEid->Octet[2];
+ pQbssLoad->RemainingAdmissionControl = pEid->Octet[3] + pEid->Octet[4] * 256;
+
+ /* Copy to pVIE*/
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ }
+ break;
+
+
+
+ case IE_EXT_CAPABILITY:
+ if (pEid->Len >= 1)
+ {
+ UCHAR MaxSize;
+ UCHAR MySize = sizeof(EXT_CAP_INFO_ELEMENT);
+
+ MaxSize = min(pEid->Len, MySize);
+
+ NdisMoveMemory(pExtCapInfo,&pEid->Octet[0], MaxSize);
+ }
+ break;
+ default:
+ break;
+ }
+
+ Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len]*/
+ pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+ }
+
+ LatchRfChannel = MsgChannel;
+
+ if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0))
+ {
+ if (CtrlChannel != 0)
+ *pChannel = CtrlChannel;
+ else
+ *pChannel = LatchRfChannel;
+ Sanity |= 0x4;
+ }
+
+ if (pPeerWscIe && (PeerWscIeLen > 0) && (PeerWscIeLen < 512))
+ {
+ UCHAR WscIe[] = {0xdd, 0x00, 0x00, 0x50, 0xF2, 0x04};
+ Ptr = (PUCHAR) pVIE;
+ WscIe[1] = PeerWscIeLen + 4;
+ NdisMoveMemory(Ptr + *LengthVIE, WscIe, 6);
+ NdisMoveMemory(Ptr + *LengthVIE + 6, pPeerWscIe, PeerWscIeLen);
+ *LengthVIE += (PeerWscIeLen + 6);
+ }
+
+
+SanityCheck:
+ if (pPeerWscIe)
+ os_free_mem(NULL, pPeerWscIe);
+
+ if (Sanity != 0x7)
+ {
+ DBGPRINT(RT_DEBUG_LOUD, ("%s() - missing field, Sanity=0x%02x\n", __FUNCTION__, Sanity));
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN PeerBeaconAndProbeRspSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ IN UCHAR MsgChannel,
+ OUT BCN_IE_LIST *ie_list,
+ OUT USHORT *LengthVIE,
+ OUT PNDIS_802_11_VARIABLE_IEs pVIE)
+{
+ UCHAR *Ptr;
+ PFRAME_802_11 pFrame;
+ PEID_STRUCT pEid;
+ UCHAR SubType;
+ UCHAR Sanity;
+ ULONG Length = 0;
+ UCHAR *pPeerWscIe = NULL;
+ INT PeerWscIeLen = 0;
+ UCHAR LatchRfChannel = 0;
+
+
+ /*
+ For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel
+ 1. If the AP is 11n enabled, then check the control channel.
+ 2. If the AP didn't have any info about channel, use the channel we received this
+ frame as the channel. (May inaccuracy!!)
+ */
+ UCHAR CtrlChannel = 0;
+
+
+
+ os_alloc_mem(NULL, &pPeerWscIe, 512);
+ Sanity = 0; /* Add for 3 necessary EID field check*/
+
+ ie_list->AironetCellPowerLimit = 0xFF; /* Default of AironetCellPowerLimit is 0xFF*/
+ ie_list->NewExtChannelOffset = 0xff; /*Default 0xff means no such IE*/
+ *LengthVIE = 0; /* Set the length of VIE to init value 0*/
+
+ pFrame = (PFRAME_802_11)Msg;
+
+ /* get subtype from header*/
+ SubType = (UCHAR)pFrame->Hdr.FC.SubType;
+
+ /* get Addr2 and BSSID from header*/
+ COPY_MAC_ADDR(&ie_list->Addr2[0], pFrame->Hdr.Addr2);
+ COPY_MAC_ADDR(&ie_list->Bssid[0], pFrame->Hdr.Addr3);
+
+ Ptr = pFrame->Octet;
+ Length += LENGTH_802_11;
+
+ /* get timestamp from payload and advance the pointer*/
+ NdisMoveMemory(&ie_list->TimeStamp, Ptr, TIMESTAMP_LEN);
+
+ ie_list->TimeStamp.u.LowPart = cpu2le32(ie_list->TimeStamp.u.LowPart);
+ ie_list->TimeStamp.u.HighPart = cpu2le32(ie_list->TimeStamp.u.HighPart);
+
+ Ptr += TIMESTAMP_LEN;
+ Length += TIMESTAMP_LEN;
+
+ /* get beacon interval from payload and advance the pointer*/
+ NdisMoveMemory(&ie_list->BeaconPeriod, Ptr, 2);
+ Ptr += 2;
+ Length += 2;
+
+ /* get capability info from payload and advance the pointer*/
+ NdisMoveMemory(&ie_list->CapabilityInfo, Ptr, 2);
+ Ptr += 2;
+ Length += 2;
+
+ if (CAP_IS_ESS_ON(ie_list->CapabilityInfo))
+ ie_list->BssType = BSS_INFRA;
+ else
+ ie_list->BssType = BSS_ADHOC;
+
+ pEid = (PEID_STRUCT) Ptr;
+
+ /* get variable fields from payload and advance the pointer*/
+ while ((Length + 2 + pEid->Len) <= MsgLen)
+ {
+
+ /* Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow.*/
+ if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s() - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n",
+ __FUNCTION__, (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN));
+ break;
+ }
+
+ switch(pEid->Eid)
+ {
+ case IE_SSID:
+ /* Already has one SSID EID in this beacon, ignore the second one*/
+ if (Sanity & 0x1)
+ break;
+ if(pEid->Len <= MAX_LEN_OF_SSID)
+ {
+ NdisMoveMemory(&ie_list->Ssid[0], pEid->Octet, pEid->Len);
+ ie_list->SsidLen = pEid->Len;
+ Sanity |= 0x1;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_SSID (len=%d)\n",__FUNCTION__,pEid->Len));
+ goto SanityCheck;
+ }
+ break;
+
+ case IE_SUPP_RATES:
+ if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
+ {
+ Sanity |= 0x2;
+ NdisMoveMemory(&ie_list->SupRate[0], pEid->Octet, pEid->Len);
+ ie_list->SupRateLen = pEid->Len;
+
+ /*
+ TODO: 2004-09-14 not a good design here, cause it exclude extra
+ rates from ScanTab. We should report as is. And filter out
+ unsupported rates in MlmeAux
+ */
+ /* Check against the supported rates*/
+ /* RTMPCheckRates(pAd, SupRate, pSupRateLen);*/
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_SUPP_RATES (len=%d)\n",__FUNCTION__,pEid->Len));
+ goto SanityCheck;
+ }
+ break;
+
+ case IE_HT_CAP:
+ if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension.!!*/
+ {
+ NdisMoveMemory(&ie_list->HtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE));
+ ie_list->HtCapabilityLen = SIZE_HT_CAP_IE; /* Nnow we only support 26 bytes.*/
+
+ *(USHORT *)(&ie_list->HtCapability.HtCapInfo) = cpu2le16(*(USHORT *)(&ie_list->HtCapability.HtCapInfo));
+#ifdef UNALIGNMENT_SUPPORT
+ {
+ EXT_HT_CAP_INFO extHtCapInfo;
+ NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&ie_list->HtCapability.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO));
+ *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo));
+ NdisMoveMemory((PUCHAR)(&ie_list->HtCapability.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO));
+ }
+#else
+ *(USHORT *)(&ie_list->HtCapability.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&ie_list->HtCapability.ExtHtCapInfo));
+#endif /* UNALIGNMENT_SUPPORT */
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_HT_CAP. pEid->Len = %d\n", __FUNCTION__, pEid->Len));
+ }
+
+ break;
+ case IE_ADD_HT:
+ if (pEid->Len >= sizeof(ADD_HT_INFO_IE))
+ {
+ /*
+ This IE allows extension, but we can ignore extra bytes beyond our
+ knowledge , so only copy first sizeof(ADD_HT_INFO_IE)
+ */
+ NdisMoveMemory(&ie_list->AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE));
+ ie_list->AddHtInfoLen = SIZE_ADD_HT_INFO_IE;
+
+ CtrlChannel = ie_list->AddHtInfo.ControlChan;
+
+ *(USHORT *)(&ie_list->AddHtInfo.AddHtInfo2) = cpu2le16(*(USHORT *)(&ie_list->AddHtInfo.AddHtInfo2));
+ *(USHORT *)(&ie_list->AddHtInfo.AddHtInfo3) = cpu2le16(*(USHORT *)(&ie_list->AddHtInfo.AddHtInfo3));
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_ADD_HT. \n", __FUNCTION__));
+ }
+
+ break;
+ case IE_SECONDARY_CH_OFFSET:
+ if (pEid->Len == 1)
+ ie_list->NewExtChannelOffset = pEid->Octet[0];
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_SECONDARY_CH_OFFSET. \n", __FUNCTION__));
+ }
+ break;
+
+ case IE_FH_PARM:
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(IE_FH_PARM) \n", __FUNCTION__));
+ break;
+
+ case IE_DS_PARM:
+ if(pEid->Len == 1)
+ {
+ ie_list->Channel = *pEid->Octet;
+ Sanity |= 0x4;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_DS_PARM (len=%d)\n",__FUNCTION__,pEid->Len));
+ goto SanityCheck;
+ }
+ break;
+
+ case IE_CF_PARM:
+ if(pEid->Len == 6)
+ {
+ ie_list->CfParm.bValid = TRUE;
+ ie_list->CfParm.CfpCount = pEid->Octet[0];
+ ie_list->CfParm.CfpPeriod = pEid->Octet[1];
+ ie_list->CfParm.CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3];
+ ie_list->CfParm.CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5];
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_CF_PARM\n", __FUNCTION__));
+ if (pPeerWscIe)
+ os_free_mem(NULL, pPeerWscIe);
+ return FALSE;
+ }
+ break;
+
+ case IE_IBSS_PARM:
+ if(pEid->Len == 2)
+ {
+ NdisMoveMemory(&ie_list->AtimWin, pEid->Octet, pEid->Len);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_IBSS_PARM\n", __FUNCTION__));
+ if (pPeerWscIe)
+ os_free_mem(NULL, pPeerWscIe);
+ return FALSE;
+ }
+ break;
+
+ case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
+ if(pEid->Len == 3)
+ ie_list->NewChannel = pEid->Octet[1]; /*extract new channel number*/
+ break;
+
+ /*
+ New for WPA
+ CCX v2 has the same IE, we need to parse that too
+ Wifi WMM use the same IE vale, need to parse that too
+ */
+ /* case IE_WPA:*/
+ case IE_VENDOR_SPECIFIC:
+ /* Check the OUI version, filter out non-standard usage*/
+ if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7))
+ {
+ if (pEid->Octet[3] != 0)
+ ie_list->RalinkIe = pEid->Octet[3];
+ else
+ ie_list->RalinkIe = 0xf0000000; /* Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag.*/
+ }
+ else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
+ {
+ /* Copy to pVIE which will report to bssid list.*/
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ }
+ else if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24))
+ {
+ PUCHAR ptr;
+ int i;
+
+ /* parsing EDCA parameters*/
+ ie_list->EdcaParm.bValid = TRUE;
+ ie_list->EdcaParm.bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/
+ ie_list->EdcaParm.bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/
+ ie_list->EdcaParm.bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/
+ ie_list->EdcaParm.EdcaUpdateCount = pEid->Octet[6] & 0x0f;
+ ie_list->EdcaParm.bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0;
+ ptr = &pEid->Octet[8];
+ for (i=0; i<4; i++)
+ {
+ UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX*/
+ ie_list->EdcaParm.bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM*/
+ ie_list->EdcaParm.Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN*/
+ ie_list->EdcaParm.Cwmin[aci] = *(ptr+1) & 0x0f; /* b0~4 is Cwmin*/
+ ie_list->EdcaParm.Cwmax[aci] = *(ptr+1) >> 4; /* b5~8 is Cwmax*/
+ ie_list->EdcaParm.Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); /* in unit of 32-us*/
+ ptr += 4; /* point to next AC*/
+ }
+ }
+ else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7))
+ {
+ /* parsing EDCA parameters*/
+ ie_list->EdcaParm.bValid = TRUE;
+ ie_list->EdcaParm.bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/
+ ie_list->EdcaParm.bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/
+ ie_list->EdcaParm.bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/
+ ie_list->EdcaParm.EdcaUpdateCount = pEid->Octet[6] & 0x0f;
+ ie_list->EdcaParm.bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0;
+
+ /* use default EDCA parameter*/
+ ie_list->EdcaParm.bACM[QID_AC_BE] = 0;
+ ie_list->EdcaParm.Aifsn[QID_AC_BE] = 3;
+ ie_list->EdcaParm.Cwmin[QID_AC_BE] = CW_MIN_IN_BITS;
+ ie_list->EdcaParm.Cwmax[QID_AC_BE] = CW_MAX_IN_BITS;
+ ie_list->EdcaParm.Txop[QID_AC_BE] = 0;
+
+ ie_list->EdcaParm.bACM[QID_AC_BK] = 0;
+ ie_list->EdcaParm.Aifsn[QID_AC_BK] = 7;
+ ie_list->EdcaParm.Cwmin[QID_AC_BK] = CW_MIN_IN_BITS;
+ ie_list->EdcaParm.Cwmax[QID_AC_BK] = CW_MAX_IN_BITS;
+ ie_list->EdcaParm.Txop[QID_AC_BK] = 0;
+
+ ie_list->EdcaParm.bACM[QID_AC_VI] = 0;
+ ie_list->EdcaParm.Aifsn[QID_AC_VI] = 2;
+ ie_list->EdcaParm.Cwmin[QID_AC_VI] = CW_MIN_IN_BITS-1;
+ ie_list->EdcaParm.Cwmax[QID_AC_VI] = CW_MAX_IN_BITS;
+ ie_list->EdcaParm.Txop[QID_AC_VI] = 96; /* AC_VI: 96*32us ~= 3ms*/
+
+ ie_list->EdcaParm.bACM[QID_AC_VO] = 0;
+ ie_list->EdcaParm.Aifsn[QID_AC_VO] = 2;
+ ie_list->EdcaParm.Cwmin[QID_AC_VO] = CW_MIN_IN_BITS-2;
+ ie_list->EdcaParm.Cwmax[QID_AC_VO] = CW_MAX_IN_BITS-1;
+ ie_list->EdcaParm.Txop[QID_AC_VO] = 48; /* AC_VO: 48*32us ~= 1.5ms*/
+ }
+ else if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4)
+ )
+ {
+ if (PeerWscIeLen >= 512)
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: PeerWscIeLen = %d (>= 512)\n", __FUNCTION__, PeerWscIeLen));
+ if (pPeerWscIe && (PeerWscIeLen < 512))
+ {
+ NdisMoveMemory(pPeerWscIe+PeerWscIeLen, pEid->Octet+4, pEid->Len-4);
+ PeerWscIeLen += (pEid->Len - 4);
+ }
+
+ }
+
+
+ break;
+
+ case IE_EXT_SUPP_RATES:
+ if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
+ {
+ NdisMoveMemory(&ie_list->ExtRate[0], pEid->Octet, pEid->Len);
+ ie_list->ExtRateLen = pEid->Len;
+
+ /*
+ TODO: 2004-09-14 not a good design here, cause it exclude extra rates
+ from ScanTab. We should report as is. And filter out unsupported
+ rates in MlmeAux
+ */
+ /* Check against the supported rates*/
+ /* RTMPCheckRates(pAd, ExtRate, pExtRateLen);*/
+ }
+ break;
+
+ case IE_ERP:
+ if (pEid->Len == 1)
+ ie_list->Erp = (UCHAR)pEid->Octet[0];
+ break;
+
+ case IE_AIRONET_CKIP:
+ /*
+ 0. Check Aironet IE length, it must be larger or equal to 28
+ Cisco AP350 used length as 28
+ Cisco AP12XX used length as 30
+ */
+ if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2))
+ break;
+
+ /* 1. Copy CKIP flag byte to buffer for process*/
+ ie_list->CkipFlag = *(pEid->Octet + 8);
+ break;
+
+ case IE_AP_TX_POWER:
+ /* AP Control of Client Transmit Power*/
+ /*0. Check Aironet IE length, it must be 6*/
+ if (pEid->Len != 0x06)
+ break;
+
+ /* Get cell power limit in dBm*/
+ if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1)
+ ie_list->AironetCellPowerLimit = *(pEid->Octet + 4);
+ break;
+
+ /* WPA2 & 802.11i RSN*/
+ case IE_RSN:
+ /* There is no OUI for version anymore, check the group cipher OUI before copying*/
+ if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
+ {
+ /* Copy to pVIE which will report to microsoft bssid list.*/
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ }
+ break;
+
+#ifdef WAPI_SUPPORT
+ /* WAPI information element*/
+ case IE_WAPI:
+ if (RTMPEqualMemory(pEid->Octet + 4, WAPI_OUI, 3))
+ {
+ /* Copy to pVIE*/
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ }
+ break;
+#endif /* WAPI_SUPPORT */
+
+
+ case IE_QBSS_LOAD:
+ if (pEid->Len == 5)
+ {
+ ie_list->QbssLoad.bValid = TRUE;
+ ie_list->QbssLoad.StaNum = pEid->Octet[0] + pEid->Octet[1] * 256;
+ ie_list->QbssLoad.ChannelUtilization = pEid->Octet[2];
+ ie_list->QbssLoad.RemainingAdmissionControl = pEid->Octet[3] + pEid->Octet[4] * 256;
+
+ /* Copy to pVIE*/
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ }
+ break;
+
+
+
+ case IE_EXT_CAPABILITY:
+ if (pEid->Len >= 1)
+ {
+ NdisMoveMemory(&ie_list->ExtCapInfo,&pEid->Octet[0], sizeof(EXT_CAP_INFO_ELEMENT) /*4*/);
+ break;
+ }
+
+#ifdef DOT11_VHT_AC
+ case IE_VHT_CAP:
+ if (pEid->Len == sizeof(VHT_CAP_IE)) {
+ NdisMoveMemory(&ie_list->vht_cap_ie, &pEid->Octet[0], sizeof(VHT_CAP_IE));
+ ie_list->vht_cap_len = pEid->Len;
+ }
+ break;
+ case IE_VHT_OP:
+ if (pEid->Len == sizeof(VHT_OP_IE)) {
+ NdisMoveMemory(&ie_list->vht_op_ie, &pEid->Octet[0], sizeof(VHT_OP_IE));
+ ie_list->vht_op_len = pEid->Len;
+ }
+ break;
+#endif /* DOT11_VHT_AC */
+
+ default:
+ break;
+ }
+
+ Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len]*/
+ pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+ }
+
+ LatchRfChannel = MsgChannel;
+
+ if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0))
+ {
+ if (CtrlChannel != 0)
+ ie_list->Channel = CtrlChannel;
+ else
+ ie_list->Channel = LatchRfChannel;
+ Sanity |= 0x4;
+ }
+
+ if (pPeerWscIe && (PeerWscIeLen > 0) && (PeerWscIeLen < 512))
+ {
+ UCHAR WscIe[] = {0xdd, 0x00, 0x00, 0x50, 0xF2, 0x04};
+ Ptr = (PUCHAR) pVIE;
+ WscIe[1] = PeerWscIeLen + 4;
+ NdisMoveMemory(Ptr + *LengthVIE, WscIe, 6);
+ NdisMoveMemory(Ptr + *LengthVIE + 6, pPeerWscIe, PeerWscIeLen);
+ *LengthVIE += (PeerWscIeLen + 6);
+ }
+
+
+SanityCheck:
+ if (pPeerWscIe)
+ os_free_mem(NULL, pPeerWscIe);
+
+ if (Sanity != 0x7)
+ {
+ DBGPRINT(RT_DEBUG_LOUD, ("%s() - missing field, Sanity=0x%02x\n", __FUNCTION__, Sanity));
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+
+#ifdef DOT11N_DRAFT3
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check for some IE addressed in 802.11n d3.03.
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN PeerBeaconAndProbeRspSanity2(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ IN OVERLAP_BSS_SCAN_IE *BssScan,
+ OUT UCHAR *RegClass)
+{
+ CHAR *Ptr;
+ PFRAME_802_11 pFrame;
+ PEID_STRUCT pEid;
+ ULONG Length = 0;
+ BOOLEAN brc;
+
+ pFrame = (PFRAME_802_11)Msg;
+
+ *RegClass = 0;
+ Ptr = pFrame->Octet;
+ Length += LENGTH_802_11;
+
+ /* get timestamp from payload and advance the pointer*/
+ Ptr += TIMESTAMP_LEN;
+ Length += TIMESTAMP_LEN;
+
+ /* get beacon interval from payload and advance the pointer*/
+ Ptr += 2;
+ Length += 2;
+
+ /* get capability info from payload and advance the pointer*/
+ Ptr += 2;
+ Length += 2;
+
+ pEid = (PEID_STRUCT) Ptr;
+ brc = FALSE;
+
+ RTMPZeroMemory(BssScan, sizeof(OVERLAP_BSS_SCAN_IE));
+ /* get variable fields from payload and advance the pointer*/
+ while ((Length + 2 + pEid->Len) <= MsgLen)
+ {
+ switch(pEid->Eid)
+ {
+ case IE_SUPP_REG_CLASS:
+ if(pEid->Len > 0)
+ {
+ *RegClass = *pEid->Octet;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_REG_CLASS (len=%d)\n",pEid->Len));
+ }
+ break;
+ case IE_OVERLAPBSS_SCAN_PARM:
+ if (pEid->Len == sizeof(OVERLAP_BSS_SCAN_IE))
+ {
+ brc = TRUE;
+ RTMPMoveMemory(BssScan, pEid->Octet, sizeof(OVERLAP_BSS_SCAN_IE));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_OVERLAPBSS_SCAN_PARM (len=%d)\n",pEid->Len));
+ }
+ break;
+
+ case IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT:
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT\n"));
+ break;
+
+ }
+
+ Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */
+ pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+ }
+
+ return brc;
+
+}
+#endif /* DOT11N_DRAFT3 */
+
+#if defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT)
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+ */
+BOOLEAN MlmeScanReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT UCHAR *pBssType,
+ OUT CHAR Ssid[],
+ OUT UCHAR *pSsidLen,
+ OUT UCHAR *pScanType)
+{
+ MLME_SCAN_REQ_STRUCT *Info;
+
+ Info = (MLME_SCAN_REQ_STRUCT *)(Msg);
+ *pBssType = Info->BssType;
+ *pSsidLen = Info->SsidLen;
+ NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen);
+ *pScanType = Info->ScanType;
+
+ if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC || *pBssType == BSS_ANY)
+ && (SCAN_MODE_VALID(*pScanType))
+ )
+ {
+ return TRUE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqSanity fail - wrong BssType or ScanType\n"));
+ return FALSE;
+ }
+}
+#endif
+
+/* IRQL = DISPATCH_LEVEL*/
+UCHAR ChannelSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR channel)
+{
+ int i;
+
+ for (i = 0; i < pAd->ChannelListNum; i ++)
+ {
+ if (channel == pAd->ChannelList[i].Channel)
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN PeerDeauthSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr1,
+ OUT PUCHAR pAddr2,
+ OUT PUCHAR pAddr3,
+ OUT USHORT *pReason)
+{
+ PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+
+ COPY_MAC_ADDR(pAddr1, pFrame->Hdr.Addr1);
+ COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+ COPY_MAC_ADDR(pAddr3, pFrame->Hdr.Addr3);
+ NdisMoveMemory(pReason, &pFrame->Octet[0], 2);
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN PeerAuthSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr,
+ OUT USHORT *pAlg,
+ OUT USHORT *pSeq,
+ OUT USHORT *pStatus,
+ CHAR *pChlgText)
+{
+ PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+
+ COPY_MAC_ADDR(pAddr, pFrame->Hdr.Addr2);
+ NdisMoveMemory(pAlg, &pFrame->Octet[0], 2);
+ NdisMoveMemory(pSeq, &pFrame->Octet[2], 2);
+ NdisMoveMemory(pStatus, &pFrame->Octet[4], 2);
+
+ if (*pAlg == AUTH_MODE_OPEN)
+ {
+ if (*pSeq == 1 || *pSeq == 2)
+ {
+ return TRUE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n"));
+ return FALSE;
+ }
+ }
+ else if (*pAlg == AUTH_MODE_KEY)
+ {
+ if (*pSeq == 1 || *pSeq == 4)
+ {
+ return TRUE;
+ }
+ else if (*pSeq == 2 || *pSeq == 3)
+ {
+ NdisMoveMemory(pChlgText, &pFrame->Octet[8], CIPHER_TEXT_LEN);
+ return TRUE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n"));
+ return FALSE;
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong algorithm\n"));
+ return FALSE;
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+ */
+BOOLEAN MlmeAuthReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr,
+ OUT ULONG *pTimeout,
+ OUT USHORT *pAlg)
+{
+ MLME_AUTH_REQ_STRUCT *pInfo;
+
+ pInfo = (MLME_AUTH_REQ_STRUCT *)Msg;
+ COPY_MAC_ADDR(pAddr, pInfo->Addr);
+ *pTimeout = pInfo->Timeout;
+ *pAlg = pInfo->Alg;
+
+ if (((*pAlg == AUTH_MODE_KEY) ||(*pAlg == AUTH_MODE_OPEN)
+ ) &&
+ ((*pAddr & 0x01) == 0))
+ {
+ return TRUE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeAuthReqSanity fail - wrong algorithm\n"));
+ return FALSE;
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN MlmeAssocReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pApAddr,
+ OUT USHORT *pCapabilityInfo,
+ OUT ULONG *pTimeout,
+ OUT USHORT *pListenIntv)
+{
+ MLME_ASSOC_REQ_STRUCT *pInfo;
+
+ pInfo = (MLME_ASSOC_REQ_STRUCT *)Msg;
+ *pTimeout = pInfo->Timeout; /* timeout*/
+ COPY_MAC_ADDR(pApAddr, pInfo->Addr); /* AP address*/
+ *pCapabilityInfo = pInfo->CapabilityInfo; /* capability info*/
+ *pListenIntv = pInfo->ListenIntv;
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN PeerDisassocSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT USHORT *pReason)
+{
+ PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+
+ COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+ NdisMoveMemory(pReason, &pFrame->Octet[0], 2);
+
+ return TRUE;
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Sanity check NetworkType (11b, 11g or 11a)
+
+ Arguments:
+ pBss - Pointer to BSS table.
+
+ Return Value:
+ Ndis802_11DS .......(11b)
+ Ndis802_11OFDM24....(11g)
+ Ndis802_11OFDM5.....(11a)
+
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity(
+ IN PBSS_ENTRY pBss)
+{
+ NDIS_802_11_NETWORK_TYPE NetWorkType;
+ UCHAR rate, i;
+
+ NetWorkType = Ndis802_11DS;
+
+ if (pBss->Channel <= 14)
+ {
+
+ /* First check support Rate.*/
+ for (i = 0; i < pBss->SupRateLen; i++)
+ {
+ rate = pBss->SupRate[i] & 0x7f; /* Mask out basic rate set bit*/
+ if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22))
+ {
+ continue;
+ }
+ else
+ {
+
+ /* Otherwise (even rate > 108) means Ndis802_11OFDM24*/
+ NetWorkType = Ndis802_11OFDM24;
+ break;
+ }
+ }
+
+
+ /* Second check Extend Rate.*/
+ if (NetWorkType != Ndis802_11OFDM24)
+ {
+ for (i = 0; i < pBss->ExtRateLen; i++)
+ {
+ rate = pBss->SupRate[i] & 0x7f; /* Mask out basic rate set bit*/
+ if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22))
+ {
+ continue;
+ }
+ else
+ {
+
+ /* Otherwise (even rate > 108) means Ndis802_11OFDM24*/
+ NetWorkType = Ndis802_11OFDM24;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ NetWorkType = Ndis802_11OFDM5;
+ }
+
+ if (pBss->HtCapabilityLen != 0)
+ {
+ if (NetWorkType == Ndis802_11OFDM5)
+ NetWorkType = Ndis802_11OFDM5_N;
+ else
+ NetWorkType = Ndis802_11OFDM24_N;
+ }
+
+ return NetWorkType;
+}
+
+
+#ifdef QOS_DLS_SUPPORT
+BOOLEAN PeerDlsReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pDA,
+ OUT PUCHAR pSA,
+ OUT USHORT *pCapabilityInfo,
+ OUT USHORT *pDlsTimeout,
+ OUT UCHAR *pRatesLen,
+ OUT UCHAR Rates[],
+ OUT UCHAR *pHtCapabilityLen,
+ OUT HT_CAPABILITY_IE *pHtCapability)
+{
+ CHAR *Ptr;
+ PFRAME_802_11 Fr = (PFRAME_802_11)Msg;
+ PEID_STRUCT eid_ptr;
+
+ /* to prevent caller from using garbage output value*/
+ *pCapabilityInfo = 0;
+ *pDlsTimeout = 0;
+ *pHtCapabilityLen = 0;
+
+ Ptr = (PCHAR)Fr->Octet;
+
+ /* offset to destination MAC address (Category and Action field)*/
+ Ptr += 2;
+
+ /* get DA from payload and advance the pointer*/
+ NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN);
+ Ptr += MAC_ADDR_LEN;
+
+ /* get SA from payload and advance the pointer*/
+ NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN);
+ Ptr += MAC_ADDR_LEN;
+
+ /* get capability info from payload and advance the pointer*/
+ NdisMoveMemory(pCapabilityInfo, Ptr, 2);
+ Ptr += 2;
+
+ /* get capability info from payload and advance the pointer*/
+ NdisMoveMemory(pDlsTimeout, Ptr, 2);
+ Ptr += 2;
+
+ /* Category and Action field + DA + SA + capability + Timeout*/
+ eid_ptr = (PEID_STRUCT) &Fr->Octet[18];
+
+ while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen))
+ {
+ switch(eid_ptr->Eid)
+ {
+ case IE_SUPP_RATES:
+ if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0))
+ {
+ NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len);
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0]));
+ DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7]));
+ *pRatesLen = eid_ptr->Len;
+ }
+ else
+ {
+ *pRatesLen = 8;
+ Rates[0] = 0x82;
+ Rates[1] = 0x84;
+ Rates[2] = 0x8b;
+ Rates[3] = 0x96;
+ Rates[4] = 0x12;
+ Rates[5] = 0x24;
+ Rates[6] = 0x48;
+ Rates[7] = 0x6c;
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len));
+ }
+ break;
+
+ case IE_EXT_SUPP_RATES:
+ if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES)
+ {
+ NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len);
+ *pRatesLen = (*pRatesLen) + eid_ptr->Len;
+ }
+ else
+ {
+ NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen));
+ *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES;
+ }
+ break;
+
+ case IE_HT_CAP:
+ if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE))
+ {
+ NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_IE));
+
+ *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
+#ifdef UNALIGNMENT_SUPPORT
+ {
+ EXT_HT_CAP_INFO extHtCapInfo;
+
+ NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO));
+ *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo));
+ NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO));
+ }
+#else
+ *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
+#endif /* UNALIGNMENT_SUPPORT */
+ *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_HT_CAP\n"));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len));
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+ }
+
+ return TRUE;
+}
+
+BOOLEAN PeerDlsRspSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pDA,
+ OUT PUCHAR pSA,
+ OUT USHORT *pCapabilityInfo,
+ OUT USHORT *pStatus,
+ OUT UCHAR *pRatesLen,
+ OUT UCHAR Rates[],
+ OUT UCHAR *pHtCapabilityLen,
+ OUT HT_CAPABILITY_IE *pHtCapability)
+{
+ CHAR *Ptr;
+ PFRAME_802_11 Fr = (PFRAME_802_11)Msg;
+ PEID_STRUCT eid_ptr;
+
+ /* to prevent caller from using garbage output value*/
+ if (pStatus)
+ *pStatus = 0;
+ *pCapabilityInfo = 0;
+ *pHtCapabilityLen = 0;
+
+ Ptr = (PCHAR)Fr->Octet;
+
+ /* offset to destination MAC address (Category and Action field)*/
+ Ptr += 2;
+
+ /* get status code from payload and advance the pointer*/
+ if (pStatus)
+ NdisMoveMemory(pStatus, Ptr, 2);
+ Ptr += 2;
+
+ /* get DA from payload and advance the pointer*/
+ NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN);
+ Ptr += MAC_ADDR_LEN;
+
+ /* get SA from payload and advance the pointer*/
+ NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN);
+ Ptr += MAC_ADDR_LEN;
+
+ if (pStatus == 0)
+ {
+ /* get capability info from payload and advance the pointer*/
+ NdisMoveMemory(pCapabilityInfo, Ptr, 2);
+ Ptr += 2;
+ }
+
+ /* Category and Action field + status code + DA + SA + capability*/
+ eid_ptr = (PEID_STRUCT) &Fr->Octet[18];
+
+ while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen))
+ {
+ switch(eid_ptr->Eid)
+ {
+ case IE_SUPP_RATES:
+ if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0))
+ {
+ NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len);
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0]));
+ DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7]));
+ *pRatesLen = eid_ptr->Len;
+ }
+ else
+ {
+ *pRatesLen = 8;
+ Rates[0] = 0x82;
+ Rates[1] = 0x84;
+ Rates[2] = 0x8b;
+ Rates[3] = 0x96;
+ Rates[4] = 0x12;
+ Rates[5] = 0x24;
+ Rates[6] = 0x48;
+ Rates[7] = 0x6c;
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len));
+ }
+ break;
+
+ case IE_EXT_SUPP_RATES:
+ if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES)
+ {
+ NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len);
+ *pRatesLen = (*pRatesLen) + eid_ptr->Len;
+ }
+ else
+ {
+ NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen));
+ *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES;
+ }
+ break;
+
+ case IE_HT_CAP:
+ if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE))
+ {
+ NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_IE));
+
+ *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
+#ifdef UNALIGNMENT_SUPPORT
+ {
+ EXT_HT_CAP_INFO extHtCapInfo;
+
+ NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO));
+ *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo));
+ NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO));
+ }
+#else
+ *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
+#endif /* UNALIGNMENT_SUPPORT */
+ *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_HT_CAP\n"));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len));
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+ }
+
+ return TRUE;
+}
+
+BOOLEAN PeerDlsTearDownSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pDA,
+ OUT PUCHAR pSA,
+ OUT USHORT *pReason)
+{
+ CHAR *Ptr;
+ PFRAME_802_11 Fr = (PFRAME_802_11)Msg;
+
+ /* to prevent caller from using garbage output value*/
+ *pReason = 0;
+
+ Ptr = (PCHAR)Fr->Octet;
+
+ /* offset to destination MAC address (Category and Action field)*/
+ Ptr += 2;
+
+ /* get DA from payload and advance the pointer*/
+ NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN);
+ Ptr += MAC_ADDR_LEN;
+
+ /* get SA from payload and advance the pointer*/
+ NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN);
+ Ptr += MAC_ADDR_LEN;
+
+ /* get reason code from payload and advance the pointer*/
+ NdisMoveMemory(pReason, Ptr, 2);
+ Ptr += 2;
+
+ return TRUE;
+}
+#endif /* QOS_DLS_SUPPORT */
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+ */
+BOOLEAN PeerProbeReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT CHAR Ssid[],
+ OUT UCHAR *SsidLen,
+ OUT BOOLEAN *bRssiRequested)
+{
+ PFRAME_802_11 Fr = (PFRAME_802_11)Msg;
+ UCHAR *Ptr;
+ UCHAR eid =0, eid_len = 0, *eid_data;
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR apidx = MAIN_MBSSID;
+ UCHAR Addr1[MAC_ADDR_LEN];
+#ifdef WSC_INCLUDED
+ UCHAR *pPeerWscIe = NULL;
+ UINT PeerWscIeLen = 0;
+#endif /* WSC_INCLUDED */
+#endif /* CONFIG_AP_SUPPORT */
+ UINT total_ie_len = 0;
+
+ /* to prevent caller from using garbage output value*/
+#ifdef CONFIG_AP_SUPPORT
+ apidx = apidx; /* avoid compile warning */
+#endif /* CONFIG_AP_SUPPORT */
+ *SsidLen = 0;
+
+ COPY_MAC_ADDR(pAddr2, &Fr->Hdr.Addr2);
+
+ if (Fr->Octet[0] != IE_SSID || Fr->Octet[1] > MAX_LEN_OF_SSID)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("APPeerProbeReqSanity fail - wrong SSID IE\n"));
+ return FALSE;
+ }
+
+ *SsidLen = Fr->Octet[1];
+ NdisMoveMemory(Ssid, &Fr->Octet[2], *SsidLen);
+
+#ifdef CONFIG_AP_SUPPORT
+ COPY_MAC_ADDR(Addr1, &Fr->Hdr.Addr1);
+#ifdef WSC_AP_SUPPORT
+ os_alloc_mem(NULL, &pPeerWscIe, 512);
+#endif /* WSC_AP_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ Ptr = Fr->Octet;
+ eid = Ptr[0];
+ eid_len = Ptr[1];
+ total_ie_len = eid_len + 2;
+ eid_data = Ptr+2;
+
+ /* get variable fields from payload and advance the pointer*/
+ while((eid_data + eid_len) <= ((UCHAR*)Fr + MsgLen))
+ {
+ switch(eid)
+ {
+ case IE_VENDOR_SPECIFIC:
+ if (eid_len <= 4)
+ break;
+#ifdef RSSI_FEEDBACK
+ if (bRssiRequested && NdisEqualMemory(eid_data, RALINK_OUI, 3) && (eid_len == 7))
+ {
+ if (*(eid_data + 3/* skip RALINK_OUI */) & 0x8)
+ *bRssiRequested = TRUE;
+ break;
+ }
+#endif /* RSSI_FEEDBACK */
+
+ if (NdisEqualMemory(eid_data, WPS_OUI, 4)
+ )
+ {
+#ifdef CONFIG_AP_SUPPORT
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef WSC_INCLUDED
+
+
+ WscCheckPeerDPID(pAd, Fr, eid_data, eid_len);
+
+#ifdef CONFIG_AP_SUPPORT
+ if (PeerWscIeLen >= 512)
+ DBGPRINT(RT_DEBUG_ERROR, ("APPeerProbeReqSanity : PeerWscIeLen = %d (>= 512)\n", PeerWscIeLen));
+ if (pPeerWscIe && (PeerWscIeLen < 512))
+ {
+ NdisMoveMemory(pPeerWscIe+PeerWscIeLen, eid_data+4, eid_len-4);
+ PeerWscIeLen += (eid_len - 4);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* WSC_INCLUDED */
+ break;
+ }
+
+ default:
+ break;
+ }
+ eid = Ptr[total_ie_len];
+ eid_len = Ptr[total_ie_len + 1];
+ eid_data = Ptr + total_ie_len + 2;
+ total_ie_len += (eid_len + 2);
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef WSC_INCLUDED
+ if (pPeerWscIe && (PeerWscIeLen > 0))
+ {
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ if (NdisEqualMemory(Addr1, pAd->ApCfg.MBSSID[apidx].Bssid, MAC_ADDR_LEN))
+ break;
+ }
+
+ /*
+ Due to Addr1 in Probe Request may be FF:FF:FF:FF:FF:FF
+ and we need to send out this information to external registrar.
+ Therefore we choose ra0 to send this probe req when we couldn't find apidx by Addr1.
+ */
+ if (apidx >= pAd->ApCfg.BssidNum)
+ {
+ apidx = MAIN_MBSSID;
+ }
+
+ if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode & WSC_PROXY) != WSC_DISABLE)
+ {
+ int bufLen = 0;
+ PUCHAR pBuf = NULL;
+ WSC_IE_PROBREQ_DATA *pprobreq = NULL;
+
+ /*
+ PeerWscIeLen: Len of WSC IE without WSC OUI
+ */
+ bufLen = sizeof(WSC_IE_PROBREQ_DATA) + PeerWscIeLen;
+ os_alloc_mem(NULL, &pBuf, bufLen);
+ if(pBuf)
+ {
+ /*Send WSC probe req to UPnP*/
+ NdisZeroMemory(pBuf, bufLen);
+ pprobreq = (WSC_IE_PROBREQ_DATA*)pBuf;
+ if (32 >= *SsidLen) /*Well, I think that it must be TRUE!*/
+ {
+ NdisMoveMemory(pprobreq->ssid, Ssid, *SsidLen); /* SSID*/
+ NdisMoveMemory(pprobreq->macAddr, Fr->Hdr.Addr2, 6); /* Mac address*/
+ pprobreq->data[0] = PeerWscIeLen>>8; /* element ID*/
+ pprobreq->data[1] = PeerWscIeLen & 0xff; /* element Length */
+ NdisMoveMemory((pBuf+sizeof(WSC_IE_PROBREQ_DATA)), pPeerWscIe, PeerWscIeLen); /* (WscProbeReqData)*/
+ WscSendUPnPMessage(pAd, apidx,
+ WSC_OPCODE_UPNP_MGMT, WSC_UPNP_MGMT_SUB_PROBE_REQ,
+ pBuf, bufLen, 0, 0, &Fr->Hdr.Addr2[0], AP_MODE);
+ }
+ os_free_mem(NULL, pBuf);
+ }
+ }
+ }
+ if (pPeerWscIe)
+ os_free_mem(NULL, pPeerWscIe);
+#endif /* WSC_INCLUDED */
+#endif /* CONFIG_AP_SUPPORT */
+
+ return TRUE;
+}
+
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_sync.c b/cleopatre/devkit/mt7601udrv/common/cmm_sync.c
new file mode 100644
index 0000000000..5c81fb6286
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_sync.c
@@ -0,0 +1,494 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ cmm_sync.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John Chang 2004-09-01 modified for rt2561/2661
+*/
+#include "rt_config.h"
+
+/*BaSizeArray follows the 802.11n definition as MaxRxFactor. 2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8.*/
+UCHAR BaSizeArray[4] = {8,16,32,64};
+
+
+extern COUNTRY_REGION_CH_DESC Country_Region_ChDesc_2GHZ[];
+extern UINT16 const Country_Region_GroupNum_2GHZ;
+extern COUNTRY_REGION_CH_DESC Country_Region_ChDesc_5GHZ[];
+extern UINT16 const Country_Region_GroupNum_5GHZ;
+
+/*
+ ==========================================================================
+ Description:
+ Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type,
+ and 3) PHY-mode user selected.
+ The outcome is used by driver when doing site survey.
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID BuildChannelList(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR i, j, index=0, num=0;
+ PCH_DESC pChDesc = NULL;
+ BOOLEAN bRegionFound = FALSE;
+ PUCHAR pChannelList;
+ PUCHAR pChannelListFlag;
+
+ NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER));
+
+ /* if not 11a-only mode, channel list starts from 2.4Ghz band*/
+ if (!WMODE_5G_ONLY(pAd->CommonCfg.PhyMode))
+ {
+ for (i = 0; i < Country_Region_GroupNum_2GHZ; i++)
+ {
+ if ((pAd->CommonCfg.CountryRegion & 0x7f) ==
+ Country_Region_ChDesc_2GHZ[i].RegionIndex)
+ {
+ pChDesc = Country_Region_ChDesc_2GHZ[i].pChDesc;
+ num = TotalChNum(pChDesc);
+ bRegionFound = TRUE;
+ break;
+ }
+ }
+
+ if (!bRegionFound)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("CountryRegion=%d not support", pAd->CommonCfg.CountryRegion));
+ return;
+ }
+
+ if (num > 0)
+ {
+ os_alloc_mem(NULL, (UCHAR **)&pChannelList, num * sizeof(UCHAR));
+
+ if (!pChannelList)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelList failed\n", __FUNCTION__));
+ return;
+ }
+
+ os_alloc_mem(NULL, (UCHAR **)&pChannelListFlag, num * sizeof(UCHAR));
+
+ if (!pChannelListFlag)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelListFlag failed\n", __FUNCTION__));
+ os_free_mem(NULL, pChannelList);
+ return;
+ }
+
+ for (i = 0; i < num; i++)
+ {
+ pChannelList[i] = GetChannel_2GHZ(pChDesc, i);
+ pChannelListFlag[i] = GetChannelFlag(pChDesc, i);
+ }
+
+ for (i = 0; i < num; i++)
+ {
+ for (j = 0; j < MAX_NUM_OF_CHANNELS; j++)
+ {
+ if (pChannelList[i] == pAd->TxPower[j].Channel)
+ NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER));
+ pAd->ChannelList[index + i].Flags = pChannelListFlag[i];
+ }
+
+#ifdef DOT11_N_SUPPORT
+ if (N_ChannelGroupCheck(pAd, pAd->ChannelList[index + i].Channel))
+ pAd->ChannelList[index + i].Flags |= CHANNEL_40M_CAP;
+#endif /* DOT11_N_SUPPORT */
+
+ pAd->ChannelList[index+i].MaxTxPwr = 20;
+ }
+
+ index += num;
+
+ os_free_mem(NULL, pChannelList);
+ os_free_mem(NULL, pChannelListFlag);
+ }
+ bRegionFound = FALSE;
+ num = 0;
+ }
+
+ if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode))
+ {
+ for (i = 0; i < Country_Region_GroupNum_5GHZ; i++)
+ {
+ if ((pAd->CommonCfg.CountryRegionForABand & 0x7f) ==
+ Country_Region_ChDesc_5GHZ[i].RegionIndex)
+ {
+ pChDesc = Country_Region_ChDesc_5GHZ[i].pChDesc;
+ num = TotalChNum(pChDesc);
+ bRegionFound = TRUE;
+ break;
+ }
+ }
+
+ if (!bRegionFound)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("CountryRegionABand=%d not support", pAd->CommonCfg.CountryRegionForABand));
+ return;
+ }
+
+ if (num > 0)
+ {
+ UCHAR RadarCh[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR q=0;
+#endif /* CONFIG_AP_SUPPORT */
+ os_alloc_mem(NULL, (UCHAR **)&pChannelList, num * sizeof(UCHAR));
+
+ if (!pChannelList)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelList failed\n", __FUNCTION__));
+ return;
+ }
+
+ os_alloc_mem(NULL, (UCHAR **)&pChannelListFlag, num * sizeof(UCHAR));
+
+ if (!pChannelListFlag)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelListFlag failed\n", __FUNCTION__));
+ os_free_mem(NULL, pChannelList);
+ return;
+ }
+
+ for (i = 0; i < num; i++)
+ {
+ pChannelList[i] = GetChannel_5GHZ(pChDesc, i);
+ pChannelListFlag[i] = GetChannelFlag(pChDesc, i);
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ for (i = 0; i < num; i++)
+ {
+ if((pAd->CommonCfg.bIEEE80211H == 0)|| ((pAd->CommonCfg.bIEEE80211H == 1) && (pAd->CommonCfg.RDDurRegion != FCC)))
+ {
+ pChannelList[q] = GetChannel_5GHZ(pChDesc, i);
+ pChannelListFlag[q] = GetChannelFlag(pChDesc, i);
+ q++;
+ }
+ /*Based on the requiremnt of FCC, some channles could not be used anymore when test DFS function.*/
+ else if ((pAd->CommonCfg.bIEEE80211H == 1) &&
+ (pAd->CommonCfg.RDDurRegion == FCC) &&
+ (pAd->Dot11_H.bDFSIndoor == 1))
+ {
+ if((GetChannel_5GHZ(pChDesc, i) < 116) || (GetChannel_5GHZ(pChDesc, i) > 128))
+ {
+ pChannelList[q] = GetChannel_5GHZ(pChDesc, i);
+ pChannelListFlag[q] = GetChannelFlag(pChDesc, i);
+ q++;
+ }
+ }
+ else if ((pAd->CommonCfg.bIEEE80211H == 1) &&
+ (pAd->CommonCfg.RDDurRegion == FCC) &&
+ (pAd->Dot11_H.bDFSIndoor == 0))
+ {
+ if((GetChannel_5GHZ(pChDesc, i) < 100) || (GetChannel_5GHZ(pChDesc, i) > 140) )
+ {
+ pChannelList[q] = GetChannel_5GHZ(pChDesc, i);
+ pChannelListFlag[q] = GetChannelFlag(pChDesc, i);
+ q++;
+ }
+ }
+
+ }
+ num = q;
+#endif /* CONFIG_AP_SUPPORT */
+
+ for (i=0; i<num; i++)
+ {
+ for (j=0; j<MAX_NUM_OF_CHANNELS; j++)
+ {
+ if (pChannelList[i] == pAd->TxPower[j].Channel)
+ NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER));
+ pAd->ChannelList[index + i].Flags = pChannelListFlag[i];
+ }
+
+#ifdef DOT11_N_SUPPORT
+ if (N_ChannelGroupCheck(pAd, pAd->ChannelList[index + i].Channel))
+ pAd->ChannelList[index + i].Flags |= CHANNEL_40M_CAP;
+#endif /* DOT11_N_SUPPORT */
+
+ for (j=0; j<15; j++)
+ {
+ if (pChannelList[i] == RadarCh[j])
+ pAd->ChannelList[index+i].DfsReq = TRUE;
+ }
+ pAd->ChannelList[index+i].MaxTxPwr = 20;
+ }
+ index += num;
+
+ os_free_mem(NULL, pChannelList);
+ os_free_mem(NULL, pChannelListFlag);
+ }
+ }
+
+ pAd->ChannelListNum = index;
+ DBGPRINT(RT_DEBUG_TRACE,("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n",
+ pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, pAd->CommonCfg.PhyMode, pAd->ChannelListNum));
+
+#ifdef RT_CFG80211_SUPPORT
+ for (i=0;i<pAd->ChannelListNum;i++)
+ {
+ CFG80211OS_ChanInfoInit(
+ pAd->pCfg80211_CB,
+ i,
+ pAd->ChannelList[i].Channel,
+ pAd->ChannelList[i].MaxTxPwr,
+ WMODE_CAP_N(pAd->CommonCfg.PhyMode),
+ (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20));
+ }
+#endif /* RT_CFG80211_SUPPORT */
+
+#ifdef DBG
+ for (i=0;i<pAd->ChannelListNum;i++)
+ {
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, Flags = %x\n ",
+ pAd->ChannelList[i].Channel,
+ pAd->ChannelList[i].Power,
+ pAd->ChannelList[i].Power2,
+ pAd->ChannelList[i].Flags));
+ }
+#endif
+}
+
+/*
+ ==========================================================================
+ Description:
+ This routine return the first channel number according to the country
+ code selection and RF IC selection (signal band or dual band). It is called
+ whenever driver need to start a site survey of all supported channels.
+ Return:
+ ch - the first channel number of current country code setting
+
+ IRQL = PASSIVE_LEVEL
+
+ ==========================================================================
+ */
+UCHAR FirstChannel(
+ IN PRTMP_ADAPTER pAd)
+{
+ return pAd->ChannelList[0].Channel;
+}
+
+/*
+ ==========================================================================
+ Description:
+ This routine returns the next channel number. This routine is called
+ during driver need to start a site survey of all supported channels.
+ Return:
+ next_channel - the next channel number valid in current country code setting.
+ Note:
+ return 0 if no more next channel
+ ==========================================================================
+ */
+UCHAR NextChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR channel)
+{
+ int i;
+ UCHAR next_channel = 0;
+
+ for (i = 0; i < (pAd->ChannelListNum - 1); i++)
+ {
+ if (channel == pAd->ChannelList[i].Channel)
+ {
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+ /* Only scan effected channel if this is a SCAN_2040_BSS_COEXIST*/
+ /* 2009 PF#2: Nee to handle the second channel of AP fall into affected channel range.*/
+ if ((pAd->MlmeAux.ScanType == SCAN_2040_BSS_COEXIST) && (pAd->ChannelList[i+1].Channel >14))
+ {
+ channel = pAd->ChannelList[i+1].Channel;
+ continue;
+ }
+ else
+#endif /* DOT11N_DRAFT3 */
+#endif /* DOT11_N_SUPPORT */
+ {
+ /* Record this channel's idx in ChannelList array.*/
+ next_channel = pAd->ChannelList[i+1].Channel;
+ break;
+ }
+ }
+
+ }
+ return next_channel;
+}
+
+/*
+ ==========================================================================
+ Description:
+ This routine is for Cisco Compatible Extensions 2.X
+ Spec31. AP Control of Client Transmit Power
+ Return:
+ None
+ Note:
+ Required by Aironet dBm(mW)
+ 0dBm(1mW), 1dBm(5mW), 13dBm(20mW), 15dBm(30mW),
+ 17dBm(50mw), 20dBm(100mW)
+
+ We supported
+ 3dBm(Lowest), 6dBm(10%), 9dBm(25%), 12dBm(50%),
+ 14dBm(75%), 15dBm(100%)
+
+ The client station's actual transmit power shall be within +/- 5dB of
+ the minimum value or next lower value.
+ ==========================================================================
+ */
+VOID ChangeToCellPowerLimit(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR AironetCellPowerLimit)
+{
+ /*
+ valud 0xFF means that hasn't found power limit information
+ from the AP's Beacon/Probe response
+ */
+ if (AironetCellPowerLimit == 0xFF)
+ return;
+
+ if (AironetCellPowerLimit < 6) /*Used Lowest Power Percentage.*/
+ pAd->CommonCfg.TxPowerPercentage = 6;
+ else if (AironetCellPowerLimit < 9)
+ pAd->CommonCfg.TxPowerPercentage = 10;
+ else if (AironetCellPowerLimit < 12)
+ pAd->CommonCfg.TxPowerPercentage = 25;
+ else if (AironetCellPowerLimit < 14)
+ pAd->CommonCfg.TxPowerPercentage = 50;
+ else if (AironetCellPowerLimit < 15)
+ pAd->CommonCfg.TxPowerPercentage = 75;
+ else
+ pAd->CommonCfg.TxPowerPercentage = 100; /*else used maximum*/
+
+ if (pAd->CommonCfg.TxPowerPercentage > pAd->CommonCfg.TxPowerDefault)
+ pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
+
+}
+
+
+CHAR ConvertToRssi(RTMP_ADAPTER *pAd, CHAR Rssi, UCHAR rssi_idx, UCHAR AntSel, UCHAR BW)
+{
+ UCHAR RssiOffset, LNAGain;
+
+ /* Rssi equals to zero or rssi_idx larger than 3 should be an invalid value*/
+ if (Rssi == 0 || rssi_idx >= 3)
+ return -99;
+
+ LNAGain = GET_LNA_GAIN(pAd);
+ if (pAd->LatchRfRegs.Channel > 14)
+ RssiOffset = pAd->ARssiOffset[rssi_idx];
+ else
+ RssiOffset = pAd->BGRssiOffset[rssi_idx];
+
+#ifdef RT65xx
+ if (IS_RT65XX(pAd))
+ return (Rssi - LNAGain - RssiOffset);
+ else
+#endif /* RT65xx */
+#ifdef MT7601
+ if ( IS_MT7601(pAd) )
+ {
+ CHAR LNA, RSSI;
+ PCHAR LNATable;
+/*
+ CHAR MainBW40LNA[] = { 1, 18, 35 };
+ CHAR MainBW20LNA[] = { 1, 18, 36 };
+ CHAR AuxBW40LNA[] = { 1, 23, 42 };
+ CHAR AuxBW20LNA[] = { 1, 23, 42 };
+*/
+ CHAR MainBW40LNA[] = { 0, 16, 34 };
+ CHAR MainBW20LNA[] = { -2, 15, 33 };
+ CHAR AuxBW40LNA[] = { -2, 16, 34 };
+ CHAR AuxBW20LNA[] = { -2, 15, 33 };
+
+ LNA = (Rssi >> 6) & 0x3;
+ RSSI = Rssi & 0x3F;
+
+ if ( (AntSel >> 7) == 0 )
+ {
+ if (BW == BW_40)
+ LNATable = MainBW40LNA;
+ else
+ LNATable = MainBW20LNA;
+ }
+ else
+ {
+ if (BW == BW_40)
+ LNATable = AuxBW40LNA;
+ else
+ LNATable = AuxBW20LNA;
+ }
+
+ if ( LNA == 3 )
+ LNA = LNATable[2];
+ else if ( LNA == 2 )
+ LNA = LNATable[1];
+ else
+ LNA = LNATable[0];
+
+ return ( 8 - LNA - RSSI - LNAGain - RssiOffset );
+ }
+ else
+#endif /* MT7601 */
+ return (-12 - RssiOffset - LNAGain - Rssi);
+}
+
+
+CHAR ConvertToSnr(RTMP_ADAPTER *pAd, UCHAR Snr)
+{
+ if (pAd->chipCap.SnrFormula == SNR_FORMULA2)
+ return (Snr * 3 + 8) >> 4;
+ else if (pAd->chipCap.SnrFormula == SNR_FORMULA3)
+ return (Snr * 3 / 16 ); /* * 0.1881 */
+ else
+ return ((0xeb - Snr) * 3) / 16 ;
+}
+
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef DOT11_N_SUPPORT
+extern int DetectOverlappingPeriodicRound;
+
+VOID Handle_BSS_Width_Trigger_Events(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG Now32;
+
+ if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) &&
+ (pAd->CommonCfg.Channel <=14))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Rcv BSS Width Trigger Event: 40Mhz --> 20Mhz \n"));
+ NdisGetSystemUpTime(&Now32);
+ pAd->CommonCfg.LastRcvBSSWidthTriggerEventsTime = Now32;
+ pAd->CommonCfg.bRcvBSSWidthTriggerEvents = TRUE;
+ pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0;
+ pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0;
+ DetectOverlappingPeriodicRound = 31;
+ }
+}
+#endif /* DOT11_N_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_tkip.c b/cleopatre/devkit/mt7601udrv/common/cmm_tkip.c
new file mode 100644
index 0000000000..c2a1216744
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_tkip.c
@@ -0,0 +1,923 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ cmm_tkip.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Wu 02-25-02 Initial
+*/
+
+#include "rt_config.h"
+
+/* Rotation functions on 32 bit values */
+#define ROL32( A, n ) \
+ ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) )
+#define ROR32( A, n ) ROL32( (A), 32-(n) )
+
+UINT Tkip_Sbox_Lower[256] =
+{
+ 0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54,
+ 0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A,
+ 0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B,
+ 0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B,
+ 0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F,
+ 0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F,
+ 0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5,
+ 0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F,
+ 0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB,
+ 0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97,
+ 0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED,
+ 0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A,
+ 0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94,
+ 0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3,
+ 0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04,
+ 0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D,
+ 0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39,
+ 0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95,
+ 0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83,
+ 0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76,
+ 0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4,
+ 0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B,
+ 0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0,
+ 0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18,
+ 0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51,
+ 0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85,
+ 0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12,
+ 0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9,
+ 0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7,
+ 0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A,
+ 0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8,
+ 0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A
+};
+
+UINT Tkip_Sbox_Upper[256] =
+{
+ 0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91,
+ 0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC,
+ 0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB,
+ 0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B,
+ 0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83,
+ 0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A,
+ 0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F,
+ 0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA,
+ 0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B,
+ 0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13,
+ 0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6,
+ 0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85,
+ 0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11,
+ 0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B,
+ 0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1,
+ 0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF,
+ 0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E,
+ 0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6,
+ 0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B,
+ 0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD,
+ 0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8,
+ 0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2,
+ 0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49,
+ 0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10,
+ 0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97,
+ 0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F,
+ 0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C,
+ 0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27,
+ 0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33,
+ 0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5,
+ 0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0,
+ 0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C
+};
+
+
+/* Expanded IV for TKIP function.*/
+
+typedef struct GNU_PACKED _IV_CONTROL_
+{
+ union GNU_PACKED
+ {
+ struct GNU_PACKED
+ {
+ UCHAR rc0;
+ UCHAR rc1;
+ UCHAR rc2;
+
+ union GNU_PACKED
+ {
+ struct GNU_PACKED
+ {
+#ifdef RT_BIG_ENDIAN
+ UCHAR KeyID:2;
+ UCHAR ExtIV:1;
+ UCHAR Rsvd:5;
+#else
+ UCHAR Rsvd:5;
+ UCHAR ExtIV:1;
+ UCHAR KeyID:2;
+#endif
+ } field;
+ UCHAR Byte;
+ } CONTROL;
+ } field;
+
+ ULONG word;
+ } IV16;
+
+ ULONG IV32;
+} TKIP_IV, *PTKIP_IV;
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Convert from UCHAR[] to ULONG in a portable way
+
+ Arguments:
+ pMICKey pointer to MIC Key
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+ULONG RTMPTkipGetUInt32(
+ IN PUCHAR pMICKey)
+{
+ ULONG res = 0;
+ INT i;
+
+ for (i = 0; i < 4; i++)
+ {
+ res |= (*pMICKey++) << (8 * i);
+ }
+
+ return res;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Convert from ULONG to UCHAR[] in a portable way
+
+ Arguments:
+ pDst pointer to destination for convert ULONG to UCHAR[]
+ val the value for convert
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPTkipPutUInt32(
+ IN OUT PUCHAR pDst,
+ IN ULONG val)
+{
+ INT i;
+
+ for(i = 0; i < 4; i++)
+ {
+ *pDst++ = (UCHAR) (val & 0xff);
+ val >>= 8;
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Set the MIC Key.
+
+ Arguments:
+ pAd Pointer to our adapter
+ pMICKey pointer to MIC Key
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPTkipSetMICKey(
+ IN PTKIP_KEY_INFO pTkip,
+ IN PUCHAR pMICKey)
+{
+ /* Set the key */
+ pTkip->K0 = RTMPTkipGetUInt32(pMICKey);
+ pTkip->K1 = RTMPTkipGetUInt32(pMICKey + 4);
+ /* and reset the message */
+ pTkip->L = pTkip->K0;
+ pTkip->R = pTkip->K1;
+ pTkip->nBytesInM = 0;
+ pTkip->M = 0;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculate the MIC Value.
+
+ Arguments:
+ pAd Pointer to our adapter
+ uChar Append this uChar
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPTkipAppendByte(
+ IN PTKIP_KEY_INFO pTkip,
+ IN UCHAR uChar)
+{
+ /* Append the byte to our word-sized buffer */
+ pTkip->M |= (uChar << (8* pTkip->nBytesInM));
+ pTkip->nBytesInM++;
+ /* Process the word if it is full. */
+ if( pTkip->nBytesInM >= 4 )
+ {
+ pTkip->L ^= pTkip->M;
+ pTkip->R ^= ROL32( pTkip->L, 17 );
+ pTkip->L += pTkip->R;
+ pTkip->R ^= ((pTkip->L & 0xff00ff00) >> 8) | ((pTkip->L & 0x00ff00ff) << 8);
+ pTkip->L += pTkip->R;
+ pTkip->R ^= ROL32( pTkip->L, 3 );
+ pTkip->L += pTkip->R;
+ pTkip->R ^= ROR32( pTkip->L, 2 );
+ pTkip->L += pTkip->R;
+ /* Clear the buffer */
+ pTkip->M = 0;
+ pTkip->nBytesInM = 0;
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculate the MIC Value.
+
+ Arguments:
+ pAd Pointer to our adapter
+ pSrc Pointer to source data for Calculate MIC Value
+ Len Indicate the length of the source data
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPTkipAppend(
+ IN PTKIP_KEY_INFO pTkip,
+ IN PUCHAR pSrc,
+ IN UINT nBytes)
+{
+ /* This is simple */
+ while(nBytes > 0)
+ {
+ RTMPTkipAppendByte(pTkip, *pSrc++);
+ nBytes--;
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Get the MIC Value.
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ the MIC Value is store in pAd->PrivateInfo.MIC
+ ========================================================================
+*/
+VOID RTMPTkipGetMIC(
+ IN PTKIP_KEY_INFO pTkip)
+{
+ /* Append the minimum padding*/
+ RTMPTkipAppendByte(pTkip, 0x5a );
+ RTMPTkipAppendByte(pTkip, 0 );
+ RTMPTkipAppendByte(pTkip, 0 );
+ RTMPTkipAppendByte(pTkip, 0 );
+ RTMPTkipAppendByte(pTkip, 0 );
+ /* and then zeroes until the length is a multiple of 4 */
+ while( pTkip->nBytesInM != 0 )
+ {
+ RTMPTkipAppendByte(pTkip, 0 );
+ }
+ /* The appendByte function has already computed the result. */
+ RTMPTkipPutUInt32(pTkip->MIC, pTkip->L);
+ RTMPTkipPutUInt32(pTkip->MIC + 4, pTkip->R);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Init MIC Value calculation function which include set MIC key &
+ calculate first 16 bytes (DA + SA + priority + 0)
+
+ Arguments:
+ pAd Pointer to our adapter
+ pTKey Pointer to the Temporal Key (TK), TK shall be 128bits.
+ pDA Pointer to DA address
+ pSA Pointer to SA address
+ pMICKey pointer to MIC Key
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPInitMICEngine(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pKey,
+ IN PUCHAR pDA,
+ IN PUCHAR pSA,
+ IN UCHAR UserPriority,
+ IN PUCHAR pMICKey)
+{
+ ULONG Priority = UserPriority;
+
+ /* Init MIC value calculation*/
+ RTMPTkipSetMICKey(&pAd->PrivateInfo.Tx, pMICKey);
+ /* DA*/
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, pDA, MAC_ADDR_LEN);
+ /* SA*/
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSA, MAC_ADDR_LEN);
+ /* Priority + 3 bytes of 0*/
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, (PUCHAR)&Priority, 4);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Compare MIC value of received MSDU
+
+ Arguments:
+ pAd Pointer to our adapter
+ pSrc Pointer to the received Plain text data
+ pDA Pointer to DA address
+ pSA Pointer to SA address
+ pMICKey pointer to MIC Key
+ Len the length of the received plain text data exclude MIC value
+
+ Return Value:
+ TRUE MIC value matched
+ FALSE MIC value mismatched
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+BOOLEAN RTMPTkipCompareMICValue(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pSrc,
+ IN PUCHAR pDA,
+ IN PUCHAR pSA,
+ IN PUCHAR pMICKey,
+ IN UCHAR UserPriority,
+ IN UINT Len)
+{
+ UCHAR OldMic[8];
+ ULONG Priority = UserPriority;
+
+ /* Init MIC value calculation*/
+ RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey);
+ /* DA*/
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN);
+ /* SA*/
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN);
+ /* Priority + 3 bytes of 0*/
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4);
+
+ /* Calculate MIC value from plain text data*/
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len);
+
+ /* Get MIC valude from received frame*/
+ NdisMoveMemory(OldMic, pSrc + Len, 8);
+
+ /* Get MIC value from decrypted plain data*/
+ RTMPTkipGetMIC(&pAd->PrivateInfo.Rx);
+
+ /* Move MIC value from MSDU, this steps should move to data path.*/
+ /* Since the MIC value might cross MPDUs.*/
+ if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8))
+ {
+ DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValue(): TKIP MIC Error !\n")); /*MIC error.*/
+
+
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Copy frame from waiting queue into relative ring buffer and set
+ appropriate ASIC register to kick hardware transmit function
+
+ Arguments:
+ pAd Pointer to our adapter
+ PNDIS_PACKET Pointer to Ndis Packet for MIC calculation
+ pEncap Pointer to LLC encap data
+ LenEncap Total encap length, might be 0 which indicates no encap
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPCalculateMICValue(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN PUCHAR pEncap,
+ IN PCIPHER_KEY pKey,
+ IN UCHAR apidx)
+{
+ PACKET_INFO PacketInfo;
+ PUCHAR pSrcBufVA;
+ UINT SrcBufLen;
+ PUCHAR pSrc;
+ UCHAR UserPriority;
+ UCHAR vlan_offset = 0;
+
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
+
+ UserPriority = RTMP_GET_PACKET_UP(pPacket);
+ pSrc = pSrcBufVA;
+
+ /* determine if this is a vlan packet */
+ if (((*(pSrc + 12) << 8) + *(pSrc + 13)) == 0x8100)
+ vlan_offset = 4;
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ /* Start Calculate MIC Value*/
+ if (apidx >= MIN_NET_DEVICE_FOR_APCLI && ((apidx - MIN_NET_DEVICE_FOR_APCLI) < MAX_APCLI_NUM) && (pAd->OpMode == OPMODE_AP))
+ { /* For packet which need to do MATConvert, we need to use the CurrentAddress of specific ApCli interface.*/
+ RTMPInitMICEngine(
+ pAd,
+ pKey->Key,
+ pSrc,
+ pAd->ApCfg.ApCliTab[apidx-MIN_NET_DEVICE_FOR_APCLI].CurrentAddress,
+ UserPriority,
+ pKey->TxMic);
+ }
+ else
+#endif /* APCLI_SUPPORT */
+#ifdef IGMP_SNOOP_SUPPORT
+ if ((RTMP_GET_PACKET_WCID(pPacket) != MCAST_WCID) && (*pSrc & 0x01) && (pAd->OpMode == OPMODE_AP))
+ {
+ RTMPInitMICEngine(
+ pAd,
+ pKey->Key,
+ pAd->MacTab.Content[RTMP_GET_PACKET_WCID(pPacket)].Addr,
+ pSrc + 6,
+ UserPriority,
+ pKey->TxMic);
+ }
+ else
+#endif /* IGMP_SNOOP_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ {
+ RTMPInitMICEngine(
+ pAd,
+ pKey->Key,
+ pSrc,
+ pSrc + 6,
+ UserPriority,
+ pKey->TxMic);
+ }
+
+
+ if (pEncap != NULL)
+ {
+ /* LLC encapsulation*/
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, pEncap, 6);
+ /* Protocol Type*/
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc + 12 + vlan_offset, 2);
+ }
+ SrcBufLen -= (14 + vlan_offset);
+ pSrc += (14 + vlan_offset);
+ do
+ {
+ if (SrcBufLen > 0)
+ {
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc, SrcBufLen);
+ }
+
+ break; /* No need handle next packet */
+
+ } while (TRUE);
+
+ /* Compute the final MIC Value*/
+ RTMPTkipGetMIC(&pAd->PrivateInfo.Tx);
+}
+
+
+/************************************************************/
+/* tkip_sbox() */
+/* Returns a 16 bit value from a 64K entry table. The Table */
+/* is synthesized from two 256 entry byte wide tables. */
+/************************************************************/
+
+UINT tkip_sbox(UINT index)
+{
+ UINT index_low;
+ UINT index_high;
+ UINT left, right;
+
+ index_low = (index % 256);
+ index_high = ((index >> 8) % 256);
+
+ left = Tkip_Sbox_Lower[index_low] + (Tkip_Sbox_Upper[index_low] * 256);
+ right = Tkip_Sbox_Upper[index_high] + (Tkip_Sbox_Lower[index_high] * 256);
+
+ return (left ^ right);
+}
+
+UINT rotr1(UINT a)
+{
+ unsigned int b;
+
+ if ((a & 0x01) == 0x01)
+ {
+ b = (a >> 1) | 0x8000;
+ }
+ else
+ {
+ b = (a >> 1) & 0x7fff;
+ }
+ b = b % 65536;
+ return b;
+}
+
+VOID RTMPTkipMixKey(
+ UCHAR *key,
+ UCHAR *ta,
+ ULONG pnl, /* Least significant 16 bits of PN */
+ ULONG pnh, /* Most significant 32 bits of PN */
+ UCHAR *rc4key,
+ UINT *p1k)
+{
+
+ UINT tsc0;
+ UINT tsc1;
+ UINT tsc2;
+
+ UINT ppk0;
+ UINT ppk1;
+ UINT ppk2;
+ UINT ppk3;
+ UINT ppk4;
+ UINT ppk5;
+
+ INT i;
+ INT j;
+
+ tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */
+ tsc1 = (unsigned int)(pnh % 65536);
+ tsc2 = (unsigned int)(pnl % 65536); /* lsb */
+
+ /* Phase 1, step 1 */
+ p1k[0] = tsc1;
+ p1k[1] = tsc0;
+ p1k[2] = (UINT)(ta[0] + (ta[1]*256));
+ p1k[3] = (UINT)(ta[2] + (ta[3]*256));
+ p1k[4] = (UINT)(ta[4] + (ta[5]*256));
+
+ /* Phase 1, step 2 */
+ for (i=0; i<8; i++)
+ {
+ j = 2*(i & 1);
+ p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((256*key[1+j]) + key[j])) % 65536 )) % 65536;
+ p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((256*key[5+j]) + key[4+j])) % 65536 )) % 65536;
+ p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((256*key[9+j]) + key[8+j])) % 65536 )) % 65536;
+ p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((256*key[13+j]) + key[12+j])) % 65536 )) % 65536;
+ p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((256*key[1+j]) + key[j]))) % 65536 )) % 65536;
+ p1k[4] = (p1k[4] + i) % 65536;
+ }
+
+ /* Phase 2, Step 1 */
+ ppk0 = p1k[0];
+ ppk1 = p1k[1];
+ ppk2 = p1k[2];
+ ppk3 = p1k[3];
+ ppk4 = p1k[4];
+ ppk5 = (p1k[4] + tsc2) % 65536;
+
+ /* Phase2, Step 2 */
+ ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((256*key[1]) + key[0])) % 65536);
+ ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((256*key[3]) + key[2])) % 65536);
+ ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((256*key[5]) + key[4])) % 65536);
+ ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((256*key[7]) + key[6])) % 65536);
+ ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((256*key[9]) + key[8])) % 65536);
+ ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((256*key[11]) + key[10])) % 65536);
+
+ ppk0 = ppk0 + rotr1(ppk5 ^ ((256*key[13]) + key[12]));
+ ppk1 = ppk1 + rotr1(ppk0 ^ ((256*key[15]) + key[14]));
+ ppk2 = ppk2 + rotr1(ppk1);
+ ppk3 = ppk3 + rotr1(ppk2);
+ ppk4 = ppk4 + rotr1(ppk3);
+ ppk5 = ppk5 + rotr1(ppk4);
+
+ /* Phase 2, Step 3 */
+ /* Phase 2, Step 3 */
+
+ tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */
+ tsc1 = (unsigned int)(pnh % 65536);
+ tsc2 = (unsigned int)(pnl % 65536); /* lsb */
+
+ rc4key[0] = (tsc2 >> 8) % 256;
+ rc4key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f;
+ rc4key[2] = tsc2 % 256;
+ rc4key[3] = ((ppk5 ^ ((256*key[1]) + key[0])) >> 1) % 256;
+
+ rc4key[4] = ppk0 % 256;
+ rc4key[5] = (ppk0 >> 8) % 256;
+
+ rc4key[6] = ppk1 % 256;
+ rc4key[7] = (ppk1 >> 8) % 256;
+
+ rc4key[8] = ppk2 % 256;
+ rc4key[9] = (ppk2 >> 8) % 256;
+
+ rc4key[10] = ppk3 % 256;
+ rc4key[11] = (ppk3 >> 8) % 256;
+
+ rc4key[12] = ppk4 % 256;
+ rc4key[13] = (ppk4 >> 8) % 256;
+
+ rc4key[14] = ppk5 % 256;
+ rc4key[15] = (ppk5 >> 8) % 256;
+}
+
+
+/*
+ TRUE: Success!
+ FALSE: Decrypt Error!
+*/
+BOOLEAN RTMPSoftDecryptTKIP(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pHdr,
+ IN UCHAR UserPriority,
+ IN PCIPHER_KEY pKey,
+ INOUT PUCHAR pData,
+ IN UINT16 *DataByteCnt)
+{
+ PHEADER_802_11 pFrame;
+ UINT8 frame_type;
+ UINT8 frame_subtype;
+ UINT8 from_ds;
+ UINT8 to_ds;
+ UINT8 a4_exists;
+ UINT8 qc_exists;
+ UCHAR TA[MAC_ADDR_LEN];
+ UCHAR DA[MAC_ADDR_LEN];
+ UCHAR SA[MAC_ADDR_LEN];
+ UCHAR RC4Key[16];
+ UINT p1k[5]; /*for mix_key;*/
+ ULONG pnl;/* Least significant 16 bits of PN */
+ ULONG pnh;/* Most significant 32 bits of PN */
+ ARC4_CTX_STRUC ARC4_CTX;
+ PUCHAR plaintext_ptr;
+ UINT32 plaintext_len;
+ PUCHAR ciphertext_ptr;
+ UINT32 ciphertext_len;
+ UINT crc32 = 0;
+ UINT trailfcs = 0;
+ UCHAR MIC[8];
+ UCHAR TrailMIC[8];
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE);
+#endif
+
+ if (pKey->KeyLen == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : the key is empty)\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ /* Indicate type and subtype of Frame Control field */
+ frame_type = (((*pHdr) >> 2) & 0x03);
+ frame_subtype = (((*pHdr) >> 4) & 0x0f);
+
+ /* Indicate the fromDS and ToDS */
+ from_ds = ((*(pHdr + 1)) & 0x2) >> 1;
+ to_ds = ((*(pHdr + 1)) & 0x1);
+
+ /* decide if the Address 4 exist or QoS exist */
+ a4_exists = (from_ds & to_ds);
+ qc_exists = ((frame_subtype == SUBTYPE_QDATA) ||
+ (frame_subtype == SUBTYPE_QDATA_CFACK) ||
+ (frame_subtype == SUBTYPE_QDATA_CFPOLL) ||
+ (frame_subtype == SUBTYPE_QDATA_CFACK_CFPOLL));
+
+ /* pointer to 802.11 header */
+ pFrame = (PHEADER_802_11)pHdr;
+
+ /* Assign DA, SA and TA for TKIP calculation */
+ if (to_ds == 0 && from_ds == 1)
+ {
+ NdisMoveMemory(DA, pFrame->Addr1, MAC_ADDR_LEN);
+ NdisMoveMemory(TA, pFrame->Addr2, MAC_ADDR_LEN); /*BSSID */
+ NdisMoveMemory(SA, pFrame->Addr3, MAC_ADDR_LEN);
+ }
+ else if (to_ds == 0 && from_ds == 0 )
+ {
+ NdisMoveMemory(DA, pFrame->Addr1, MAC_ADDR_LEN);
+ NdisMoveMemory(TA, pFrame->Addr2, MAC_ADDR_LEN);
+ NdisMoveMemory(SA, pFrame->Addr2, MAC_ADDR_LEN);
+ }
+ else if (to_ds == 1 && from_ds == 0)
+ {
+ NdisMoveMemory(SA, pFrame->Addr2, MAC_ADDR_LEN);
+ NdisMoveMemory(TA, pFrame->Addr2, MAC_ADDR_LEN);
+ NdisMoveMemory(DA, pFrame->Addr3, MAC_ADDR_LEN);
+ }
+ else if (to_ds == 1 && from_ds == 1)
+ {
+ NdisMoveMemory(TA, pFrame->Addr2, MAC_ADDR_LEN);
+ NdisMoveMemory(DA, pFrame->Addr3, MAC_ADDR_LEN);
+ NdisMoveMemory(SA, pFrame->Octet, MAC_ADDR_LEN);
+ }
+
+ pnl = (*(pData)) << 8 | (*(pData + 2));
+ pnh = *((PULONG)(pData + 4));
+ pnh = cpu2le32(pnh);
+ RTMPTkipMixKey(pKey->Key, TA, pnl, pnh, RC4Key, p1k);
+
+ /* skip 8-bytes TKIP IV/EIV header */
+ ciphertext_ptr = pData + LEN_TKIP_IV_HDR;
+ ciphertext_len = *DataByteCnt - LEN_TKIP_IV_HDR;
+
+ /* WEP Decapsulation */
+ /* Generate an RC4 key stream */
+ ARC4_INIT(&ARC4_CTX, &RC4Key[0], 16);
+
+ /* Decrypt the TKIP MPDU by ARC4.
+ It shall include plaintext, MIC and ICV.
+ The result output would overwrite the original TKIP IV/EIV header position */
+ ARC4_Compute(&ARC4_CTX, ciphertext_ptr, ciphertext_len, pData);
+
+ /* Point to the decrypted data frame and its length shall exclude ICV length */
+ plaintext_ptr = pData;
+ plaintext_len = ciphertext_len - LEN_ICV;
+
+ /* Extract peer's ICV */
+ NdisMoveMemory(&trailfcs, plaintext_ptr + plaintext_len, LEN_ICV);
+
+ /* Re-computes the ICV and
+ bit-wise compares with the peer's ICV. */
+ crc32 = RTMP_CALC_FCS32(PPPINITFCS32, plaintext_ptr, plaintext_len);
+ crc32 ^= 0xffffffff; /* complement */
+
+ if(crc32 != cpu2le32(trailfcs))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("! WEP Data CRC Error !\n")); /*CRC error.*/
+ return FALSE;
+ }
+
+ /* Extract peer's MIC and subtract MIC length from total data length */
+ plaintext_len -= LEN_TKIP_MIC;
+ NdisMoveMemory(TrailMIC, plaintext_ptr + plaintext_len, LEN_TKIP_MIC);
+ RTMPInitMICEngine(pAd, pKey->Key, DA, SA, UserPriority, pKey->RxMic);
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, plaintext_ptr, plaintext_len);
+ RTMPTkipGetMIC(&pAd->PrivateInfo.Tx);
+ NdisMoveMemory(MIC, pAd->PrivateInfo.Tx.MIC, LEN_TKIP_MIC);
+
+ if (!NdisEqualMemory(MIC, TrailMIC, LEN_TKIP_MIC))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("! TKIP MIC Error !\n")); /*MIC error.*/
+ return FALSE;
+ }
+
+ /* Update the total data length */
+ *DataByteCnt = plaintext_len;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE);
+#endif
+ return TRUE;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Use RC4 to protect the Key Data field of EAPoL frame.
+ It's defined in IEEE 802.11i-2004 p.84
+
+ Arguments:
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID TKIP_GTK_KEY_WRAP(
+ IN UCHAR *key,
+ IN UCHAR *iv,
+ IN UCHAR *input_text,
+ IN UINT32 input_len,
+ OUT UCHAR *output_text)
+{
+ UCHAR ekey[LEN_KEY_DESC_IV + LEN_PTK_KEK];
+/* ARC4_CTX_STRUC ARC4_CTX;*/
+ ARC4_CTX_STRUC *pARC4_CTX = NULL;
+
+
+ /* allocate memory */
+ os_alloc_mem(NULL, (UCHAR **)&pARC4_CTX, sizeof(ARC4_CTX_STRUC));
+ if (pARC4_CTX == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ return;
+ }
+
+ /* The encryption key is generated by concatenating the
+ EAPOL-Key IV field and the KEK. */
+ NdisMoveMemory(ekey, iv, LEN_KEY_DESC_IV);
+ NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], key, LEN_PTK_KEK);
+
+ /* RC4 stream cipher initialization with the KEK */
+ ARC4_INIT(pARC4_CTX, &ekey[0], LEN_KEY_DESC_IV + LEN_PTK_KEK);
+
+ /* The first 256 octets of the RC4 key stream shall be discarded */
+ ARC4_Discard_KeyLength(pARC4_CTX, 256);
+
+ /* encryption begins using the 257th key stream octet */
+ ARC4_Compute(pARC4_CTX, input_text, input_len, output_text);
+
+ if (pARC4_CTX != NULL)
+ os_free_mem(NULL, pARC4_CTX);
+}
+
+VOID TKIP_GTK_KEY_UNWRAP(
+ IN UCHAR *key,
+ IN UCHAR *iv,
+ IN UCHAR *input_text,
+ IN UINT32 input_len,
+ OUT UCHAR *output_text)
+{
+ TKIP_GTK_KEY_WRAP(key, iv, input_text, input_len, output_text);
+}
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_video.c b/cleopatre/devkit/mt7601udrv/common/cmm_video.c
new file mode 100644
index 0000000000..1e4ec06ac2
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_video.c
@@ -0,0 +1,168 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ****************************************************************************
+
+ Module Name:
+ cmm_video.c
+
+ Abstract:
+ Ralink WiFi Driver video mode related subroutines
+
+ Revision History:
+ Who When What
+ --------- ---------- ----------------------------------------------
+
+*/
+
+#include "rt_config.h"
+
+
+#ifdef VIDEO_TURBINE_SUPPORT
+
+
+
+BOOLEAN UpdateFromGlobal = FALSE;
+
+void VideoTurbineUpdate(
+ IN PRTMP_ADAPTER pAd)
+{
+ if (UpdateFromGlobal == TRUE)
+ {
+ pAd->VideoTurbine.Enable = GLOBAL_AP_VIDEO_CONFIG.Enable;
+ pAd->VideoTurbine.ClassifierEnable = GLOBAL_AP_VIDEO_CONFIG.ClassifierEnable;
+ pAd->VideoTurbine.HighTxMode = GLOBAL_AP_VIDEO_CONFIG.HighTxMode;
+ pAd->VideoTurbine.TxPwr = GLOBAL_AP_VIDEO_CONFIG.TxPwr;
+ pAd->VideoTurbine.VideoMCSEnable = GLOBAL_AP_VIDEO_CONFIG.VideoMCSEnable;
+ pAd->VideoTurbine.VideoMCS = GLOBAL_AP_VIDEO_CONFIG.VideoMCS;
+ pAd->VideoTurbine.TxBASize = GLOBAL_AP_VIDEO_CONFIG.TxBASize;
+ pAd->VideoTurbine.TxLifeTimeMode = GLOBAL_AP_VIDEO_CONFIG.TxLifeTimeMode;
+ pAd->VideoTurbine.TxLifeTime = GLOBAL_AP_VIDEO_CONFIG.TxLifeTime;
+ pAd->VideoTurbine.TxRetryLimit = GLOBAL_AP_VIDEO_CONFIG.TxRetryLimit;
+ }
+}
+
+
+VOID TxSwQDepthAdjust(IN RTMP_ADAPTER *pAd, IN UINT32 qLen)
+{
+ ULONG IrqFlags;
+ INT qIdx;
+ QUEUE_HEADER *pTxQ, *pEntry;
+ PNDIS_PACKET pPacket;
+
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+ pAd->TxSwQMaxLen = qLen;
+ for (qIdx = 0; qIdx < NUM_OF_TX_RING; qIdx++)
+ {
+ pTxQ = &pAd->TxSwQueue[qIdx];
+ while(pTxQ->Number >= pAd->TxSwQMaxLen)
+ {
+ pEntry = RemoveHeadQueue(pTxQ);
+ if (pEntry)
+ {
+ pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ }
+ else
+ break;
+ }
+ }
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+
+ DBGPRINT(RT_DEBUG_OFF, ("%s():Set TxSwQMaxLen as %d\n",
+ __FUNCTION__, pAd->TxSwQMaxLen));
+}
+
+
+VOID VideoTurbineDynamicTune(
+ IN PRTMP_ADAPTER pAd)
+{
+ if (pAd->VideoTurbine.Enable == TRUE)
+ {
+ UINT32 MacReg = 0;
+
+ {
+ /* Tx retry limit = 2F,1F */
+ RTMP_IO_READ32(pAd, TX_RTY_CFG, &MacReg);
+ MacReg &= 0xFFFF0000;
+ MacReg |= GetAsicVideoRetry(pAd);
+ RTMP_IO_WRITE32(pAd, TX_RTY_CFG, MacReg);
+ }
+
+ pAd->VideoTurbine.TxBASize = GetAsicVideoTxBA(pAd);
+
+ Set_RateAdaptInterval(pAd, "100:50");
+ TxSwQDepthAdjust(pAd, 1024);
+
+ }
+ else
+ {
+ UINT32 MacReg = 0;
+
+
+ /* Default Tx retry limit = 1F,0F */
+ RTMP_IO_READ32(pAd, TX_RTY_CFG, &MacReg);
+ MacReg &= 0xFFFF0000;
+ MacReg |= GetAsicDefaultRetry(pAd);
+ RTMP_IO_WRITE32(pAd, TX_RTY_CFG, MacReg);
+
+ pAd->VideoTurbine.TxBASize = GetAsicDefaultTxBA(pAd);
+
+ /* reset to default rate adaptation simping interval */
+ if ((pAd->ra_interval != DEF_RA_TIME_INTRVAL) ||
+ (pAd->ra_fast_interval != DEF_QUICK_RA_TIME_INTERVAL))
+ Set_RateAdaptInterval(pAd, "500:100");
+
+ TxSwQDepthAdjust(pAd, MAX_PACKETS_IN_QUEUE);
+ }
+}
+
+UINT32 GetAsicDefaultRetry(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 RetryLimit;
+
+ RetryLimit = 0x1F0F;
+
+ return RetryLimit;
+}
+
+UCHAR GetAsicDefaultTxBA(
+ IN PRTMP_ADAPTER pAd)
+{
+ return pAd->CommonCfg.TxBASize;
+}
+
+UINT32 GetAsicVideoRetry(
+ IN PRTMP_ADAPTER pAd)
+{
+ return pAd->VideoTurbine.TxRetryLimit;
+}
+
+UCHAR GetAsicVideoTxBA(
+ IN PRTMP_ADAPTER pAd)
+{
+ return pAd->VideoTurbine.TxBASize;
+}
+
+VOID VideoConfigInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ pAd->VideoTurbine.Enable = FALSE;
+ pAd->VideoTurbine.TxRetryLimit = 0x2F1F;
+ pAd->VideoTurbine.TxBASize = pAd->CommonCfg.TxBASize;
+}
+
+#endif /* VIDEO_TURBINE_SUPPORT */
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_wep.c b/cleopatre/devkit/mt7601udrv/common/cmm_wep.c
new file mode 100644
index 0000000000..51147f6b16
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_wep.c
@@ -0,0 +1,365 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ rtmp_wep.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Wu 10-28-02 Initial
+*/
+
+#include "rt_config.h"
+
+UINT FCSTAB_32[256] =
+{
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculate a new FCS given the current FCS and the new data.
+
+ Arguments:
+ Fcs the original FCS value
+ Cp pointer to the data which will be calculate the FCS
+ Len the length of the data
+
+ Return Value:
+ UINT - FCS 32 bits
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+UINT RTMP_CALC_FCS32(
+ IN UINT Fcs,
+ IN PUCHAR Cp,
+ IN INT Len)
+{
+ while (Len--)
+ Fcs = (((Fcs) >> 8) ^ FCSTAB_32[((Fcs) ^ (*Cp++)) & 0xff]);
+
+ return (Fcs);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Init WEP function.
+
+ Arguments:
+ pAd Pointer to our adapter
+ pKey Pointer to the WEP KEY
+ KeyId WEP Key ID
+ KeyLen the length of WEP KEY
+ pDest Pointer to the destination which Encryption data will store in.
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPInitWepEngine(
+ IN PUCHAR pIv,
+ IN PUCHAR pKey,
+ IN UCHAR KeyLen,
+ OUT ARC4_CTX_STRUC *pARC4_CTX)
+{
+/* UCHAR seed[16];*/
+ PUCHAR seed = NULL;
+ UINT8 seed_len;
+
+ os_alloc_mem(NULL, (UCHAR **)&seed, sizeof(UCHAR)*16);
+ if (seed == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: seed Allocate memory fail!!!\n", __FUNCTION__));
+ return;
+ }
+
+ /* WEP seed construction */
+ NdisZeroMemory(seed, 16);
+ NdisMoveMemory(seed, pIv, 3);
+ NdisMoveMemory(&seed[3], pKey, KeyLen);
+ seed_len = 3 + KeyLen;
+
+ /* RC4 uses a pseudo-random number generator (PRNG)
+ to generate a key stream */
+ ARC4_INIT(pARC4_CTX, &seed[0], seed_len);
+
+ if (seed != NULL)
+ os_free_mem(NULL, seed);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Construct WEP IV header.
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+ It's a 4-octets header.
+
+ ========================================================================
+*/
+VOID RTMPConstructWEPIVHdr(
+ IN UINT8 key_idx,
+ IN UCHAR *pn,
+ OUT UCHAR *iv_hdr)
+{
+ NdisZeroMemory(iv_hdr, LEN_WEP_IV_HDR);
+
+ NdisMoveMemory(iv_hdr, pn, LEN_WEP_TSC);
+
+ /* Append key index */
+ iv_hdr[3] = (key_idx << 6);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ WEP MPDU cryptographic encapsulation
+
+ Arguments:
+ pAdapter Pointer to our adapter
+ pSrc Pointer to the received data
+ Len the length of the received data
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+BOOLEAN RTMPSoftEncryptWEP(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pIvHdr,
+ IN PCIPHER_KEY pKey,
+ INOUT PUCHAR pData,
+ IN ULONG DataByteCnt)
+{
+ ARC4_CTX_STRUC *ARC4_CTX = NULL;
+ UINT FCSCRC32;
+
+ os_alloc_mem(NULL, (UCHAR **)&ARC4_CTX, sizeof(ARC4_CTX_STRUC));
+ if (ARC4_CTX == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: ARC4_CTX Allocate memory fail!!!\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ if (pKey->KeyLen == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The key is empty !\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ /* Initialize WEP key stream */
+ RTMPInitWepEngine(pIvHdr,
+ pKey->Key,
+ pKey->KeyLen,
+ ARC4_CTX);
+
+ /* WEP computes the ICV over the plaintext data */
+ FCSCRC32 = RTMP_CALC_FCS32(PPPINITFCS32, pData, DataByteCnt);
+ FCSCRC32 ^= 0xffffffff; /* complement */
+ FCSCRC32 = cpu2le32(FCSCRC32);
+
+ /* Append 4-bytes ICV after the MPDU data */
+ NdisMoveMemory(pData + DataByteCnt, (PUCHAR)&FCSCRC32, LEN_ICV);
+
+ /* Encrypt the MPDU plaintext data and ICV using ARC4 with a seed */
+ ARC4_Compute(ARC4_CTX, pData, DataByteCnt + LEN_ICV, pData);
+
+ if (ARC4_CTX != NULL)
+ os_free_mem(NULL, ARC4_CTX);
+
+ return TRUE;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Decrypt received WEP data
+
+ Arguments:
+ pAdapter Pointer to our adapter
+ pSrc Pointer to the received data
+ Len the length of the received data
+
+ Return Value:
+ TRUE Decrypt WEP data success
+ FALSE Decrypt WEP data failed
+
+ Note:
+
+ ========================================================================
+*/
+BOOLEAN RTMPSoftDecryptWEP(
+ IN PRTMP_ADAPTER pAd,
+ IN PCIPHER_KEY pKey,
+ INOUT PUCHAR pData,
+ INOUT UINT16 *DataByteCnt)
+{
+ /*ARC4_CTX_STRUC ARC4_CTX;*/
+ ARC4_CTX_STRUC *ARC4_CTX = NULL;
+ PUCHAR plaintext_ptr;
+ UINT16 plaintext_len;
+ PUCHAR ciphertext_ptr;
+ UINT16 ciphertext_len;
+ UINT trailfcs;
+ UINT crc32;
+
+ os_alloc_mem(NULL, (UCHAR **)&ARC4_CTX, sizeof(ARC4_CTX_STRUC));
+ if (ARC4_CTX == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: ARC4_CTX Allocate memory fail!!!\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ if (pKey->KeyLen == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The key is not available !\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ /* Initialize WEP key stream */
+ RTMPInitWepEngine(pData,
+ pKey->Key,
+ pKey->KeyLen,
+ ARC4_CTX);
+
+ /* Skip the WEP IV header (4-bytes) */
+ ciphertext_ptr = pData + LEN_WEP_IV_HDR;
+ ciphertext_len = *DataByteCnt - LEN_WEP_IV_HDR;
+
+ /* Decrypt the WEP MPDU. It shall include plaintext and ICV.
+ The result output would overwrite the original WEP IV header position */
+ ARC4_Compute(ARC4_CTX,
+ ciphertext_ptr,
+ ciphertext_len,
+ pData);
+
+ /* Point to the decrypted data frame and its length shall exclude ICV length */
+ plaintext_ptr = pData;
+ plaintext_len = ciphertext_len - LEN_ICV;
+
+ /* Extract peer's the ICV */
+ NdisMoveMemory(&trailfcs, plaintext_ptr + plaintext_len, LEN_ICV);
+
+ /* WEP recomputes the ICV and
+ bit-wise compares it with the decrypted ICV from the MPDU. */
+ crc32 = RTMP_CALC_FCS32(PPPINITFCS32, plaintext_ptr, plaintext_len);
+ crc32 ^= 0xffffffff; /* complement */
+
+ if(crc32 != cpu2le32(trailfcs))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("! WEP Data CRC Error !\n")); /*CRC error.*/
+ return FALSE;
+ }
+
+ /* Update the total data length */
+ *DataByteCnt = plaintext_len;
+
+ if (ARC4_CTX != NULL)
+ os_free_mem(NULL, ARC4_CTX);
+
+ return TRUE;
+}
+
diff --git a/cleopatre/devkit/mt7601udrv/common/cmm_wpa.c b/cleopatre/devkit/mt7601udrv/common/cmm_wpa.c
new file mode 100644
index 0000000000..068ae2c4c5
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/cmm_wpa.c
@@ -0,0 +1,4728 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ wpa.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Jan Lee 03-07-22 Initial
+ Paul Lin 03-11-28 Modify for supplicant
+*/
+#include "rt_config.h"
+
+/* WPA OUI*/
+UCHAR OUI_WPA[3] = {0x00, 0x50, 0xF2};
+UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00};
+UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01};
+UCHAR OUI_WPA_WEP40[4] = {0x00, 0x50, 0xF2, 0x01};
+UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02};
+UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04};
+UCHAR OUI_WPA_WEP104[4] = {0x00, 0x50, 0xF2, 0x05};
+UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01};
+UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02};
+/* WPA2 OUI*/
+UCHAR OUI_WPA2[3] = {0x00, 0x0F, 0xAC};
+UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01};
+UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02};
+UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04};
+UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01};
+UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02};
+UCHAR OUI_WPA2_WEP104[4] = {0x00, 0x0F, 0xAC, 0x05};
+UCHAR OUI_WPA2_1X_SHA256[4] = {0x00, 0x0F, 0xAC, 0x05};
+UCHAR OUI_WPA2_PSK_SHA256[4] = {0x00, 0x0F, 0xAC, 0x06};
+
+
+
+static VOID ConstructEapolKeyData(
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN UCHAR GroupKeyWepStatus,
+ IN UCHAR keyDescVer,
+ IN UCHAR MsgType,
+ IN UCHAR DefaultKeyIdx,
+ IN UCHAR *GTK,
+ IN UCHAR *RSNIE,
+ IN UCHAR RSNIE_LEN,
+ OUT PEAPOL_PACKET pMsg);
+
+static VOID WpaEAPPacketAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+static VOID WpaEAPOLASFAlertAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+static VOID WpaEAPOLLogoffAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+static VOID WpaEAPOLStartAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+static VOID WpaEAPOLKeyAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+/*
+ ==========================================================================
+ Description:
+ association state machine init, including state transition and timer init
+ Parameters:
+ S - pointer to the association state machine
+ ==========================================================================
+ */
+VOID WpaStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ OUT STATE_MACHINE_FUNC Trans[])
+{
+ StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_WPA_PTK_STATE, MAX_WPA_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PTK, WPA_MACHINE_BASE);
+
+ StateMachineSetAction(S, WPA_PTK, MT2_EAPPacket, (STATE_MACHINE_FUNC)WpaEAPPacketAction);
+ StateMachineSetAction(S, WPA_PTK, MT2_EAPOLStart, (STATE_MACHINE_FUNC)WpaEAPOLStartAction);
+ StateMachineSetAction(S, WPA_PTK, MT2_EAPOLLogoff, (STATE_MACHINE_FUNC)WpaEAPOLLogoffAction);
+ StateMachineSetAction(S, WPA_PTK, MT2_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction);
+ StateMachineSetAction(S, WPA_PTK, MT2_EAPOLASFAlert, (STATE_MACHINE_FUNC)WpaEAPOLASFAlertAction);
+}
+
+/*
+ ==========================================================================
+ Description:
+ this is state machine function.
+ When receiving EAP packets which is for 802.1x authentication use.
+ Not use in PSK case
+ Return:
+ ==========================================================================
+*/
+VOID WpaEAPPacketAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+VOID WpaEAPOLASFAlertAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+VOID WpaEAPOLLogoffAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+/*
+ ==========================================================================
+ Description:
+ Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c
+ Return:
+ ==========================================================================
+*/
+VOID WpaEAPOLStartAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ MAC_TABLE_ENTRY *pEntry;
+ PHEADER_802_11 pHeader;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n"));
+
+ pHeader = (PHEADER_802_11)Elem->Msg;
+
+ /*For normaol PSK, we enqueue an EAPOL-Start command to trigger the process.*/
+ if (Elem->MsgLen == 6)
+ pEntry = MacTableLookup(pAd, Elem->Msg);
+ else
+ {
+ pEntry = MacTableLookup(pAd, pHeader->Addr2);
+#ifdef WSC_AP_SUPPORT
+ /*
+ a WSC enabled AP must ignore EAPOL-Start frames received from clients that associated to
+ the AP with an RSN IE or SSN IE indicating a WPA2-PSK/WPA-PSK authentication method in
+ the assication request. <<from page52 in Wi-Fi Simple Config Specification version 1.0g>>
+ */
+ if (pEntry &&
+ (pEntry->apidx == MAIN_MBSSID) &&
+ (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE) &&
+ ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) &&
+ pEntry->bWscCapable)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WPS enabled AP: Ignore EAPOL-Start frames received from clients.\n"));
+ return;
+ }
+#endif /* WSC_AP_SUPPORT */
+ }
+
+ if (pEntry)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n", pEntry->PortSecured, pEntry->WpaState, pEntry->AuthMode, pEntry->PMKID_CacheIdx));
+
+ if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)
+ && (pEntry->WpaState < AS_PTKSTART)
+ && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND))))
+ {
+ pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
+ pEntry->WpaState = AS_INITPSK;
+ pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+ NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
+ pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
+
+ WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ This is state machine function.
+ When receiving EAPOL packets which is for 802.1x key management.
+ Use both in WPA, and WPAPSK case.
+ In this function, further dispatch to different functions according to the received packet. 3 categories are :
+ 1. normal 4-way pairwisekey and 2-way groupkey handshake
+ 2. MIC error (Countermeasures attack) report packet from STA.
+ 3. Request for pairwise/group key update from STA
+ Return:
+ ==========================================================================
+*/
+VOID WpaEAPOLKeyAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ MAC_TABLE_ENTRY *pEntry;
+ PHEADER_802_11 pHeader;
+ PEAPOL_PACKET pEapol_packet;
+ KEY_INFO peerKeyInfo;
+ UINT eapol_len;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n"));
+
+ pHeader = (PHEADER_802_11)Elem->Msg;
+ pEapol_packet = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
+ eapol_len = CONV_ARRARY_TO_UINT16(pEapol_packet->Body_Len) + LENGTH_EAPOL_H;
+
+ NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
+ NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pEapol_packet->KeyDesc.KeyInfo, sizeof(KEY_INFO));
+
+
+ *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo));
+
+ do
+ {
+ pEntry = MacTableLookup(pAd, pHeader->Addr2);
+
+ if (!pEntry || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry)))
+ break;
+
+ if (pEntry->AuthMode < Ndis802_11AuthModeWPA)
+ break;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPoL-Key frame from STA %02X-%02X-%02X-%02X-%02X-%02X\n", PRINT_MAC(pEntry->Addr)));
+
+ if (eapol_len > Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("The length of EAPoL packet is invalid \n"));
+ break;
+ }
+
+ if (((pEapol_packet->ProVer != EAPOL_VER) && (pEapol_packet->ProVer != EAPOL_VER2)) ||
+ ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC) && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n"));
+ break;
+ }
+
+ /* The value 1 shall be used for all EAPOL-Key frames to and from a STA when */
+ /* neither the group nor pairwise ciphers are CCMP for Key Descriptor 1.*/
+ if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) && (peerKeyInfo.KeyDescVer != KEY_DESC_TKIP))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(TKIP) \n"));
+ break;
+ }
+ /* The value 2 shall be used for all EAPOL-Key frames to and from a STA when */
+ /* either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2 or 3.*/
+ else if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled)
+ && (peerKeyInfo.KeyDescVer != KEY_DESC_AES)
+ && (peerKeyInfo.KeyDescVer != KEY_DESC_EXT))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(AES) pEntry->WepStatus=%d, peerKeyInfo.KeyDescVer=%d\n", pEntry->WepStatus, peerKeyInfo.KeyDescVer));
+ break;
+ }
+
+ /* Check if this STA is in class 3 state and the WPA state is started */
+ if ((pEntry->Sst == SST_ASSOC) && (pEntry->WpaState >= AS_INITPSK))
+ {
+ /* Check the Key Ack (bit 7) of the Key Information to determine the Authenticator */
+ /* or not.*/
+ /* An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL-*/
+ /* Key frame from the Authenticator must not have the Ack bit set.*/
+ if (peerKeyInfo.KeyAck == 1)
+ {
+ /* The frame is snet by Authenticator. */
+ /* So the Supplicant side shall handle this.*/
+
+ if ((peerKeyInfo.Secure == 0) && (peerKeyInfo.Request == 0) &&
+ (peerKeyInfo.Error == 0) && (peerKeyInfo.KeyType == PAIRWISEKEY))
+ {
+ /*
+ Process
+ 1. the message 1 of 4-way HS in WPA or WPA2
+ EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1)
+ 2. the message 3 of 4-way HS in WPA
+ EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3)
+ */
+ if (peerKeyInfo.KeyMic == 0)
+ PeerPairMsg1Action(pAd, pEntry, Elem);
+ else
+ PeerPairMsg3Action(pAd, pEntry, Elem);
+ }
+ else if ((peerKeyInfo.Secure == 1) &&
+ (peerKeyInfo.KeyMic == 1) &&
+ (peerKeyInfo.Request == 0) &&
+ (peerKeyInfo.Error == 0))
+ {
+ /*
+ Process
+ 1. the message 3 of 4-way HS in WPA2
+ EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3)
+ 2. the message 1 of group KS in WPA or WPA2
+ EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N])
+ */
+ if (peerKeyInfo.KeyType == PAIRWISEKEY)
+ PeerPairMsg3Action(pAd, pEntry, Elem);
+ else
+ PeerGroupMsg1Action(pAd, pEntry, Elem);
+ }
+ }
+ else
+ {
+ /*
+ The frame is snet by Supplicant.So the Authenticator
+ side shall handle this.
+ */
+#ifdef CONFIG_AP_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+ if ((peerKeyInfo.KeyMic == 1) &&
+ (peerKeyInfo.Secure == 1) &&
+ (peerKeyInfo.Error == 0) &&
+ (peerKeyInfo.KeyType == GROUPKEY) &&
+ (pEapol_packet->KeyDesc.KeyDataLen[1] == 12))
+ {
+ /* This is a ralink proprietary DLS STA-Key processing*/
+ RTMPHandleSTAKey(pAd, pEntry, Elem);
+ }
+ else
+#endif /* QOS_DLS_SUPPORT */
+ if ((peerKeyInfo.KeyMic == 1) &&
+ (peerKeyInfo.Request == 1) &&
+ (peerKeyInfo.Error == 1))
+ {
+ /* The Supplicant uses a single Michael MIC Failure Report frame */
+ /* to report a MIC failure event to the Authenticator. */
+ /* A Michael MIC Failure Report is an EAPOL-Key frame with */
+ /* the following Key Information field bits set to 1: */
+ /* MIC bit, Error bit, Request bit, Secure bit.*/
+
+ DBGPRINT(RT_DEBUG_ERROR, ("Received an Michael MIC Failure Report, active countermeasure \n"));
+ RTMP_HANDLE_COUNTER_MEASURE(pAd, pEntry);
+ }
+ else
+#endif /* CONFIG_AP_SUPPORT */
+ if ((peerKeyInfo.Request == 0) &&
+ (peerKeyInfo.Error == 0) &&
+ (peerKeyInfo.KeyMic == 1))
+ {
+ if (peerKeyInfo.Secure == 0 && peerKeyInfo.KeyType == PAIRWISEKEY)
+ {
+ /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,Data)*/
+ /* Process 1. message 2 of 4-way HS in WPA or WPA2 */
+ /* 2. message 4 of 4-way HS in WPA */
+ if (CONV_ARRARY_TO_UINT16(pEapol_packet->KeyDesc.KeyDataLen) == 0)
+ {
+ PeerPairMsg4Action(pAd, pEntry, Elem);
+ }
+ else
+ {
+ PeerPairMsg2Action(pAd, pEntry, Elem);
+ }
+ }
+ else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == PAIRWISEKEY)
+ {
+ /* EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0) */
+ /* Process message 4 of 4-way HS in WPA2*/
+ PeerPairMsg4Action(pAd, pEntry, Elem);
+ }
+ else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == GROUPKEY)
+ {
+ /* EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0)*/
+ /* Process message 2 of Group key HS in WPA or WPA2 */
+ PeerGroupMsg2Action(pAd, pEntry, &Elem->Msg[LENGTH_802_11], (Elem->MsgLen - LENGTH_802_11));
+ }
+ }
+#ifdef CONFIG_AP_SUPPORT
+ else if ((peerKeyInfo.Request == 1) && (peerKeyInfo.Error == 0))
+ {
+ INT i;
+ UCHAR apidx = pEntry->apidx;
+
+ /* Need to check KeyType for groupkey or pairwise key update, refer to 8021i P.114, */
+ if (peerKeyInfo.KeyType == GROUPKEY)
+ {
+ UINT8 Wcid;
+ PMULTISSID_STRUCT pMbssEntry;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("REQUEST=1, ERROR=0, update group key\n"));
+
+ pMbssEntry = &pAd->ApCfg.MBSSID[apidx];
+
+ GenRandom(pAd, pMbssEntry->Bssid, pMbssEntry->GNonce);
+ pMbssEntry->DefaultKeyId = (pMbssEntry->DefaultKeyId == 1) ? 2 : 1;
+ WpaDeriveGTK(pMbssEntry->GMK,
+ pMbssEntry->GNonce,
+ pMbssEntry->Bssid,
+ pMbssEntry->GTK, LEN_TKIP_GTK);
+
+ for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i])
+ && (pAd->MacTab.Content[i].WpaState == AS_PTKINITDONE)
+ && (pAd->MacTab.Content[i].apidx == apidx))
+ {
+ pAd->MacTab.Content[i].GTKState = REKEY_NEGOTIATING;
+ WPAStart2WayGroupHS(pAd, &pAd->MacTab.Content[i]);
+ pAd->MacTab.Content[i].ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR;
+ RTMPModTimer(&pAd->MacTab.Content[i].RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
+ }
+ }
+
+ /* Get a specific WCID to record this MBSS key attribute */
+ GET_GroupKey_WCID(pAd, Wcid, apidx);
+
+ WPAInstallSharedKey(pAd,
+ pMbssEntry->GroupKeyWepStatus,
+ apidx,
+ pMbssEntry->DefaultKeyId,
+ Wcid,
+ TRUE,
+ pMbssEntry->GTK,
+ LEN_TKIP_GTK);
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("REQUEST=1, ERROR= 0, update pairwise key\n"));
+
+ NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY));
+
+ /* clear this entry as no-security mode*/
+ AsicRemovePairwiseKeyEntry(pAd, pEntry->Aid);
+
+ pEntry->Sst = SST_ASSOC;
+ if (pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPA2)
+ pEntry->WpaState = AS_INITPMK;
+ else if (pEntry->AuthMode == Ndis802_11AuthModeWPAPSK || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
+ pEntry->WpaState = AS_INITPSK;
+
+ pEntry->GTKState = REKEY_NEGOTIATING;
+ pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
+ pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
+ pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+ NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
+
+ WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ }
+ }while(FALSE);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Copy frame from waiting queue into relative ring buffer and set
+ appropriate ASIC register to kick hardware encryption before really
+ sent out to air.
+
+ Arguments:
+ pAd Pointer to our adapter
+ PNDIS_PACKET Pointer to outgoing Ndis frame
+ NumberOfFrag Number of fragment required
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPToWirelessSta(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PUCHAR pHeader802_3,
+ IN UINT HdrLen,
+ IN PUCHAR pData,
+ IN UINT DataLen,
+ IN BOOLEAN bClearFrame)
+{
+ PNDIS_PACKET pPacket;
+ NDIS_STATUS Status;
+
+ if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry)
+ ))
+ return;
+
+ do {
+ /* build a NDIS packet*/
+ Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen);
+ if (Status != NDIS_STATUS_SUCCESS)
+ break;
+
+
+ if (bClearFrame)
+ RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1);
+ else
+ RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0);
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(pEntry))
+ {
+ RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
+ RTMP_SET_PACKET_MOREDATA(pPacket, FALSE);
+ RTMP_SET_PACKET_NET_DEVICE_APCLI(pPacket, pEntry->MatchAPCLITabIdx);
+ RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid); /* to ApClient links.*/
+ }
+ else
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ {
+ RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
+
+ RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); /* set a default value*/
+ if(pEntry->apidx != 0)
+ RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, pEntry->apidx);
+
+ RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
+ RTMP_SET_PACKET_MOREDATA(pPacket, FALSE);
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* send out the packet */
+ APSendPacket(pAd, pPacket);
+
+ /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it*/
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ } while (FALSE);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Check the validity of the received EAPoL frame
+ Return:
+ TRUE if all parameters are OK,
+ FALSE otherwise
+ ==========================================================================
+ */
+BOOLEAN PeerWpaMessageSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN PEAPOL_PACKET pMsg,
+ IN ULONG MsgLen,
+ IN UCHAR MsgType,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ UCHAR mic[LEN_KEY_DESC_MIC], digest[80]; /*, KEYDATA[MAX_LEN_OF_RSNIE];*/
+ UCHAR *KEYDATA = NULL;
+ BOOLEAN bReplayDiff = FALSE;
+ BOOLEAN bWPA2 = FALSE;
+ KEY_INFO EapolKeyInfo;
+ UCHAR GroupKeyIndex = 0;
+
+
+ /* allocate memory */
+ os_alloc_mem(NULL, (UCHAR **)&KEYDATA, MAX_LEN_OF_RSNIE);
+ if (KEYDATA == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ NdisZeroMemory(mic, sizeof(mic));
+ NdisZeroMemory(digest, sizeof(digest));
+ NdisZeroMemory(KEYDATA, MAX_LEN_OF_RSNIE);
+ NdisZeroMemory((PUCHAR)&EapolKeyInfo, sizeof(EapolKeyInfo));
+
+ NdisMoveMemory((PUCHAR)&EapolKeyInfo, (PUCHAR)&pMsg->KeyDesc.KeyInfo, sizeof(KEY_INFO));
+
+ *((USHORT *)&EapolKeyInfo) = cpu2le16(*((USHORT *)&EapolKeyInfo));
+
+ /* Choose WPA2 or not*/
+ if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
+ bWPA2 = TRUE;
+
+ /* 0. Check MsgType*/
+ if ((MsgType > EAPOL_GROUP_MSG_2) || (MsgType < EAPOL_PAIR_MSG_1))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("The message type is invalid(%d)! \n", MsgType));
+ goto LabelErr;
+ }
+
+ /* 1. Replay counter check */
+ if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1) /* For supplicant*/
+ {
+ /* First validate replay counter, only accept message with larger replay counter.*/
+ /* Let equal pass, some AP start with all zero replay counter*/
+ UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY];
+
+ NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
+ if ((RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY) != 1) &&
+ (RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
+ {
+ bReplayDiff = TRUE;
+ }
+ }
+ else if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) /* For authenticator*/
+ {
+ /* check Replay Counter coresponds to MSG from authenticator, otherwise discard*/
+ if (!NdisEqualMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY))
+ {
+ bReplayDiff = TRUE;
+ }
+ }
+
+ /* Replay Counter different condition*/
+ if (bReplayDiff)
+ {
+ /* send wireless event - for replay counter different*/
+ RTMPSendWirelessEvent(pAd, IW_REPLAY_COUNTER_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+ if (MsgType < EAPOL_GROUP_MSG_1)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in pairwise msg %d of 4-way handshake!\n", MsgType));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4)));
+ }
+
+ hex_dump("Receive replay counter ", pMsg->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+ hex_dump("Current replay counter ", pEntry->R_Counter, LEN_KEY_DESC_REPLAY);
+ goto LabelErr;
+ }
+
+ /* 2. Verify MIC except Pairwise Msg1*/
+ if (MsgType != EAPOL_PAIR_MSG_1)
+ {
+ UCHAR rcvd_mic[LEN_KEY_DESC_MIC];
+ UINT eapol_len = CONV_ARRARY_TO_UINT16(pMsg->Body_Len) + 4;
+
+ /* Record the received MIC for check later*/
+ NdisMoveMemory(rcvd_mic, pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+ NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+
+ if (EapolKeyInfo.KeyDescVer == KEY_DESC_TKIP) /* TKIP*/
+ {
+ RT_HMAC_MD5(pEntry->PTK, LEN_PTK_KCK, (PUCHAR)pMsg, eapol_len, mic, MD5_DIGEST_SIZE);
+ }
+ else if (EapolKeyInfo.KeyDescVer == KEY_DESC_AES) /* AES */
+ {
+ RT_HMAC_SHA1(pEntry->PTK, LEN_PTK_KCK, (PUCHAR)pMsg, eapol_len, digest, SHA1_DIGEST_SIZE);
+ NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
+ }
+ else if (EapolKeyInfo.KeyDescVer == KEY_DESC_EXT) /* AES-128 */
+ {
+ UINT mlen = AES_KEY128_LENGTH;
+ AES_CMAC((PUCHAR)pMsg, eapol_len, pEntry->PTK, LEN_PTK_KCK, mic, &mlen);
+ }
+
+
+ if (!NdisEqualMemory(rcvd_mic, mic, LEN_KEY_DESC_MIC))
+ {
+ /* send wireless event - for MIC different*/
+ RTMPSendWirelessEvent(pAd, IW_MIC_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+ if (MsgType < EAPOL_GROUP_MSG_1)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in pairwise msg %d of 4-way handshake!\n", MsgType));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4)));
+ }
+
+ hex_dump("Received MIC", rcvd_mic, LEN_KEY_DESC_MIC);
+ hex_dump("Desired MIC", mic, LEN_KEY_DESC_MIC);
+
+ goto LabelErr;
+ }
+ }
+
+ /* 1. Decrypt the Key Data field if GTK is included.*/
+ /* 2. Extract the context of the Key Data field if it exist. */
+ /* The field in pairwise_msg_2_WPA1(WPA2) & pairwise_msg_3_WPA1 is clear.*/
+ /* The field in group_msg_1_WPA1(WPA2) & pairwise_msg_3_WPA2 is encrypted.*/
+ if (CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen) > 0)
+ {
+ /* Decrypt this field */
+ if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
+ {
+ if((EapolKeyInfo.KeyDescVer == KEY_DESC_EXT) || (EapolKeyInfo.KeyDescVer == KEY_DESC_AES))
+ {
+ UINT aes_unwrap_len = 0;
+
+ /* AES */
+ AES_Key_Unwrap(pMsg->KeyDesc.KeyData,
+ CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen),
+ &pEntry->PTK[LEN_PTK_KCK], LEN_PTK_KEK,
+ KEYDATA, &aes_unwrap_len);
+ SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, aes_unwrap_len);
+ }
+ else
+ {
+ TKIP_GTK_KEY_UNWRAP(&pEntry->PTK[LEN_PTK_KCK],
+ pMsg->KeyDesc.KeyIv,
+ pMsg->KeyDesc.KeyData,
+ CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen),
+ KEYDATA);
+ }
+
+ if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
+ GroupKeyIndex = EapolKeyInfo.KeyIndex;
+
+ }
+ else if ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3 && !bWPA2))
+ {
+ NdisMoveMemory(KEYDATA, pMsg->KeyDesc.KeyData, CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen));
+ }
+ else
+ {
+
+ goto LabelOK;
+ }
+
+ /* Parse Key Data field to */
+ /* 1. verify RSN IE for pairwise_msg_2_WPA1(WPA2) ,pairwise_msg_3_WPA1(WPA2)*/
+ /* 2. verify KDE format for pairwise_msg_3_WPA2, group_msg_1_WPA2*/
+ /* 3. update shared key for pairwise_msg_3_WPA2, group_msg_1_WPA1(WPA2)*/
+ if (!RTMPParseEapolKeyData(pAd, KEYDATA,
+ CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen),
+ GroupKeyIndex, MsgType, bWPA2, pEntry))
+ {
+ goto LabelErr;
+ }
+ }
+
+LabelOK:
+ if (KEYDATA != NULL)
+ os_free_mem(NULL, KEYDATA);
+ return TRUE;
+
+LabelErr:
+ if (KEYDATA != NULL)
+ os_free_mem(NULL, KEYDATA);
+ return FALSE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ This is a function to initilize 4-way handshake
+
+ Return:
+
+ ==========================================================================
+*/
+VOID WPAStart4WayHS(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN ULONG TimeInterval)
+{
+ UCHAR Header802_3[14];
+ UCHAR *mpool;
+ PEAPOL_PACKET pEapolFrame;
+ PUINT8 pBssid = NULL;
+ UCHAR group_cipher = Ndis802_11WEPDisabled;
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR apidx = 0;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n"));
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The interface is closed...\n"));
+ return;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The entry doesn't exist.\n"));
+ return;
+ }
+
+ if (pEntry->apidx < pAd->ApCfg.BssidNum)
+ {
+ apidx = pEntry->apidx;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The apidx(%d) is invalid.\n", pEntry->apidx));
+ return;
+ }
+
+ /* pointer to the corresponding position*/
+ pBssid = pAd->ApCfg.MBSSID[apidx].Bssid;
+ group_cipher = pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pBssid == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n"));
+ return;
+ }
+
+ /* Check the status*/
+ if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : Not expect calling\n"));
+ return;
+ }
+
+#ifdef WSC_AP_SUPPORT
+ if (MAC_ADDR_EQUAL(pEntry->Addr, pAd->ApCfg.MBSSID[apidx].WscControl.EntryAddr) &&
+ pAd->ApCfg.MBSSID[apidx].WscControl.EapMsgRunning)
+ {
+ pEntry->WpaState = AS_NOTUSE;
+ DBGPRINT(RT_DEBUG_ERROR, ("This is a WSC-Enrollee. Not expect calling WPAStart4WayHS here \n"));
+ return;
+ }
+#endif /* WSC_AP_SUPPORT */
+
+ /* Increment replay counter by 1*/
+ ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
+
+ /* Randomly generate ANonce */
+ GenRandom(pAd, (UCHAR *)pBssid, pEntry->ANonce);
+
+ /* Allocate memory for output*/
+ os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
+ if (mpool == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
+ return;
+ }
+
+ pEapolFrame = (PEAPOL_PACKET)mpool;
+ NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER);
+
+ /* Construct EAPoL message - Pairwise Msg 1*/
+ /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */
+ ConstructEapolMsg(pEntry,
+ group_cipher,
+ EAPOL_PAIR_MSG_1,
+ 0, /* Default key index*/
+ pEntry->ANonce,
+ NULL, /* TxRSC*/
+ NULL, /* GTK*/
+ NULL, /* RSNIE*/
+ 0, /* RSNIE length */
+ pEapolFrame);
+
+#ifdef CONFIG_AP_SUPPORT
+ /* If PMKID match in WPA2-enterprise mode, fill PMKID into Key data field and update PMK here */
+ if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND))
+ {
+ /* Fill in value for KDE */
+ pEapolFrame->KeyDesc.KeyData[0] = 0xDD;
+ pEapolFrame->KeyDesc.KeyData[2] = 0x00;
+ pEapolFrame->KeyDesc.KeyData[3] = 0x0F;
+ pEapolFrame->KeyDesc.KeyData[4] = 0xAC;
+ pEapolFrame->KeyDesc.KeyData[5] = 0x04;
+
+ NdisMoveMemory(&pEapolFrame->KeyDesc.KeyData[6], &pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[pEntry->PMKID_CacheIdx].PMKID, LEN_PMKID);
+ NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMK, &pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[pEntry->PMKID_CacheIdx].PMK, PMK_LEN);
+
+ pEapolFrame->KeyDesc.KeyData[1] = 0x14;/* 4+LEN_PMKID*/
+ INC_UINT16_TO_ARRARY(pEapolFrame->KeyDesc.KeyDataLen, 6 + LEN_PMKID);
+ INC_UINT16_TO_ARRARY(pEapolFrame->Body_Len, 6 + LEN_PMKID);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Make outgoing frame*/
+ MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
+ RTMPToWirelessSta(pAd, pEntry, Header802_3,
+ LENGTH_802_3, (PUCHAR)pEapolFrame,
+ CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4,
+ (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
+
+ /* Trigger Retry Timer*/
+ RTMPModTimer(&pEntry->RetryTimer, TimeInterval);
+
+ /* Update State*/
+ pEntry->WpaState = AS_PTKSTART;
+
+ os_free_mem(NULL, mpool);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart4WayHS: send Msg1 of 4-way \n"));
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2
+
+ Arguments:
+ pAd Pointer to our adapter
+ Elem Message body
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID PeerPairMsg1Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR PTK[80];
+ UCHAR Header802_3[14];
+ PEAPOL_PACKET pMsg1;
+ UINT MsgLen;
+ UCHAR *mpool;
+ PEAPOL_PACKET pEapolFrame;
+ PUINT8 pCurrentAddr = NULL;
+ PUINT8 pmk_ptr = NULL;
+ UCHAR group_cipher = Ndis802_11WEPDisabled;
+ PUINT8 rsnie_ptr = NULL;
+ UCHAR rsnie_len = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n"));
+
+ if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry)))
+ return;
+
+ if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG))
+ return;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(pEntry))
+ {
+ UINT IfIndex = 0;
+
+ IfIndex = pEntry->MatchAPCLITabIdx;
+ if (IfIndex >= MAX_APCLI_NUM)
+ return;
+
+ pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].CurrentAddress;
+ pmk_ptr = pAd->ApCfg.ApCliTab[IfIndex].PMK;
+ group_cipher = pAd->ApCfg.ApCliTab[IfIndex].GroupCipher;
+ rsnie_ptr = pAd->ApCfg.ApCliTab[IfIndex].RSN_IE;
+ rsnie_len = pAd->ApCfg.ApCliTab[IfIndex].RSNIE_Len;
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pCurrentAddr == NULL)
+ return;
+
+ /* Store the received frame*/
+ pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
+ MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
+
+ /* Sanity Check peer Pairwise message 1 - Replay Counter*/
+ if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry) == FALSE)
+ return;
+
+ /* Store Replay counter, it will use to verify message 3 and construct message 2*/
+ NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+ /* Store ANonce*/
+ NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
+
+ /* Generate random SNonce*/
+ GenRandom(pAd, (UCHAR *)pCurrentAddr, pEntry->SNonce);
+
+ {
+ /* Calculate PTK(ANonce, SNonce)*/
+ WpaDerivePTK(pAd,
+ pmk_ptr,
+ pEntry->ANonce,
+ pEntry->Addr,
+ pEntry->SNonce,
+ pCurrentAddr,
+ PTK,
+ LEN_PTK);
+
+ /* Save key to PTK entry*/
+ NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
+ }
+
+ /* Update WpaState*/
+ pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
+
+ /* Allocate memory for output*/
+ os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
+ if (mpool == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
+ return;
+ }
+
+ pEapolFrame = (PEAPOL_PACKET)mpool;
+ NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER);
+
+ /* Construct EAPoL message - Pairwise Msg 2*/
+ /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2)*/
+ ConstructEapolMsg(pEntry,
+ group_cipher,
+ EAPOL_PAIR_MSG_2,
+ 0, /* DefaultKeyIdx*/
+ pEntry->SNonce,
+ NULL, /* TxRsc*/
+ NULL, /* GTK*/
+ (UCHAR *)rsnie_ptr,
+ rsnie_len,
+ pEapolFrame);
+
+ /* Make outgoing frame*/
+ MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
+
+ RTMPToWirelessSta(pAd, pEntry,
+ Header802_3, sizeof(Header802_3), (PUCHAR)pEapolFrame,
+ CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, TRUE);
+
+ os_free_mem(NULL, mpool);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n"));
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ When receiving the second packet of 4-way pairwisekey handshake.
+ Return:
+ ==========================================================================
+*/
+VOID PeerPairMsg2Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR PTK[80];
+ BOOLEAN Cancelled;
+ PHEADER_802_11 pHeader;
+ UCHAR *mpool;
+ PEAPOL_PACKET pEapolFrame;
+ PEAPOL_PACKET pMsg2;
+ UINT MsgLen;
+ UCHAR Header802_3[LENGTH_802_3];
+ UCHAR TxTsc[6];
+ PUINT8 pBssid = NULL;
+ PUINT8 pmk_ptr = NULL;
+ PUINT8 gtk_ptr = NULL;
+ UCHAR default_key = 0;
+ UCHAR group_cipher = Ndis802_11WEPDisabled;
+ PUINT8 rsnie_ptr = NULL;
+ UCHAR rsnie_len = 0;
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR apidx = 0;
+#endif /* CONFIG_AP_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n"));
+
+ if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry))
+ return;
+
+ if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG))
+ return;
+
+ /* check Entry in valid State*/
+ if (pEntry->WpaState < AS_PTKSTART)
+ return;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if (pEntry->apidx >= pAd->ApCfg.BssidNum)
+ return;
+ else
+ apidx = pEntry->apidx;
+
+ pBssid = pAd->ApCfg.MBSSID[apidx].Bssid;
+ pmk_ptr = pAd->ApCfg.MBSSID[apidx].PMK;
+ gtk_ptr = pAd->ApCfg.MBSSID[apidx].GTK;
+ group_cipher = pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus;
+ default_key = pAd->ApCfg.MBSSID[apidx].DefaultKeyId;
+
+ /* Get Group TxTsc form Asic*/
+ RTMPGetTxTscFromAsic(pAd, apidx, TxTsc);
+
+ if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPAPSK))
+ {
+ rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0];
+ rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0];
+ }
+ else
+ {
+ if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) ||
+ (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2))
+ {
+ rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1];
+ rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[1][0];
+ }
+ else
+ {
+ rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0];
+ rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0];
+ }
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /* pointer to 802.11 header*/
+ pHeader = (PHEADER_802_11)Elem->Msg;
+
+ /* skip 802.11_header(24-byte) and LLC_header(8) */
+ pMsg2 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
+ MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
+
+ /* Store SNonce*/
+ NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
+
+ {
+ /* Derive PTK*/
+ if ((pmk_ptr == NULL) || (pBssid == NULL))
+ {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("%s: pmk_ptr or pBssid == NULL!\n", __FUNCTION__));
+ return;
+ }
+
+ WpaDerivePTK(pAd,
+ (UCHAR *)pmk_ptr,
+ pEntry->ANonce, /* ANONCE*/
+ (UCHAR *)pBssid,
+ pEntry->SNonce, /* SNONCE*/
+ pEntry->Addr,
+ PTK,
+ LEN_PTK);
+
+ NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
+ }
+
+ /* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE*/
+ if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry) == FALSE)
+ return;
+
+ do
+ {
+ /* Allocate memory for input*/
+ os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
+ if (mpool == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
+ return;
+ }
+
+ pEapolFrame = (PEAPOL_PACKET)mpool;
+ NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER);
+
+ /* delete retry timer*/
+ RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
+
+ /* Change state*/
+ pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
+
+ /* Increment replay counter by 1*/
+ ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
+
+ /* Construct EAPoL message - Pairwise Msg 3*/
+ ConstructEapolMsg(pEntry,
+ group_cipher,
+ EAPOL_PAIR_MSG_3,
+ default_key,
+ pEntry->ANonce,
+ TxTsc,
+ (UCHAR *)gtk_ptr,
+ (UCHAR *)rsnie_ptr,
+ rsnie_len,
+ pEapolFrame);
+
+ /* Make outgoing frame*/
+ MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
+ RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3,
+ (PUCHAR)pEapolFrame,
+ CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4,
+ (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
+
+ pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR;
+ RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
+
+ /* Update State*/
+ pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
+
+ os_free_mem(NULL, mpool);
+
+ }while(FALSE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4
+
+ Arguments:
+ pAd Pointer to our adapter
+ Elem Message body
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID PeerPairMsg3Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PHEADER_802_11 pHeader;
+ UCHAR Header802_3[14];
+ UCHAR *mpool;
+ PEAPOL_PACKET pEapolFrame;
+ PEAPOL_PACKET pMsg3;
+ UINT MsgLen;
+ PUINT8 pCurrentAddr = NULL;
+ UCHAR group_cipher = Ndis802_11WEPDisabled;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n"));
+
+ if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry)))
+ return;
+
+ if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG))
+ return;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(pEntry))
+ {
+ UINT IfIndex = 0;
+
+ IfIndex = pEntry->MatchAPCLITabIdx;
+ if (IfIndex >= MAX_APCLI_NUM)
+ return;
+
+ pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].CurrentAddress;
+ group_cipher = pAd->ApCfg.ApCliTab[IfIndex].GroupCipher;
+
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pCurrentAddr == NULL)
+ return;
+
+ /* Record 802.11 header & the received EAPOL packet Msg3*/
+ pHeader = (PHEADER_802_11) Elem->Msg;
+ pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
+ MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
+
+ /* Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE*/
+ if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry) == FALSE)
+ return;
+
+ /* Save Replay counter, it will use construct message 4*/
+ NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+ /* Double check ANonce*/
+ if (!NdisEqualMemory(pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
+ {
+ return;
+ }
+
+ /* Allocate memory for output*/
+ os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
+ if (mpool == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
+ return;
+ }
+
+ pEapolFrame = (PEAPOL_PACKET)mpool;
+ NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER);
+
+ /* Construct EAPoL message - Pairwise Msg 4*/
+ ConstructEapolMsg(pEntry,
+ group_cipher,
+ EAPOL_PAIR_MSG_4,
+ 0, /* group key index not used in message 4*/
+ NULL, /* Nonce not used in message 4*/
+ NULL, /* TxRSC not used in message 4*/
+ NULL, /* GTK not used in message 4*/
+ NULL, /* RSN IE not used in message 4*/
+ 0,
+ pEapolFrame);
+
+ /* Update WpaState*/
+ pEntry->WpaState = AS_PTKINITDONE;
+ /* Update pairwise key */
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(pEntry))
+ APCliInstallPairwiseKey(pAd, pEntry);
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* open 802.1x port control and privacy filter*/
+ if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK ||
+ pEntry->AuthMode == Ndis802_11AuthModeWPA2)
+ {
+ pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
+ pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
+#ifdef CONFIG_MULTI_CHANNEL
+ if (pAd->Multi_Channel_Enable == TRUE)
+ {
+ MultiChannelTimerStart(pAd,pEntry);
+ }
+#endif /*CONFIG_MULTI_CHANNEL*/
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
+ GetAuthMode(pEntry->AuthMode),
+ GetEncryptType(pEntry->WepStatus),
+ GetEncryptType(group_cipher)));
+ }
+ else
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ /* Patch issue with gateway AP*/
+ /* In WPA mode, AP doesn't send out message 1 of group-key HS.*/
+ /* So, Supplicant shall maintain a timeout action to disconnect */
+ /* this link.*/
+ /* Todo - Does it need to apply to STA ?*/
+ if (IS_ENTRY_APCLI(pEntry))
+ RTMPSetTimer(&pEntry->RetryTimer, PEER_GROUP_KEY_UPDATE_INIV);
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+ /* Init 802.3 header and send out*/
+ MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
+ RTMPToWirelessSta(pAd, pEntry,
+ Header802_3, sizeof(Header802_3),
+ (PUCHAR)pEapolFrame,
+ CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, TRUE);
+
+ os_free_mem(NULL, mpool);
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n"));
+}
+
+/*
+ ==========================================================================
+ Description:
+ When receiving the last packet of 4-way pairwisekey handshake.
+ Initilize 2-way groupkey handshake following.
+ Return:
+ ==========================================================================
+*/
+VOID PeerPairMsg4Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PEAPOL_PACKET pMsg4;
+ PHEADER_802_11 pHeader;
+ UINT MsgLen;
+ BOOLEAN Cancelled;
+ UCHAR group_cipher = Ndis802_11WEPDisabled;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n"));
+
+ do
+ {
+ if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry))
+ break;
+
+ if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG ) )
+ break;
+
+ if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING)
+ break;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ UCHAR apidx = 0;
+
+ if (pEntry->apidx >= pAd->ApCfg.BssidNum)
+ break;
+ else
+ apidx = pEntry->apidx;
+
+ group_cipher = pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* pointer to 802.11 header*/
+ pHeader = (PHEADER_802_11)Elem->Msg;
+
+ /* skip 802.11_header(24-byte) and LLC_header(8) */
+ pMsg4 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
+ MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
+
+ /* Sanity Check peer Pairwise message 4 - Replay Counter, MIC*/
+ if (PeerWpaMessageSanity(pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE)
+ break;
+
+ /* 3. Install pairwise key */
+ WPAInstallPairwiseKey(pAd, pEntry->apidx, pEntry, TRUE);
+
+ /* 4. upgrade state */
+ pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
+ pEntry->WpaState = AS_PTKINITDONE;
+ pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
+
+#ifdef WSC_AP_SUPPORT
+ if (pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE)
+ WscInformFromWPA(pEntry);
+#endif /* WSC_AP_SUPPORT */
+
+ if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 ||
+ pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
+ {
+ pEntry->GTKState = REKEY_ESTABLISHED;
+ RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef DOT1X_SUPPORT
+ if (pEntry->AuthMode == Ndis802_11AuthModeWPA2)
+ {
+ UCHAR PMK_key[20];
+ UCHAR digest[80];
+
+ /* Calculate PMKID, refer to IEEE 802.11i-2004 8.5.1.2*/
+ NdisMoveMemory(&PMK_key[0], "PMK Name", 8);
+ NdisMoveMemory(&PMK_key[8], pAd->ApCfg.MBSSID[pEntry->apidx].Bssid, MAC_ADDR_LEN);
+ NdisMoveMemory(&PMK_key[14], pEntry->Addr, MAC_ADDR_LEN);
+ RT_HMAC_SHA1(pAd->ApCfg.MBSSID[pEntry->apidx].PMK, PMK_LEN, PMK_key, 20, digest, SHA1_DIGEST_SIZE);
+ RTMPAddPMKIDCache(pAd, pEntry->apidx, pEntry->Addr, digest, pAd->ApCfg.MBSSID[pEntry->apidx].PMK);
+ DBGPRINT(RT_DEBUG_TRACE, ("Calc PMKID=%02x:%02x:%02x:%02x:%02x:%02x\n", digest[0],digest[1],digest[2],digest[3],digest[4],digest[5]));
+ }
+#endif /* DOT1X_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* send wireless event - for set key done WPA2*/
+ RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+ DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
+ pEntry->AuthMode, GetAuthMode(pEntry->AuthMode),
+ pEntry->WepStatus, GetEncryptType(pEntry->WepStatus),
+ group_cipher,
+ GetEncryptType(group_cipher)));
+ }
+ else
+ {
+ /* 5. init Group 2-way handshake if necessary.*/
+ WPAStart2WayGroupHS(pAd, pEntry);
+
+ pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR;
+ RTMPModTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
+ }
+ }while(FALSE);
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ This is a function to send the first packet of 2-way groupkey handshake
+ Return:
+
+ ==========================================================================
+*/
+VOID WPAStart2WayGroupHS(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ UCHAR Header802_3[14];
+ UCHAR TxTsc[6];
+ UCHAR *mpool;
+ PEAPOL_PACKET pEapolFrame;
+ UCHAR group_cipher = Ndis802_11WEPDisabled;
+ UCHAR default_key = 0;
+ PUINT8 gnonce_ptr = NULL;
+ PUINT8 gtk_ptr = NULL;
+ PUINT8 pBssid = NULL;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n"));
+
+ if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry))
+ return;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ UCHAR apidx = 0;
+
+ if (pEntry->apidx >= pAd->ApCfg.BssidNum)
+ return;
+ else
+ apidx = pEntry->apidx;
+
+ group_cipher = pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus;
+ default_key = pAd->ApCfg.MBSSID[apidx].DefaultKeyId;
+ gnonce_ptr = pAd->ApCfg.MBSSID[apidx].GNonce;
+ gtk_ptr = pAd->ApCfg.MBSSID[apidx].GTK;
+ pBssid = pAd->ApCfg.MBSSID[apidx].Bssid;
+
+ /* Get Group TxTsc form Asic*/
+ RTMPGetTxTscFromAsic(pAd, apidx, TxTsc);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Allocate memory for output*/
+ os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
+ if (mpool == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
+ return;
+ }
+
+ pEapolFrame = (PEAPOL_PACKET)mpool;
+ NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER);
+
+ /* Increment replay counter by 1*/
+ ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
+
+ /* Construct EAPoL message - Group Msg 1*/
+ ConstructEapolMsg(pEntry,
+ group_cipher,
+ EAPOL_GROUP_MSG_1,
+ default_key,
+ (UCHAR *)gnonce_ptr,
+ TxTsc,
+ (UCHAR *)gtk_ptr,
+ NULL,
+ 0,
+ pEapolFrame);
+
+ /* Make outgoing frame*/
+ if (pBssid == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pBssid == NULL!\n", __FUNCTION__));
+ return;
+ }
+
+ MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
+ RTMPToWirelessSta(pAd, pEntry,
+ Header802_3, LENGTH_802_3,
+ (PUCHAR)pEapolFrame,
+ CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, FALSE);
+
+ os_free_mem(NULL, mpool);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n"));
+
+ return;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process Group key 2-way handshaking
+
+ Arguments:
+ pAd Pointer to our adapter
+ Elem Message body
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID PeerGroupMsg1Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Header802_3[14];
+ UCHAR *mpool;
+ PEAPOL_PACKET pEapolFrame;
+ PEAPOL_PACKET pGroup;
+ UINT MsgLen;
+ UCHAR default_key = 0;
+ UCHAR group_cipher = Ndis802_11WEPDisabled;
+ PUINT8 pCurrentAddr = NULL;
+#ifdef APCLI_SUPPORT
+ BOOLEAN Cancelled;
+#endif /* APCLI_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n"));
+
+ if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry)))
+ return;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(pEntry))
+ {
+ UINT IfIndex = 0;
+
+ IfIndex = pEntry->MatchAPCLITabIdx;
+ if (IfIndex >= MAX_APCLI_NUM)
+ return;
+
+ pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].CurrentAddress;
+ group_cipher = pAd->ApCfg.ApCliTab[IfIndex].GroupCipher;
+ default_key = pAd->ApCfg.ApCliTab[IfIndex].DefaultKeyId;
+
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pCurrentAddr == NULL)
+ return;
+
+ /* Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8)*/
+ pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
+ MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
+
+ /* Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE*/
+ if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry) == FALSE)
+ return;
+
+ /* delete retry timer*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ /* Patch issue with gateway AP*/
+ /* In WPA mode, AP doesn't send out message 1 of group-key HS.*/
+ /* So, Supplicant shall maintain a timeout action to disconnect */
+ /* this link.*/
+ /* Todo - Does it need to apply to STA ?*/
+ if (IS_ENTRY_APCLI(pEntry))
+ RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Save Replay counter, it will use to construct message 2*/
+ NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+ /* Allocate memory for output*/
+ os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
+ if (mpool == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
+ return;
+ }
+
+ pEapolFrame = (PEAPOL_PACKET)mpool;
+ NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER);
+
+
+ /* Construct EAPoL message - Group Msg 2*/
+ ConstructEapolMsg(pEntry,
+ group_cipher,
+ EAPOL_GROUP_MSG_2,
+ default_key,
+ NULL, /* Nonce not used*/
+ NULL, /* TxRSC not used*/
+ NULL, /* GTK not used*/
+ NULL, /* RSN IE not used*/
+ 0,
+ pEapolFrame);
+
+ /* open 802.1x port control and privacy filter*/
+ pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
+ pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerGroupMsg1Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
+ GetAuthMode(pEntry->AuthMode),
+ GetEncryptType(pEntry->WepStatus),
+ GetEncryptType(group_cipher)));
+
+ /* init header and Fill Packet and send Msg 2 to authenticator */
+ MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
+
+
+ RTMPToWirelessSta(pAd, pEntry,
+ Header802_3, sizeof(Header802_3),
+ (PUCHAR)pEapolFrame,
+ CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, FALSE);
+
+ os_free_mem(NULL, mpool);
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerGroupMsg1Action: send group message 2\n"));
+}
+
+
+VOID EnqueueStartForPSKExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ MAC_TABLE_ENTRY *pEntry = (PMAC_TABLE_ENTRY) FunctionContext;
+
+ if ((pEntry) && IS_ENTRY_CLIENT(pEntry) && (pEntry->WpaState < AS_PTKSTART))
+ {
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd;
+
+ switch (pEntry->EnqueueEapolStartTimerRunning)
+ {
+ case EAPOL_START_PSK:
+ DBGPRINT(RT_DEBUG_TRACE, ("Enqueue EAPoL-Start-PSK for sta(%02x:%02x:%02x:%02x:%02x:%02x) \n", PRINT_MAC(pEntry->Addr)));
+
+ MlmeEnqueue(pAd, WPA_STATE_MACHINE, MT2_EAPOLStart, 6, &pEntry->Addr, 0);
+ break;
+#ifdef CONFIG_AP_SUPPORT
+#ifdef DOT1X_SUPPORT
+ case EAPOL_START_1X:
+ DBGPRINT(RT_DEBUG_TRACE, ("Enqueue EAPoL-Start-1X for sta(%02x:%02x:%02x:%02x:%02x:%02x) \n", PRINT_MAC(pEntry->Addr)));
+
+ DOT1X_EapTriggerAction(pAd, pEntry);
+ break;
+#endif /* DOT1X_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ default:
+ break;
+
+ }
+ }
+ pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
+
+}
+
+
+VOID MlmeDeAuthAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN USHORT Reason,
+ IN BOOLEAN bDataFrameFirst)
+{
+ PUCHAR pOutBuffer = NULL;
+ ULONG FrameLen = 0;
+ HEADER_802_11 DeAuthHdr;
+ NDIS_STATUS NStatus;
+
+ if (pEntry)
+ {
+ /* Send out a Deauthentication request frame*/
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ return;
+
+ /* send wireless event - for send disassication */
+ RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Send DEAUTH frame with ReasonCode(%d) to %02x:%02x:%02x:%02x:%02x:%02x \n",Reason, PRINT_MAC(pEntry->Addr)));
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].Bssid);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &DeAuthHdr,
+ 2, &Reason,
+ END_OF_ARGS);
+
+
+
+ if (bDataFrameFirst)
+ MiniportMMRequest(pAd, MGMT_USE_QUEUE_FLAG, pOutBuffer, FrameLen);
+ else
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ /* ApLogEvent(pAd, pEntry->Addr, EVENT_DISASSOCIATED);*/
+ MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
+ }
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ When receiving the last packet of 2-way groupkey handshake.
+ Return:
+ ==========================================================================
+*/
+VOID PeerGroupMsg2Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN VOID *Msg,
+ IN UINT MsgLen)
+{
+ UINT Len;
+ PUCHAR pData;
+ BOOLEAN Cancelled;
+ PEAPOL_PACKET pMsg2;
+ UCHAR group_cipher = Ndis802_11WEPDisabled;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n"));
+
+ if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry))
+ return;
+
+ if (MsgLen < (LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG))
+ return;
+
+ if (pEntry->WpaState != AS_PTKINITDONE)
+ return;
+
+
+ do
+ {
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ UCHAR apidx = 0;
+
+ if (pEntry->apidx >= pAd->ApCfg.BssidNum)
+ return;
+ else
+ apidx = pEntry->apidx;
+
+ group_cipher = pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ pData = (PUCHAR)Msg;
+ pMsg2 = (PEAPOL_PACKET) (pData + LENGTH_802_1_H);
+ Len = MsgLen - LENGTH_802_1_H;
+
+ /* Sanity Check peer group message 2 - Replay Counter, MIC*/
+ if (PeerWpaMessageSanity(pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE)
+ break;
+
+ /* 3. upgrade state*/
+
+ RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
+ pEntry->GTKState = REKEY_ESTABLISHED;
+
+ if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
+ {
+ /* send wireless event - for set key done WPA2*/
+ RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+ DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
+ pEntry->AuthMode, GetAuthMode(pEntry->AuthMode),
+ pEntry->WepStatus, GetEncryptType(pEntry->WepStatus),
+ group_cipher, GetEncryptType(group_cipher)));
+ }
+ else
+ {
+ /* send wireless event - for set key done WPA*/
+ RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA1_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+ DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA1, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
+ pEntry->AuthMode, GetAuthMode(pEntry->AuthMode),
+ pEntry->WepStatus, GetEncryptType(pEntry->WepStatus),
+ group_cipher, GetEncryptType(group_cipher)));
+ }
+ }while(FALSE);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Classify WPA EAP message type
+
+ Arguments:
+ EAPType Value of EAP message type
+ MsgType Internal Message definition for MLME state machine
+
+ Return Value:
+ TRUE Found appropriate message type
+ FALSE No appropriate message type
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ All these constants are defined in wpa_cmm.h
+ For supplicant, there is only EAPOL Key message avaliable
+
+ ========================================================================
+*/
+BOOLEAN WpaMsgTypeSubst(
+ IN UCHAR EAPType,
+ OUT INT *MsgType)
+{
+ switch (EAPType)
+ {
+ case EAPPacket:
+ *MsgType = MT2_EAPPacket;
+ break;
+ case EAPOLStart:
+ *MsgType = MT2_EAPOLStart;
+ break;
+ case EAPOLLogoff:
+ *MsgType = MT2_EAPOLLogoff;
+ break;
+ case EAPOLKey:
+ *MsgType = MT2_EAPOLKey;
+ break;
+ case EAPOLASFAlert:
+ *MsgType = MT2_EAPOLASFAlert;
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * inc_iv_byte - Increment arbitrary length byte array
+ * @counter: Pointer to byte array
+ * @len: Length of the counter in bytes
+ *
+ * This function increments the least byte of the counter by one and continues
+ * rolling over to more significant bytes if the byte was incremented from
+ * 0xff to 0x00.
+ */
+void inc_iv_byte(UCHAR *iv, UINT len, UINT cnt)
+{
+ int pos = 0;
+ int carry = 0;
+ UCHAR pre_iv;
+
+ while (pos < len)
+ {
+ pre_iv = iv[pos];
+
+ if (carry == 1)
+ iv[pos] ++;
+ else
+ iv[pos] += cnt;
+
+ if (iv[pos] > pre_iv)
+ break;
+
+ carry = 1;
+ pos++;
+ }
+
+ if (pos >= len)
+ DBGPRINT(RT_DEBUG_WARN, ("!!! inc_iv_byte overflow !!!\n"));
+}
+
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ The pseudo-random function(PRF) that hashes various inputs to
+ derive a pseudo-random value. To add liveness to the pseudo-random
+ value, a nonce should be one of the inputs.
+
+ It is used to generate PTK, GTK or some specific random value.
+
+ Arguments:
+ UCHAR *key, - the key material for HMAC_SHA1 use
+ INT key_len - the length of key
+ UCHAR *prefix - a prefix label
+ INT prefix_len - the length of the label
+ UCHAR *data - a specific data with variable length
+ INT data_len - the length of a specific data
+ INT len - the output lenght
+
+ Return Value:
+ UCHAR *output - the calculated result
+
+ Note:
+ 802.11i-2004 Annex H.3
+
+ ========================================================================
+*/
+VOID PRF(
+ IN UCHAR *key,
+ IN INT key_len,
+ IN UCHAR *prefix,
+ IN INT prefix_len,
+ IN UCHAR *data,
+ IN INT data_len,
+ OUT UCHAR *output,
+ IN INT len)
+{
+ INT i;
+ UCHAR *input;
+ INT currentindex = 0;
+ INT total_len;
+
+ /* Allocate memory for input*/
+ os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
+
+ if (input == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
+ return;
+ }
+
+ /* Generate concatenation input*/
+ NdisMoveMemory(input, prefix, prefix_len);
+
+ /* Concatenate a single octet containing 0*/
+ input[prefix_len] = 0;
+
+ /* Concatenate specific data*/
+ NdisMoveMemory(&input[prefix_len + 1], data, data_len);
+ total_len = prefix_len + 1 + data_len;
+
+ /* Concatenate a single octet containing 0*/
+ /* This octet shall be update later*/
+ input[total_len] = 0;
+ total_len++;
+
+ /* Iterate to calculate the result by hmac-sha-1*/
+ /* Then concatenate to last result*/
+ for (i = 0; i < (len + 19) / 20; i++)
+ {
+ RT_HMAC_SHA1(key, key_len, input, total_len, &output[currentindex], SHA1_DIGEST_SIZE);
+ currentindex += 20;
+
+ /* update the last octet */
+ input[total_len - 1]++;
+ }
+ os_free_mem(NULL, input);
+}
+
+/*
+* F(P, S, c, i) = U1 xor U2 xor ... Uc
+* U1 = PRF(P, S || Int(i))
+* U2 = PRF(P, U1)
+* Uc = PRF(P, Uc-1)
+*/
+
+static void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output)
+{
+ unsigned char digest[36], digest1[SHA1_DIGEST_SIZE];
+ int i, j, len;
+
+ len = strlen(password);
+
+ /* U1 = PRF(P, S || int(i)) */
+ memcpy(digest, ssid, ssidlength);
+ digest[ssidlength] = (unsigned char)((count>>24) & 0xff);
+ digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff);
+ digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff);
+ digest[ssidlength+3] = (unsigned char)(count & 0xff);
+ RT_HMAC_SHA1((unsigned char*) password, len, digest, ssidlength+4, digest1, SHA1_DIGEST_SIZE); /* for WPA update*/
+
+ /* output = U1 */
+ memcpy(output, digest1, SHA1_DIGEST_SIZE);
+ for (i = 1; i < iterations; i++)
+ {
+ /* Un = PRF(P, Un-1) */
+ RT_HMAC_SHA1((unsigned char*) password, len, digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE); /* for WPA update*/
+ memcpy(digest1, digest, SHA1_DIGEST_SIZE);
+
+ /* output = output xor Un */
+ for (j = 0; j < SHA1_DIGEST_SIZE; j++)
+ {
+ output[j] ^= digest[j];
+ }
+ }
+}
+
+/*
+* password - ascii string up to 63 characters in length
+* ssid - octet string up to 32 octets
+* ssidlength - length of ssid in octets
+* output must be 40 octets in length and outputs 256 bits of key
+*/
+int RtmpPasswordHash(PSTRING password, PUCHAR ssid, INT ssidlength, PUCHAR output)
+{
+ if ((strlen(password) > 63) || (ssidlength > 32))
+ return 0;
+
+ F(password, ssid, ssidlength, 4096, 1, output);
+ F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]);
+ return 1;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ The key derivation function(KDF) is defined in IEEE 802.11r/D9.0, 8.5.1.5.2
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+ Output ¡ö KDF-Length (K, label, Context) where
+ Input: K, a 256-bit key derivation key
+ label, a string identifying the purpose of the keys derived using this KDF
+ Context, a bit string that provides context to identify the derived key
+ Length, the length of the derived key in bits
+ Output: a Length-bit derived key
+
+ result ¡ö ""
+ iterations ¡ö (Length+255)/256
+ do i = 1 to iterations
+ result ¡ö result || HMAC-SHA256(K, i || label || Context || Length)
+ od
+ return first Length bits of result, and securely delete all unused bits
+
+ In this algorithm, i and Length are encoded as 16-bit unsigned integers.
+
+ ========================================================================
+*/
+VOID KDF(
+ IN PUINT8 key,
+ IN INT key_len,
+ IN PUINT8 label,
+ IN INT label_len,
+ IN PUINT8 data,
+ IN INT data_len,
+ OUT PUINT8 output,
+ IN USHORT len)
+{
+ USHORT i;
+ UCHAR *input;
+ INT currentindex = 0;
+ INT total_len;
+ UINT len_in_bits = (len << 3);
+
+ os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
+
+ if (input == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!KDF: no memory!!!\n"));
+ return;
+ }
+
+ NdisZeroMemory(input, 1024);
+
+ /* Initial concatenated value (i || label || Context || Length)*/
+ /* concatenate 16-bit unsigned integer, its initial value is 1. */
+ input[0] = 1;
+ input[1] = 0;
+ total_len = 2;
+
+ /* concatenate a prefix string*/
+ NdisMoveMemory(&input[total_len], label, label_len);
+ total_len += label_len;
+
+ /* concatenate the context*/
+ NdisMoveMemory(&input[total_len], data, data_len);
+ total_len += data_len;
+
+ /* concatenate the length in bits (16-bit unsigned integer)*/
+ input[total_len] = (len_in_bits & 0xFF);
+ input[total_len + 1] = (len_in_bits & 0xFF00) >> 8;
+ total_len += 2;
+
+ for (i = 1; i <= ((len_in_bits + 255) / 256); i++)
+ {
+ /* HMAC-SHA256 derives output */
+ RT_HMAC_SHA256((UCHAR *)key, key_len, input, total_len, (UCHAR *)&output[currentindex], 32);
+
+ currentindex += 32; /* next concatenation location*/
+ input[0]++; /* increment octet count*/
+
+ }
+ os_free_mem(NULL, input);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPDerivePMKID(
+ IN PUINT8 pAaddr,
+ IN PUINT8 pSpaddr,
+ IN PUINT8 pKey,
+ IN PUINT8 pAkm_oui,
+ OUT PUINT8 pPMKID)
+{
+ UCHAR digest[80], text_buf[20];
+ UINT8 text_len;
+
+ /* Concatenate the text for PMKID calculation*/
+ NdisMoveMemory(&text_buf[0], "PMK Name", 8);
+ NdisMoveMemory(&text_buf[8], pAaddr, MAC_ADDR_LEN);
+ NdisMoveMemory(&text_buf[14], pSpaddr, MAC_ADDR_LEN);
+ text_len = 20;
+
+ {
+ RT_HMAC_SHA1(pKey, PMK_LEN, text_buf, text_len, digest, SHA1_DIGEST_SIZE);
+ }
+
+ /* Truncate the first 128-bit of output result */
+ NdisMoveMemory(pPMKID, digest, LEN_PMKID);
+
+}
+
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
+ It shall be called by 4-way handshake processing.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ PMK - pointer to PMK
+ ANonce - pointer to ANonce
+ AA - pointer to Authenticator Address
+ SNonce - pointer to SNonce
+ SA - pointer to Supplicant Address
+ len - indicate the length of PTK (octet)
+
+ Return Value:
+ Output pointer to the PTK
+
+ Note:
+ Refer to IEEE 802.11i-2004 8.5.1.2
+
+ ========================================================================
+*/
+VOID WpaDerivePTK(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR *PMK,
+ IN UCHAR *ANonce,
+ IN UCHAR *AA,
+ IN UCHAR *SNonce,
+ IN UCHAR *SA,
+ OUT UCHAR *output,
+ IN UINT len)
+{
+ UCHAR concatenation[76];
+ UINT CurrPos = 0;
+ UCHAR temp[32];
+ UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
+ 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
+
+ /* initiate the concatenation input*/
+ NdisZeroMemory(temp, sizeof(temp));
+ NdisZeroMemory(concatenation, 76);
+
+ /* Get smaller address*/
+ if (RTMPCompareMemory(SA, AA, 6) == 1)
+ NdisMoveMemory(concatenation, AA, 6);
+ else
+ NdisMoveMemory(concatenation, SA, 6);
+ CurrPos += 6;
+
+ /* Get larger address*/
+ if (RTMPCompareMemory(SA, AA, 6) == 1)
+ NdisMoveMemory(&concatenation[CurrPos], SA, 6);
+ else
+ NdisMoveMemory(&concatenation[CurrPos], AA, 6);
+
+ /* store the larger mac address for backward compatible of */
+ /* ralink proprietary STA-key issue */
+ NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
+ CurrPos += 6;
+
+ /* Get smaller Nonce*/
+ if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
+ NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue*/
+ else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
+ NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
+ else
+ NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
+ CurrPos += 32;
+
+ /* Get larger Nonce*/
+ if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
+ NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue*/
+ else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
+ NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
+ else
+ NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
+ CurrPos += 32;
+
+ hex_dump("PMK", PMK, LEN_PMK);
+ hex_dump("concatenation=", concatenation, 76);
+
+ /* Use PRF to generate PTK*/
+ PRF(PMK, LEN_PMK, Prefix, 22, concatenation, 76, output, len);
+
+}
+
+VOID WpaDeriveGTK(
+ IN UCHAR *GMK,
+ IN UCHAR *GNonce,
+ IN UCHAR *AA,
+ OUT UCHAR *output,
+ IN UINT len)
+{
+ UCHAR concatenation[76];
+ UINT CurrPos=0;
+ UCHAR Prefix[19];
+ UCHAR temp[80];
+
+ NdisMoveMemory(&concatenation[CurrPos], AA, 6);
+ CurrPos += 6;
+
+ NdisMoveMemory(&concatenation[CurrPos], GNonce , 32);
+ CurrPos += 32;
+
+ Prefix[0] = 'G';
+ Prefix[1] = 'r';
+ Prefix[2] = 'o';
+ Prefix[3] = 'u';
+ Prefix[4] = 'p';
+ Prefix[5] = ' ';
+ Prefix[6] = 'k';
+ Prefix[7] = 'e';
+ Prefix[8] = 'y';
+ Prefix[9] = ' ';
+ Prefix[10] = 'e';
+ Prefix[11] = 'x';
+ Prefix[12] = 'p';
+ Prefix[13] = 'a';
+ Prefix[14] = 'n';
+ Prefix[15] = 's';
+ Prefix[16] = 'i';
+ Prefix[17] = 'o';
+ Prefix[18] = 'n';
+
+ PRF(GMK, PMK_LEN, Prefix, 19, concatenation, 38 , temp, len);
+ NdisMoveMemory(output, temp, len);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Generate random number by software.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ macAddr - pointer to local MAC address
+
+ Return Value:
+
+ Note:
+ 802.1ii-2004 Annex H.5
+
+ ========================================================================
+*/
+VOID GenRandom(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR *macAddr,
+ OUT UCHAR *random)
+{
+ INT i, curr;
+ UCHAR local[80], KeyCounter[32];
+ UCHAR result[80];
+ ULONG CurrentTime;
+ UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
+
+ /* Zero the related information*/
+ NdisZeroMemory(result, 80);
+ NdisZeroMemory(local, 80);
+ NdisZeroMemory(KeyCounter, 32);
+
+ for (i = 0; i < 32; i++)
+ {
+ /* copy the local MAC address*/
+ COPY_MAC_ADDR(local, macAddr);
+ curr = MAC_ADDR_LEN;
+
+ /* concatenate the current time*/
+ NdisGetSystemUpTime(&CurrentTime);
+ NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
+ curr += sizeof(CurrentTime);
+
+ /* concatenate the last result*/
+ NdisMoveMemory(&local[curr], result, 32);
+ curr += 32;
+
+ /* concatenate a variable */
+ NdisMoveMemory(&local[curr], &i, 2);
+ curr += 2;
+
+ /* calculate the result*/
+ PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
+ }
+
+ NdisMoveMemory(random, result, 32);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build cipher suite in RSN-IE.
+ It only shall be called by RTMPMakeRSNIE.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ ElementID - indicate the WPA1 or WPA2
+ WepStatus - indicate the encryption type
+ bMixCipher - a boolean to indicate the pairwise cipher and group
+ cipher are the same or not
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+static VOID RTMPMakeRsnIeCipher(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR ElementID,
+ IN UINT WepStatus,
+ IN UCHAR apidx,
+ IN BOOLEAN bMixCipher,
+ IN UCHAR FlexibleCipher,
+ OUT PUCHAR pRsnIe,
+ OUT UCHAR *rsn_len)
+{
+ UCHAR PairwiseCnt;
+
+ *rsn_len = 0;
+
+ /* decide WPA2 or WPA1 */
+ if (ElementID == Wpa2Ie)
+ {
+ RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe;
+
+ /* Assign the verson as 1*/
+ pRsnie_cipher->version = 1;
+
+ switch (WepStatus)
+ {
+ /* TKIP mode*/
+ case Ndis802_11Encryption2Enabled:
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
+ pRsnie_cipher->ucount = 1;
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
+ *rsn_len = sizeof(RSNIE2);
+ break;
+
+ /* AES mode*/
+ case Ndis802_11Encryption3Enabled:
+ if (bMixCipher)
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
+ else
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4);
+ pRsnie_cipher->ucount = 1;
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
+ *rsn_len = sizeof(RSNIE2);
+ break;
+
+ /* TKIP-AES mix mode*/
+ case Ndis802_11Encryption4Enabled:
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
+
+ PairwiseCnt = 1;
+ /* Insert WPA2 TKIP as the first pairwise cipher */
+ if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher))
+ {
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
+ /* Insert WPA2 AES as the secondary pairwise cipher*/
+ if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher))
+ {
+ NdisMoveMemory(pRsnIe + sizeof(RSNIE2), OUI_WPA2_CCMP, 4);
+ PairwiseCnt = 2;
+ }
+ }
+ else
+ {
+ /* Insert WPA2 AES as the first pairwise cipher */
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
+ }
+
+ pRsnie_cipher->ucount = PairwiseCnt;
+ *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1));
+ break;
+ }
+
+
+ /* swap for big-endian platform*/
+ pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
+ pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
+ }
+ else
+ {
+ RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe;
+
+ /* Assign OUI and version*/
+ NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
+ pRsnie_cipher->version = 1;
+
+ switch (WepStatus)
+ {
+ /* TKIP mode*/
+ case Ndis802_11Encryption2Enabled:
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
+ pRsnie_cipher->ucount = 1;
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
+ *rsn_len = sizeof(RSNIE);
+ break;
+
+ /* AES mode*/
+ case Ndis802_11Encryption3Enabled:
+ if (bMixCipher)
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
+ else
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4);
+ pRsnie_cipher->ucount = 1;
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
+ *rsn_len = sizeof(RSNIE);
+ break;
+
+ /* TKIP-AES mix mode*/
+ case Ndis802_11Encryption4Enabled:
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
+
+ PairwiseCnt = 1;
+ /* Insert WPA TKIP as the first pairwise cipher */
+ if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
+ {
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
+ /* Insert WPA AES as the secondary pairwise cipher*/
+ if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher))
+ {
+ NdisMoveMemory(pRsnIe + sizeof(RSNIE), OUI_WPA_CCMP, 4);
+ PairwiseCnt = 2;
+ }
+ }
+ else
+ {
+ /* Insert WPA AES as the first pairwise cipher */
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
+ }
+
+ pRsnie_cipher->ucount = PairwiseCnt;
+ *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
+ break;
+ }
+
+
+ /* swap for big-endian platform*/
+ pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
+ pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build AKM suite in RSN-IE.
+ It only shall be called by RTMPMakeRSNIE.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ ElementID - indicate the WPA1 or WPA2
+ AuthMode - indicate the authentication mode
+ apidx - indicate the interface index
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+static VOID RTMPMakeRsnIeAKM(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR ElementID,
+ IN UINT AuthMode,
+ IN UCHAR apidx,
+ OUT PUCHAR pRsnIe,
+ OUT UCHAR *rsn_len)
+{
+ RSNIE_AUTH *pRsnie_auth;
+ UCHAR AkmCnt = 1; /* default as 1*/
+
+ pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
+
+ /* decide WPA2 or WPA1 */
+ if (ElementID == Wpa2Ie)
+ {
+
+ switch (AuthMode)
+ {
+ case Ndis802_11AuthModeWPA2:
+ case Ndis802_11AuthModeWPA1WPA2:
+ NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
+
+ break;
+
+ case Ndis802_11AuthModeWPA2PSK:
+ case Ndis802_11AuthModeWPA1PSKWPA2PSK:
+ NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
+
+ break;
+ default:
+ AkmCnt = 0;
+ break;
+
+ }
+ }
+ else
+ {
+ switch (AuthMode)
+ {
+ case Ndis802_11AuthModeWPA:
+ case Ndis802_11AuthModeWPA1WPA2:
+ NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
+ break;
+
+ case Ndis802_11AuthModeWPAPSK:
+ case Ndis802_11AuthModeWPA1PSKWPA2PSK:
+ NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
+ break;
+
+ case Ndis802_11AuthModeWPANone:
+ NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
+ break;
+ default:
+ AkmCnt = 0;
+ break;
+ }
+ }
+
+ pRsnie_auth->acount = AkmCnt;
+ pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
+
+ /* update current RSNIE length*/
+ (*rsn_len) += (sizeof(RSNIE_AUTH) + (4 * (AkmCnt - 1)));
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build capability in RSN-IE.
+ It only shall be called by RTMPMakeRSNIE.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ ElementID - indicate the WPA1 or WPA2
+ apidx - indicate the interface index
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+static VOID RTMPMakeRsnIeCap(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR ElementID,
+ IN UCHAR apidx,
+ OUT PUCHAR pRsnIe,
+ OUT UCHAR *rsn_len)
+{
+ RSN_CAPABILITIES *pRSN_Cap;
+
+ /* it could be ignored in WPA1 mode*/
+ if (ElementID == WpaIe)
+ return;
+
+ pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if (apidx < pAd->ApCfg.BssidNum)
+ {
+ PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx];
+
+#ifdef DOT1X_SUPPORT
+ pRSN_Cap->field.PreAuth = (pMbss->PreAuth == TRUE) ? 1 : 0;
+#endif /* DOT1X_SUPPORT */
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
+
+ (*rsn_len) += sizeof(RSN_CAPABILITIES); /* update current RSNIE length*/
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build PMKID in RSN-IE.
+ It only shall be called by RTMPMakeRSNIE.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ ElementID - indicate the WPA1 or WPA2
+ apidx - indicate the interface index
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build RSN IE context. It is not included element-ID and length.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ AuthMode - indicate the authentication mode
+ WepStatus - indicate the encryption type
+ apidx - indicate the interface index
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPMakeRSNIE(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT AuthMode,
+ IN UINT WepStatus,
+ IN UCHAR apidx)
+{
+ PUCHAR pRsnIe = NULL; /* primary RSNIE*/
+ UCHAR *rsnielen_cur_p = 0; /* the length of the primary RSNIE */
+#ifdef CONFIG_AP_SUPPORT
+ PUCHAR pRsnIe_ex = NULL; /* secondary RSNIE, it's ONLY used in WPA-mix mode */
+ BOOLEAN bMixRsnIe = FALSE; /* indicate WPA-mix mode is on or off*/
+ UCHAR s_offset;
+#endif /* CONFIG_AP_SUPPORT */
+ UCHAR *rsnielen_ex_cur_p = 0; /* the length of the secondary RSNIE */
+ UCHAR PrimaryRsnie;
+ BOOLEAN bMixCipher = FALSE; /* indicate the pairwise and group cipher are different*/
+ UCHAR p_offset;
+ WPA_MIX_PAIR_CIPHER FlexibleCipher = MIX_CIPHER_NOTUSE; /* it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode*/
+
+ rsnielen_cur_p = NULL;
+ rsnielen_ex_cur_p = NULL;
+
+ do
+ {
+
+#ifdef APCLI_SUPPORT
+ if (apidx >= MIN_NET_DEVICE_FOR_APCLI)
+ {
+ UINT apcliIfidx = 0;
+
+ /* Only support WPAPSK or WPA2PSK for AP-Client mode */
+#ifdef APCLI_WPA_SUPPLICANT_SUPPORT
+ if (pAd->ApCfg.ApCliTab[apcliIfidx].WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+ {
+ if (AuthMode < Ndis802_11AuthModeWPA)
+ return;
+ }
+ else
+#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */
+ {
+
+ if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
+ (AuthMode != Ndis802_11AuthModeWPA2PSK))
+ return;
+
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(ApCli)\n"));
+
+ apcliIfidx = apidx - MIN_NET_DEVICE_FOR_APCLI;
+
+ /* Initiate some related information */
+ if (apcliIfidx < MAX_APCLI_NUM)
+ {
+ pAd->ApCfg.ApCliTab[apcliIfidx].RSNIE_Len = 0;
+ NdisZeroMemory(pAd->ApCfg.ApCliTab[apcliIfidx].RSN_IE, MAX_LEN_OF_RSNIE);
+ rsnielen_cur_p = &pAd->ApCfg.ApCliTab[apcliIfidx].RSNIE_Len;
+ pRsnIe = pAd->ApCfg.ApCliTab[apcliIfidx].RSN_IE;
+
+ bMixCipher = pAd->ApCfg.ApCliTab[apcliIfidx].bMixCipher;
+ break;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTMPMakeRSNIE: invalid apcliIfidx(%d)\n", apcliIfidx));
+ return;
+ }
+ }
+#endif /* APCLI_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* Sanity check for apidx */
+ MBSS_MR_APIDX_SANITY_CHECK(pAd, apidx);
+#ifdef HOSTAPD_SUPPORT
+ if(pAd->ApCfg.MBSSID[apidx].Hostapd)
+ return;
+#endif /* HOSTAPD_SUPPORT */
+ if ((AuthMode != Ndis802_11AuthModeWPA) &&
+ (AuthMode != Ndis802_11AuthModeWPAPSK) &&
+ (AuthMode != Ndis802_11AuthModeWPA2) &&
+ (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
+ (AuthMode != Ndis802_11AuthModeWPA1WPA2) &&
+ (AuthMode != Ndis802_11AuthModeWPA1PSKWPA2PSK)
+#ifdef WAPI_SUPPORT
+ && (AuthMode != Ndis802_11AuthModeWAICERT)
+ && (AuthMode != Ndis802_11AuthModeWAIPSK)
+#endif /* WAPI_SUPPORT */
+ )
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(AP-ra%d)\n", apidx));
+
+ /* decide the group key encryption type */
+ if (WepStatus == Ndis802_11Encryption4Enabled)
+ {
+ pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus = Ndis802_11Encryption2Enabled;
+ FlexibleCipher = pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher;
+ }
+ else
+ pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus = WepStatus;
+
+ /* Initiate some related information */
+ pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0] = 0;
+ pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1] = 0;
+ NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].RSN_IE[0], MAX_LEN_OF_RSNIE);
+ NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].RSN_IE[1], MAX_LEN_OF_RSNIE);
+
+ /* Pointer to the first RSNIE context */
+ rsnielen_cur_p = &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0];
+ pRsnIe = pAd->ApCfg.MBSSID[apidx].RSN_IE[0];
+
+ /* Pointer to the secondary RSNIE context */
+ rsnielen_ex_cur_p = &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1];
+ pRsnIe_ex = pAd->ApCfg.MBSSID[apidx].RSN_IE[1];
+
+ /* Decide whether the authentication mode is WPA1-WPA2 mixed mode */
+ if ((AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
+ (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
+ {
+ bMixRsnIe = TRUE;
+ }
+ break;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ } while(FALSE);
+
+ /* indicate primary RSNIE as WPA or WPA2*/
+ if ((AuthMode == Ndis802_11AuthModeWPA) ||
+ (AuthMode == Ndis802_11AuthModeWPAPSK) ||
+ (AuthMode == Ndis802_11AuthModeWPANone) ||
+ (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
+ (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
+ PrimaryRsnie = WpaIe;
+#ifdef WAPI_SUPPORT
+ else if ((AuthMode == Ndis802_11AuthModeWAICERT) ||
+ (AuthMode == Ndis802_11AuthModeWAIPSK))
+ PrimaryRsnie = WapiIe;
+#endif /* WAPI_SUPPORT */
+ else
+ PrimaryRsnie = Wpa2Ie;
+
+#ifdef WAPI_SUPPORT
+ if (PrimaryRsnie == WapiIe)
+ {
+ RTMPInsertWapiIe(AuthMode, WepStatus, pRsnIe, &p_offset);
+ }
+ else
+#endif /* WAPI_SUPPORT */
+ {
+ /* Build the primary RSNIE*/
+ /* 1. insert cipher suite*/
+ RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, apidx, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
+
+ /* 2. insert AKM*/
+ RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
+
+ /* 3. insert capability*/
+ RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
+
+ }
+
+ /* 4. update the RSNIE length*/
+ if (rsnielen_cur_p == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: rsnielen_cur_p == NULL!\n", __FUNCTION__));
+ return;
+ }
+
+ *rsnielen_cur_p = p_offset;
+
+ hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
+
+#ifdef CONFIG_AP_SUPPORT
+ if ((pAd->OpMode == OPMODE_AP)
+ )
+ {
+ /* if necessary, build the secondary RSNIE*/
+ if (bMixRsnIe)
+ {
+ /* 1. insert cipher suite*/
+ RTMPMakeRsnIeCipher(pAd, Wpa2Ie, WepStatus, apidx, bMixCipher, FlexibleCipher, pRsnIe_ex, &s_offset);
+
+ /* 2. insert AKM*/
+ RTMPMakeRsnIeAKM(pAd, Wpa2Ie, AuthMode, apidx, pRsnIe_ex, &s_offset);
+
+ /* 3. insert capability*/
+ RTMPMakeRsnIeCap(pAd, Wpa2Ie, apidx, pRsnIe_ex, &s_offset);
+
+
+ /* Update the RSNIE length*/
+ *rsnielen_ex_cur_p = s_offset;
+
+ hex_dump("The secondary RSNIE", pRsnIe_ex, (*rsnielen_ex_cur_p));
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ Check whether the received frame is EAP frame.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ pEntry - pointer to active entry
+ pData - the received frame
+ DataByteCount - the received frame's length
+ FromWhichBSSID - indicate the interface index
+
+ Return:
+ TRUE - This frame is EAP frame
+ FALSE - otherwise
+ ==========================================================================
+*/
+BOOLEAN RTMPCheckWPAframe(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PUCHAR pData,
+ IN ULONG DataByteCount,
+ IN UCHAR FromWhichBSSID)
+{
+ ULONG Body_len;
+ BOOLEAN Cancelled;
+
+ do
+ {
+ } while (FALSE);
+
+ if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
+ return FALSE;
+
+
+ /* Skip LLC header */
+ if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
+ /* Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL*/
+ NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6))
+ {
+ pData += 6;
+ }
+ /* Skip 2-bytes EAPoL type */
+ if (NdisEqualMemory(EAPOL, pData, 2))
+/* if (*(UINT16 *)EAPOL == *(UINT16 *)pData)*/
+ {
+ pData += 2;
+ }
+ else
+ return FALSE;
+
+ switch (*(pData+1))
+ {
+ case EAPPacket:
+ Body_len = (*(pData+2)<<8) | (*(pData+3));
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef IDS_SUPPORT
+ if((*(pData+4)) == EAP_CODE_REQUEST)
+ pAd->ApCfg.RcvdEapReqCount ++;
+#endif /* IDS_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
+ break;
+ case EAPOLStart:
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
+ if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
+ RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
+ pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
+ }
+ break;
+ case EAPOLLogoff:
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
+ break;
+ case EAPOLKey:
+ Body_len = (*(pData+2)<<8) | (*(pData+3));
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
+ break;
+ case EAPOLASFAlert:
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
+ break;
+ default:
+ return FALSE;
+
+ }
+ return TRUE;
+}
+
+
+#ifdef HDR_TRANS_SUPPORT
+BOOLEAN RTMPCheckWPAframe_Hdr_Trns(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PUCHAR pData,
+ IN ULONG DataByteCount,
+ IN UCHAR FromWhichBSSID)
+{
+ ULONG Body_len;
+ BOOLEAN Cancelled;
+
+ do
+ {
+ } while (FALSE);
+
+ if(DataByteCount < (LENGTH_802_3 + LENGTH_EAPOL_H))
+ return FALSE;
+
+
+ /* Skip LLC header */
+
+ pData += LENGTH_802_3;
+
+ /* Skip 2-bytes EAPoL type */
+ if (NdisEqualMemory(EAPOL, pData, 2))
+/* if (*(UINT16 *)EAPOL == *(UINT16 *)pData)*/
+ {
+ pData += 2;
+ }
+ else
+ return FALSE;
+
+ switch (*(pData+1))
+ {
+ case EAPPacket:
+ Body_len = (*(pData+2)<<8) | (*(pData+3));
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef IDS_SUPPORT
+ if((*(pData+4)) == EAP_CODE_REQUEST)
+ pAd->ApCfg.RcvdEapReqCount ++;
+#endif /* IDS_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
+ break;
+ case EAPOLStart:
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
+ if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
+ RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
+ pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
+ }
+ break;
+ case EAPOLLogoff:
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
+ break;
+ case EAPOLKey:
+ Body_len = (*(pData+2)<<8) | (*(pData+3));
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
+ break;
+ case EAPOLASFAlert:
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
+ break;
+ default:
+ return FALSE;
+
+ }
+ return TRUE;
+}
+#endif /* HDR_TRANS_SUPPORT */
+
+
+/*
+ ==========================================================================
+ Description:
+ Report the EAP message type
+
+ Arguments:
+ msg - EAPOL_PAIR_MSG_1
+ EAPOL_PAIR_MSG_2
+ EAPOL_PAIR_MSG_3
+ EAPOL_PAIR_MSG_4
+ EAPOL_GROUP_MSG_1
+ EAPOL_GROUP_MSG_2
+
+ Return:
+ message type string
+
+ ==========================================================================
+*/
+PSTRING GetEapolMsgType(CHAR msg)
+{
+ if(msg == EAPOL_PAIR_MSG_1)
+ return "Pairwise Message 1";
+ else if(msg == EAPOL_PAIR_MSG_2)
+ return "Pairwise Message 2";
+ else if(msg == EAPOL_PAIR_MSG_3)
+ return "Pairwise Message 3";
+ else if(msg == EAPOL_PAIR_MSG_4)
+ return "Pairwise Message 4";
+ else if(msg == EAPOL_GROUP_MSG_1)
+ return "Group Message 1";
+ else if(msg == EAPOL_GROUP_MSG_2)
+ return "Group Message 2";
+ else
+ return "Invalid Message";
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Check Sanity RSN IE of EAPoL message
+
+ Arguments:
+
+ Return Value:
+
+
+ ========================================================================
+*/
+BOOLEAN RTMPCheckRSNIE(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN UCHAR DataLen,
+ IN MAC_TABLE_ENTRY *pEntry,
+ OUT UCHAR *Offset)
+{
+ PUCHAR pVIE;
+ UCHAR len;
+ PEID_STRUCT pEid;
+ BOOLEAN result = FALSE;
+
+ pVIE = pData;
+ len = DataLen;
+ *Offset = 0;
+
+ while (len > sizeof(RSNIE2))
+ {
+ pEid = (PEID_STRUCT) pVIE;
+ /* WPA RSN IE*/
+ if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
+ {
+ if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) &&
+ (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
+ (pEntry->RSNIE_Len == (pEid->Len + 2)))
+ {
+ result = TRUE;
+ }
+
+ *Offset += (pEid->Len + 2);
+ }
+ /* WPA2 RSN IE, doesn't need to check RSNIE Capabilities field */
+ else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
+ {
+ if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) &&
+ (pEid->Eid == pEntry->RSN_IE[0]) &&
+ ((pEid->Len + 2) >= pEntry->RSNIE_Len) &&
+ (NdisEqualMemory(pEid->Octet, &pEntry->RSN_IE[2], pEntry->RSNIE_Len - 4)))
+ {
+
+ result = TRUE;
+ }
+
+ *Offset += (pEid->Len + 2);
+ }
+ else
+ {
+ break;
+ }
+
+ pVIE += (pEid->Len + 2);
+ len -= (pEid->Len + 2);
+ }
+
+
+ return result;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK.
+ GTK is encaptulated in KDE format at p.83 802.11i D10
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+ 802.11i D10
+
+ ========================================================================
+*/
+BOOLEAN RTMPParseEapolKeyData(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pKeyData,
+ IN UCHAR KeyDataLen,
+ IN UCHAR GroupKeyIndex,
+ IN UCHAR MsgType,
+ IN BOOLEAN bWPA2,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ PUCHAR pMyKeyData = pKeyData;
+ UCHAR KeyDataLength = KeyDataLen;
+ UCHAR GTK[MAX_LEN_GTK];
+ UCHAR GTKLEN = 0;
+ UCHAR DefaultIdx = 0;
+ UCHAR skip_offset = 0;
+
+
+ NdisZeroMemory(GTK, MAX_LEN_GTK);
+
+ /* Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it*/
+ if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3)
+ {
+ {
+ if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3)
+ {
+ /*WpaShowAllsuite(pMyKeyData, skip_offset);*/
+
+ /* skip RSN IE*/
+ pMyKeyData += skip_offset;
+ KeyDataLength -= skip_offset;
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
+ }
+ else
+ return TRUE;
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
+ /*hex_dump("remain data", pMyKeyData, KeyDataLength);*/
+
+
+ /* Parse KDE format in pairwise_msg_3_WPA2 && group_msg_1_WPA2*/
+ if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1))
+ {
+ PEID_STRUCT pEid;
+
+ pEid = (PEID_STRUCT) pMyKeyData;
+ skip_offset = 0;
+ while ((skip_offset + 2 + pEid->Len) <= KeyDataLength)
+ {
+ switch(pEid->Eid)
+ {
+ case WPA_KDE_TYPE:
+ {
+ PKDE_HDR pKDE;
+
+ pKDE = (PKDE_HDR)pEid;
+ if (NdisEqualMemory(pKDE->OUI, OUI_WPA2, 3))
+ {
+ if (pKDE->DataType == KDE_GTK)
+ {
+ PGTK_KDE pKdeGtk;
+
+ pKdeGtk = (PGTK_KDE) &pKDE->octet[0];
+ DefaultIdx = pKdeGtk->Kid;
+
+ /* Get GTK length - refer to IEEE 802.11i-2004 p.82 */
+ GTKLEN = pKDE->Len -6;
+ if (GTKLEN < LEN_WEP64)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
+ return FALSE;
+ }
+ NdisMoveMemory(GTK, pKdeGtk->GTK, GTKLEN);
+ DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN));
+ }
+ }
+ }
+ break;
+ }
+ skip_offset = skip_offset + 2 + pEid->Len;
+ pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+ }
+
+ /* skip KDE Info*/
+ pMyKeyData += skip_offset;
+ KeyDataLength -= skip_offset;
+ }
+ else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1)
+ {
+ DefaultIdx = GroupKeyIndex;
+ GTKLEN = KeyDataLength;
+ NdisMoveMemory(GTK, pMyKeyData, KeyDataLength);
+ DBGPRINT(RT_DEBUG_TRACE, ("GTK without KDE, DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN));
+ }
+
+ /* Sanity check - shared key index must be 0 ~ 3*/
+ if (DefaultIdx > 3)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
+ return FALSE;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ if (IS_ENTRY_APCLI(pEntry))
+ {
+ /* Set Group key material, TxMic and RxMic for AP-Client*/
+ if (!APCliInstallSharedKey(pAd, GTK, GTKLEN, DefaultIdx, pEntry))
+ {
+ return FALSE;
+ }
+ }
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ return TRUE;
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Construct KDE common format
+ Its format is below,
+
+ +--------------------+
+ | Type (0xdd) | 1 octet
+ +--------------------+
+ | Length | 1 octet
+ +--------------------+
+ | OUI | 3 octets
+ +--------------------+
+ | Data Type | 1 octet
+ +--------------------+
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+ It's defined in IEEE 802.11-2007 Figure 8-25.
+
+ ========================================================================
+*/
+VOID WPA_ConstructKdeHdr(
+ IN UINT8 data_type,
+ IN UINT8 data_len,
+ OUT PUCHAR pBuf)
+{
+ PKDE_HDR pHdr;
+
+ pHdr = (PKDE_HDR)pBuf;
+
+ NdisZeroMemory(pHdr, sizeof(KDE_HDR));
+
+ pHdr->Type = WPA_KDE_TYPE;
+
+ /* The Length field specifies the number of octets in the OUI, Data
+ Type, and Data fields. */
+ pHdr->Len = 4 + data_len;
+
+ NdisMoveMemory(pHdr->OUI, OUI_WPA2, 3);
+ pHdr->DataType = data_type;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Construct EAPoL message for WPA handshaking
+ Its format is below,
+
+ +--------------------+
+ | Protocol Version | 1 octet
+ +--------------------+
+ | Protocol Type | 1 octet
+ +--------------------+
+ | Body Length | 2 octets
+ +--------------------+
+ | Descriptor Type | 1 octet
+ +--------------------+
+ | Key Information | 2 octets
+ +--------------------+
+ | Key Length | 1 octet
+ +--------------------+
+ | Key Repaly Counter | 8 octets
+ +--------------------+
+ | Key Nonce | 32 octets
+ +--------------------+
+ | Key IV | 16 octets
+ +--------------------+
+ | Key RSC | 8 octets
+ +--------------------+
+ | Key ID or Reserved | 8 octets
+ +--------------------+
+ | Key MIC | 16 octets
+ +--------------------+
+ | Key Data Length | 2 octets
+ +--------------------+
+ | Key Data | n octets
+ +--------------------+
+
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID ConstructEapolMsg(
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN UCHAR GroupKeyWepStatus,
+ IN UCHAR MsgType,
+ IN UCHAR DefaultKeyIdx,
+ IN UCHAR *KeyNonce,
+ IN UCHAR *TxRSC,
+ IN UCHAR *GTK,
+ IN UCHAR *RSNIE,
+ IN UCHAR RSNIE_Len,
+ OUT PEAPOL_PACKET pMsg)
+{
+ BOOLEAN bWPA2 = FALSE;
+ UCHAR KeyDescVer;
+
+ /* Choose WPA2 or not*/
+ if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
+ (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
+ bWPA2 = TRUE;
+
+ /* Init Packet and Fill header */
+ pMsg->ProVer = EAPOL_VER;
+ pMsg->ProType = EAPOLKey;
+
+ /* Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field*/
+ SET_UINT16_TO_ARRARY(pMsg->Body_Len, MIN_LEN_OF_EAPOL_KEY_MSG);
+
+ /* Fill in EAPoL descriptor*/
+ if (bWPA2)
+ pMsg->KeyDesc.Type = WPA2_KEY_DESC;
+ else
+ pMsg->KeyDesc.Type = WPA1_KEY_DESC;
+
+ /* Key Descriptor Version (bits 0-2) specifies the key descriptor version type*/
+ {
+ /* Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 */
+ /* When either the pairwise or the group cipher is AES, the KEY_DESC_AES shall be used.*/
+ KeyDescVer = (((pEntry->WepStatus == Ndis802_11Encryption3Enabled) ||
+ (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (KEY_DESC_AES) : (KEY_DESC_TKIP));
+ }
+
+ pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer;
+
+ /* Specify Key Type as Group(0) or Pairwise(1)*/
+ if (MsgType >= EAPOL_GROUP_MSG_1)
+ pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
+ else
+ pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
+
+ /* Specify Key Index, only group_msg1_WPA1*/
+ if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
+ pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
+
+ if (MsgType == EAPOL_PAIR_MSG_3)
+ pMsg->KeyDesc.KeyInfo.Install = 1;
+
+ if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))
+ pMsg->KeyDesc.KeyInfo.KeyAck = 1;
+
+ if (MsgType != EAPOL_PAIR_MSG_1)
+ pMsg->KeyDesc.KeyInfo.KeyMic = 1;
+
+ if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) ||
+ (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)))
+ {
+ pMsg->KeyDesc.KeyInfo.Secure = 1;
+ }
+
+ /* This subfield shall be set, and the Key Data field shall be encrypted, if
+ any key material (e.g., GTK or SMK) is included in the frame. */
+ if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) ||
+ (MsgType == EAPOL_GROUP_MSG_1)))
+ {
+ pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
+ }
+
+ /* key Information element has done. */
+ *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo));
+
+ /* Fill in Key Length*/
+ if (bWPA2)
+ {
+ /* In WPA2 mode, the field indicates the length of pairwise key cipher, */
+ /* so only pairwise_msg_1 and pairwise_msg_3 need to fill. */
+ if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3))
+ pMsg->KeyDesc.KeyLength[1] = ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_TK : LEN_AES_TK);
+ }
+ else if (!bWPA2)
+ {
+ if (MsgType >= EAPOL_GROUP_MSG_1)
+ {
+ /* the length of group key cipher*/
+ pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_GTK : LEN_AES_GTK);
+ }
+ else
+ {
+ /* the length of pairwise key cipher*/
+ pMsg->KeyDesc.KeyLength[1] = ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_TK : LEN_AES_TK);
+ }
+ }
+
+ /* Fill in replay counter */
+ NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY);
+
+ /* Fill Key Nonce field */
+ /* ANonce : pairwise_msg1 & pairwise_msg3*/
+ /* SNonce : pairwise_msg2*/
+ /* GNonce : group_msg1_wpa1 */
+ if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
+ NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE);
+
+ /* Fill key IV - WPA2 as 0, WPA1 as random*/
+ if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
+ {
+ /* Suggest IV be random number plus some number,*/
+ NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV);
+ pMsg->KeyDesc.KeyIv[15] += 2;
+ }
+
+ /* Fill Key RSC field */
+ /* It contains the RSC for the GTK being installed.*/
+ if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
+ {
+ NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
+ }
+
+ /* Clear Key MIC field for MIC calculation later */
+ NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+
+ ConstructEapolKeyData(pEntry,
+ GroupKeyWepStatus,
+ KeyDescVer,
+ MsgType,
+ DefaultKeyIdx,
+ GTK,
+ RSNIE,
+ RSNIE_Len,
+ pMsg);
+
+ /* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.*/
+ if (MsgType != EAPOL_PAIR_MSG_1)
+ {
+ CalculateMIC(KeyDescVer, pEntry->PTK, pMsg);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
+ DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", CONV_ARRARY_TO_UINT16(pMsg->Body_Len)));
+ DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyLength)));
+
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Construct the Key Data field of EAPoL message
+
+ Arguments:
+ pAd Pointer to our adapter
+ Elem Message body
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID ConstructEapolKeyData(
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN UCHAR GroupKeyWepStatus,
+ IN UCHAR keyDescVer,
+ IN UCHAR MsgType,
+ IN UCHAR DefaultKeyIdx,
+ IN UCHAR *GTK,
+ IN UCHAR *RSNIE,
+ IN UCHAR RSNIE_LEN,
+ OUT PEAPOL_PACKET pMsg)
+{
+ UCHAR *mpool, *Key_Data, *eGTK;
+ ULONG data_offset;
+ BOOLEAN bWPA2Capable = FALSE;
+ BOOLEAN GTK_Included = FALSE;
+
+ /* Choose WPA2 or not*/
+ if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
+ (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
+ bWPA2Capable = TRUE;
+
+ if (MsgType == EAPOL_PAIR_MSG_1 ||
+ MsgType == EAPOL_PAIR_MSG_4 ||
+ MsgType == EAPOL_GROUP_MSG_2)
+ return;
+
+ /* allocate memory pool*/
+ os_alloc_mem(NULL, (PUCHAR *)&mpool, 1500);
+
+ if (mpool == NULL)
+ return;
+
+ /* eGTK Len = 512 */
+ eGTK = (UCHAR *) ROUND_UP(mpool, 4);
+ /* Key_Data Len = 512 */
+ Key_Data = (UCHAR *) ROUND_UP(eGTK + 512, 4);
+
+ NdisZeroMemory(Key_Data, 512);
+ SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0);
+ data_offset = 0;
+
+ /* Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 */
+ if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3)))
+ {
+ PUINT8 pmkid_ptr = NULL;
+ UINT8 pmkid_len = 0;
+
+
+ RTMPInsertRSNIE(&Key_Data[data_offset],
+ &data_offset,
+ RSNIE,
+ RSNIE_LEN,
+ pmkid_ptr,
+ pmkid_len);
+ }
+
+
+ /* Encapsulate GTK */
+ /* Only for pairwise_msg3_WPA2 and group_msg1*/
+ if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1))
+ {
+ UINT8 gtk_len;
+
+ /* Decide the GTK length */
+ if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
+ gtk_len = LEN_AES_GTK;
+ else
+ gtk_len = LEN_TKIP_GTK;
+
+ /* Insert GTK KDE format in WAP2 mode */
+ if (bWPA2Capable)
+ {
+ /* Construct the common KDE format */
+ WPA_ConstructKdeHdr(KDE_GTK, 2 + gtk_len, &Key_Data[data_offset]);
+ data_offset += sizeof(KDE_HDR);
+
+ /* GTK KDE format - 802.11i-2004 Figure-43x*/
+ Key_Data[data_offset] = (DefaultKeyIdx & 0x03);
+ Key_Data[data_offset + 1] = 0x00; /* Reserved Byte*/
+ data_offset += 2;
+ }
+
+ /* Fill in GTK */
+ NdisMoveMemory(&Key_Data[data_offset], GTK, gtk_len);
+ data_offset += gtk_len;
+
+
+ GTK_Included = TRUE;
+ }
+
+
+
+ /* If the Encrypted Key Data subfield (of the Key Information field)
+ is set, the entire Key Data field shall be encrypted. */
+ /* This whole key-data field shall be encrypted if a GTK is included.*/
+ /* Encrypt the data material in key data field with KEK*/
+ if (GTK_Included)
+ {
+ /*hex_dump("GTK_Included", Key_Data, data_offset);*/
+
+ if (
+ (keyDescVer == KEY_DESC_AES))
+ {
+ UCHAR remainder = 0;
+ UCHAR pad_len = 0;
+ UINT wrap_len =0;
+
+ /* Key Descriptor Version 2 or 3: AES key wrap, defined in IETF RFC 3394, */
+ /* shall be used to encrypt the Key Data field using the KEK field from */
+ /* the derived PTK.*/
+
+ /* If the Key Data field uses the NIST AES key wrap, then the Key Data field */
+ /* shall be padded before encrypting if the key data length is less than 16 */
+ /* octets or if it is not a multiple of 8. The padding consists of appending*/
+ /* a single octet 0xdd followed by zero or more 0x00 octets. */
+ if ((remainder = data_offset & 0x07) != 0)
+ {
+ INT i;
+
+ pad_len = (8 - remainder);
+ Key_Data[data_offset] = 0xDD;
+ for (i = 1; i < pad_len; i++)
+ Key_Data[data_offset + i] = 0;
+
+ data_offset += pad_len;
+ }
+
+ AES_Key_Wrap(Key_Data, (UINT) data_offset,
+ &pEntry->PTK[LEN_PTK_KCK], LEN_PTK_KEK,
+ eGTK, &wrap_len);
+ data_offset = wrap_len;
+
+ }
+ else
+ {
+ TKIP_GTK_KEY_WRAP(&pEntry->PTK[LEN_PTK_KCK],
+ pMsg->KeyDesc.KeyIv,
+ Key_Data,
+ data_offset,
+ eGTK);
+ }
+
+ NdisMoveMemory(pMsg->KeyDesc.KeyData, eGTK, data_offset);
+ }
+ else
+ {
+ NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
+ }
+
+ /* Update key data length field and total body length*/
+ SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset);
+ INC_UINT16_TO_ARRARY(pMsg->Body_Len, data_offset);
+
+ os_free_mem(NULL, mpool);
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calcaulate MIC. It is used during 4-ways handsharking.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ PeerWepStatus - indicate the encryption type
+
+ Return Value:
+
+ Note:
+ The EAPOL-Key MIC is a MIC of the EAPOL-Key frames,
+ from and including the EAPOL protocol version field
+ to and including the Key Data field, calculated with
+ the Key MIC field set to 0.
+
+ ========================================================================
+*/
+VOID CalculateMIC(
+ IN UCHAR KeyDescVer,
+ IN UCHAR *PTK,
+ OUT PEAPOL_PACKET pMsg)
+{
+ UCHAR *OutBuffer;
+ ULONG FrameLen = 0;
+ UCHAR mic[LEN_KEY_DESC_MIC];
+ UCHAR digest[80];
+
+ /* allocate memory for MIC calculation*/
+ os_alloc_mem(NULL, (PUCHAR *)&OutBuffer, 512);
+
+ if (OutBuffer == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n"));
+ return;
+ }
+
+ /* make a frame for calculating MIC.*/
+ MakeOutgoingFrame(OutBuffer, &FrameLen,
+ CONV_ARRARY_TO_UINT16(pMsg->Body_Len) + 4, pMsg,
+ END_OF_ARGS);
+
+ NdisZeroMemory(mic, sizeof(mic));
+
+ /* Calculate MIC*/
+ if (KeyDescVer == KEY_DESC_AES)
+ {
+ RT_HMAC_SHA1(PTK, LEN_PTK_KCK, OutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE);
+ NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
+ }
+ else if (KeyDescVer == KEY_DESC_TKIP)
+ {
+ RT_HMAC_MD5(PTK, LEN_PTK_KCK, OutBuffer, FrameLen, mic, MD5_DIGEST_SIZE);
+ }
+ else if (KeyDescVer == KEY_DESC_EXT)
+ {
+ UINT mlen = AES_KEY128_LENGTH;
+ AES_CMAC(OutBuffer, FrameLen, PTK, LEN_PTK_KCK, mic, &mlen);
+ }
+
+ /* store the calculated MIC*/
+ NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
+
+ os_free_mem(NULL, OutBuffer);
+}
+
+UCHAR RTMPExtractKeyIdxFromIVHdr(
+ IN PUCHAR pIV,
+ IN UINT8 CipherAlg)
+{
+ UCHAR keyIdx = 0xFF;
+
+ /* extract the key index from IV header */
+ switch (CipherAlg)
+ {
+ case Ndis802_11Encryption1Enabled:
+ case Ndis802_11Encryption2Enabled:
+ case Ndis802_11Encryption3Enabled:
+ keyIdx = (*(pIV + 3) & 0xc0) >> 6;
+ break;
+
+#ifdef WAPI_SUPPORT
+ case Ndis802_11EncryptionSMS4Enabled:
+ keyIdx = *(pIV) & 0xFF;
+ break;
+#endif /* WAPI_SUPPORT */
+ }
+
+ return keyIdx;
+
+}
+
+PCIPHER_KEY RTMPSwCipherKeySelection(
+ IN RTMP_ADAPTER *pAd,
+ IN PUCHAR pIV,
+ IN RX_BLK *pRxBlk,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ PCIPHER_KEY pKey = NULL;
+ UCHAR keyIdx = 0;
+ UINT8 CipherAlg = Ndis802_11EncryptionDisabled;
+
+ if ((pEntry == NULL) ||
+ (RX_BLK_TEST_FLAG(pRxBlk, fRX_APCLI)) ||
+ (RX_BLK_TEST_FLAG(pRxBlk, fRX_WDS)) ||
+ (RX_BLK_TEST_FLAG(pRxBlk, fRX_MESH)))
+ return NULL;
+
+ if (pRxBlk->pRxInfo->U2M)
+ {
+ CipherAlg = pEntry->WepStatus;
+ }
+ else
+ {
+ }
+
+
+ if ((keyIdx = RTMPExtractKeyIdxFromIVHdr(pIV, CipherAlg)) > 3)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : Invalid key index(%d) !!!\n",
+ __FUNCTION__, keyIdx));
+ return NULL;
+ }
+
+ if (CipherAlg == Ndis802_11Encryption1Enabled)
+ {
+ pKey = &pAd->SharedKey[pEntry->apidx][keyIdx];
+ }
+ else if ((CipherAlg == Ndis802_11Encryption2Enabled) ||
+ (CipherAlg == Ndis802_11Encryption3Enabled))
+ {
+ if (pRxBlk->pRxInfo->U2M)
+ pKey = &pEntry->PairwiseKey;
+ else {
+ pKey = &pAd->SharedKey[pEntry->apidx][keyIdx];
+ }
+ }
+#ifdef WAPI_SUPPORT
+ else if (CipherAlg == Ndis802_11EncryptionSMS4Enabled)
+ {
+ if (pRxBlk->pRxInfo->U2M)
+ pKey = &pEntry->PairwiseKey;
+ else
+ pKey = &pAd->SharedKey[pEntry->apidx][keyIdx];
+ }
+#endif /* WAPI_SUPPORT */
+
+ return pKey;
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Some received frames can't decrypt by Asic, so decrypt them by software.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ PeerWepStatus - indicate the encryption type
+
+ Return Value:
+ NDIS_STATUS_SUCCESS - decryption successful
+ NDIS_STATUS_FAILURE - decryption failure
+
+ ========================================================================
+*/
+NDIS_STATUS RTMPSoftDecryptionAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pHdr,
+ IN UCHAR UserPriority,
+ IN PCIPHER_KEY pKey,
+ INOUT PUCHAR pData,
+ INOUT UINT16 *DataByteCnt)
+{
+ switch (pKey->CipherAlg)
+ {
+ case CIPHER_WEP64:
+ case CIPHER_WEP128:
+ /* handle WEP decryption */
+ if (RTMPSoftDecryptWEP(pAd, pKey, pData, &(*DataByteCnt)) == FALSE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR : SW decrypt WEP data fails.\n"));
+ /* give up this frame*/
+ return NDIS_STATUS_FAILURE;
+ }
+ break;
+
+ case CIPHER_TKIP:
+ /* handle TKIP decryption */
+ if (RTMPSoftDecryptTKIP(pAd, pHdr, UserPriority,
+ pKey, pData, &(*DataByteCnt)) == FALSE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR : SW decrypt TKIP data fails.\n"));
+ /* give up this frame*/
+ return NDIS_STATUS_FAILURE;
+ }
+ break;
+
+ case CIPHER_AES:
+ /* handle AES decryption */
+ if (RTMPSoftDecryptCCMP(pAd, pHdr, pKey, pData, &(*DataByteCnt)) == FALSE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR : SW decrypt AES data fails.\n"));
+ /* give up this frame*/
+ return NDIS_STATUS_FAILURE;
+ }
+ break;
+#ifdef WAPI_SUPPORT
+#ifdef SOFT_ENCRYPT
+ case CIPHER_SMS4:
+ {
+ INT ret;
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE);
+#endif
+ if ((ret = RTMPSoftDecryptSMS4(pHdr, FALSE, pKey, pData, &(*DataByteCnt))) != STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR : SW decrypt SMS4 data fails(%d).\n", ret));
+ /* give up this frame*/
+ return NDIS_STATUS_FAILURE;
+ }
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE);
+#endif
+ }
+ break;
+#endif /* SOFT_ENCRYPT */
+#endif /* WAPI_SUPPORT */
+ default:
+ /* give up this frame*/
+ return NDIS_STATUS_FAILURE;
+ break;
+ }
+
+ return NDIS_STATUS_SUCCESS;
+
+}
+
+VOID RTMPSoftConstructIVHdr(
+ IN UCHAR CipherAlg,
+ IN UCHAR key_id,
+ IN PUCHAR pTxIv,
+ OUT PUCHAR pHdrIv,
+ OUT UINT8 *hdr_iv_len)
+{
+ *hdr_iv_len = 0;
+
+#ifdef WAPI_SUPPORT
+ if (CipherAlg == CIPHER_SMS4)
+ {
+ /* Construct and insert WPI-SMS4 IV header to MPDU header */
+ RTMPConstructWPIIVHdr(key_id, pTxIv, pHdrIv);
+ *hdr_iv_len = LEN_WPI_IV_HDR;
+ }
+ else
+#endif /* WAPI_SUPPORT */
+ if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128))
+ {
+ /* Construct and insert 4-bytes WEP IV header to MPDU header */
+ RTMPConstructWEPIVHdr(key_id, pTxIv, pHdrIv);
+ *hdr_iv_len = LEN_WEP_IV_HDR;
+ }
+ else if (CipherAlg == CIPHER_TKIP)
+ ;
+ else if (CipherAlg == CIPHER_AES)
+ {
+ /* Construct and insert 8-bytes CCMP header to MPDU header */
+ RTMPConstructCCMPHdr(key_id, pTxIv, pHdrIv);
+ *hdr_iv_len = LEN_CCMP_HDR;
+ }
+
+}
+
+VOID RTMPSoftEncryptionAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR CipherAlg,
+ IN PUCHAR pHdr,
+ IN PUCHAR pSrcBufData,
+ IN UINT32 SrcBufLen,
+ IN UCHAR KeyIdx,
+ IN PCIPHER_KEY pKey,
+ OUT UINT8 *ext_len)
+{
+ *ext_len = 0;
+
+#ifdef WAPI_SUPPORT
+#ifdef SOFT_ENCRYPT
+ if (CipherAlg == CIPHER_SMS4)
+ {
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE);
+#endif
+ /* Encrypt the MPDU data by software*/
+ RTMPSoftEncryptSMS4(pHdr,
+ pSrcBufData,
+ SrcBufLen,
+ KeyIdx,
+ pKey->Key,
+ pKey->TxTsc);
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE);
+#endif
+ *ext_len = LEN_WPI_MIC;
+ }
+ else
+#endif /* SOFT_ENCRYPT */
+#endif /* WAPI_SUPPORT */
+ if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128))
+ {
+ /* Encrypt the MPDU data by software*/
+ RTMPSoftEncryptWEP(pAd,
+ pKey->TxTsc,
+ pKey,
+ pSrcBufData,
+ SrcBufLen);
+
+ *ext_len = LEN_ICV;
+ }
+ else if (CipherAlg == CIPHER_TKIP)
+ ;
+ else if (CipherAlg == CIPHER_AES)
+ {
+ /* Encrypt the MPDU data by software*/
+ RTMPSoftEncryptCCMP(pAd,
+ pHdr,
+ pKey->TxTsc,
+ pKey->Key,
+ pSrcBufData,
+ SrcBufLen);
+
+ *ext_len = LEN_CCMP_MIC;
+ }
+
+}
+
+PUINT8 WPA_ExtractSuiteFromRSNIE(
+ IN PUINT8 rsnie,
+ IN UINT rsnie_len,
+ IN UINT8 type,
+ OUT UINT8 *count)
+{
+ PEID_STRUCT pEid;
+ INT len;
+ PUINT8 pBuf;
+ INT offset = 0;
+
+ pEid = (PEID_STRUCT)rsnie;
+ len = rsnie_len - 2; /* exclude IE and length*/
+ pBuf = (PUINT8)&pEid->Octet[0];
+
+ /* set default value*/
+ *count = 0;
+
+ /* Check length*/
+ if ((len <= 0) || (pEid->Len != len))
+ {
+ DBGPRINT_ERR(("%s : The length is invalid\n", __FUNCTION__));
+ goto out;
+ }
+
+ /* Check WPA or WPA2*/
+ if (pEid->Eid == IE_WPA)
+ {
+ /* Check the length */
+ if (len < sizeof(RSNIE))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The length is too short for WPA\n", __FUNCTION__));
+ goto out;
+ }
+ else
+ {
+ PRSNIE pRsnie;
+ UINT16 u_cnt;
+
+ pRsnie = (PRSNIE)pBuf;
+ u_cnt = cpu2le16(pRsnie->ucount);
+ offset = sizeof(RSNIE) + (LEN_OUI_SUITE * (u_cnt - 1));
+
+ if (len < offset)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The expected lenght(%d) exceed the remaining length(%d) for WPA-RSN \n",
+ __FUNCTION__, offset, len));
+ goto out;
+ }
+ else
+ {
+ /* Get the group cipher*/
+ if (type == GROUP_SUITE)
+ {
+ *count = 1;
+ return pRsnie->mcast;
+ }
+ /* Get the pairwise cipher suite*/
+ else if (type == PAIRWISE_SUITE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of pairwise cipher is %d\n",
+ __FUNCTION__, u_cnt));
+ *count = u_cnt;
+ return pRsnie->ucast[0].oui;
+ }
+ }
+ }
+ }
+ else if (pEid->Eid == IE_RSN)
+ {
+ if (len < sizeof(RSNIE2))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The length is too short for WPA2\n", __FUNCTION__));
+ goto out;
+ }
+ else
+ {
+ PRSNIE2 pRsnie2;
+ UINT16 u_cnt;
+
+ pRsnie2 = (PRSNIE2)pBuf;
+ u_cnt = cpu2le16(pRsnie2->ucount);
+ offset = sizeof(RSNIE2) + (LEN_OUI_SUITE * (u_cnt - 1));
+
+ if (len < offset)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The expected lenght(%d) exceed the remaining length(%d) for WPA2-RSN \n",
+ __FUNCTION__, offset, len));
+ goto out;
+ }
+ else
+ {
+ /* Get the group cipher*/
+ if (type == GROUP_SUITE)
+ {
+ *count = 1;
+ return pRsnie2->mcast;
+ }
+ /* Get the pairwise cipher suite*/
+ else if (type == PAIRWISE_SUITE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of pairwise cipher is %d\n",
+ __FUNCTION__, u_cnt));
+ *count = u_cnt;
+ return pRsnie2->ucast[0].oui;
+ }
+ }
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : Unknown IE (%d)\n", __FUNCTION__, pEid->Eid));
+ goto out;
+ }
+
+ /* skip group cipher and pairwise cipher suite */
+ pBuf += offset;
+ len -= offset;
+
+ /* Ready to extract the AKM information and its count */
+ if (len < sizeof(RSNIE_AUTH))
+ {
+ DBGPRINT_ERR(("%s : The length of AKM of RSN is too short\n", __FUNCTION__));
+ goto out;
+ }
+ else
+ {
+ PRSNIE_AUTH pAkm;
+ UINT16 a_cnt;
+
+ /* pointer to AKM count */
+ pAkm = (PRSNIE_AUTH)pBuf;
+ a_cnt = cpu2le16(pAkm->acount);
+ offset = sizeof(RSNIE_AUTH) + (LEN_OUI_SUITE * (a_cnt - 1));
+
+ if (len < offset)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The expected lenght(%d) exceed the remaining length(%d) for AKM \n",
+ __FUNCTION__, offset, len));
+ goto out;
+ }
+ else
+ {
+ /* Get the AKM suite */
+ if (type == AKM_SUITE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n",
+ __FUNCTION__, a_cnt));
+ *count = a_cnt;
+ return pAkm->auth[0].oui;
+ }
+ }
+ }
+
+ /* For WPA1, the remaining shall be ignored. */
+ if (pEid->Eid == IE_WPA)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s : The remaining shall be ignored in WPA mode\n",
+ __FUNCTION__));
+ goto out;
+ }
+
+ /* skip the AKM capability */
+ pBuf += offset;
+ len -= offset;
+
+ /* Parse the RSN Capabilities */
+ if (len < sizeof(RSN_CAPABILITIES))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s : The peer RSNIE doesn't include RSN-Cap\n", __FUNCTION__));
+ goto out;
+ }
+ else
+ {
+ /* Report the content of the RSN capabilities */
+ if (type == RSN_CAP_INFO)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s : Extract RSN Capabilities\n", __FUNCTION__));
+ *count = 1;
+ return pBuf;
+ }
+
+ /* skip RSN capability (2-bytes) */
+ offset = sizeof(RSN_CAPABILITIES);
+ pBuf += offset;
+ len -= offset;
+ }
+
+ /* Extract PMKID-list field */
+ if (len < sizeof(UINT16))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s : The peer RSNIE doesn't include PMKID list Count\n", __FUNCTION__));
+ goto out;
+ }
+ else
+ {
+ UINT16 p_count;
+ PUINT8 pPmkidList = NULL;
+
+ NdisMoveMemory(&p_count, pBuf, sizeof(UINT16));
+ p_count = cpu2le16(p_count);
+
+ /* Get count of the PMKID list */
+ if (p_count > 0)
+ {
+ PRSNIE_PMKID pRsnPmkid;
+
+ /* the expected length of PMKID-List field */
+ offset = sizeof(RSNIE_PMKID) + (LEN_PMKID * (p_count - 1));
+
+ /* sanity check about the length of PMKID-List field */
+ if (len < offset)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The expected lenght(%d) exceed the remaining length(%d) in PMKID-field \n",
+ __FUNCTION__, offset, len));
+ goto out;
+ }
+
+ /* pointer to PMKID field */
+ pRsnPmkid = (PRSNIE_PMKID)pBuf;
+ pPmkidList = pRsnPmkid->pmkid[0].list;
+
+ }
+ else
+ {
+ /* The PMKID field shall be without PMKID-List */
+ offset = sizeof(UINT16);
+ pPmkidList = NULL;
+ }
+
+
+ /* Extract PMKID list and its count */
+ if (type == PMKID_LIST)
+ {
+ *count = p_count;
+ return pPmkidList;
+ }
+
+ /* skip the PMKID field */
+ pBuf += offset;
+ len -= offset;
+
+ }
+
+
+out:
+ *count = 0;
+ return NULL;
+
+}
+
+VOID WpaShowAllsuite(
+ IN PUINT8 rsnie,
+ IN UINT rsnie_len)
+{
+ PUINT8 pSuite = NULL;
+ UINT8 count;
+
+ hex_dump("RSNIE", rsnie, rsnie_len);
+
+ /* group cipher*/
+ if ((pSuite = WPA_ExtractSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, &count)) != NULL)
+ {
+ hex_dump("group cipher", pSuite, 4*count);
+ }
+
+ /* pairwise cipher*/
+ if ((pSuite = WPA_ExtractSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, &count)) != NULL)
+ {
+ hex_dump("pairwise cipher", pSuite, 4*count);
+ }
+
+ /* AKM*/
+ if ((pSuite = WPA_ExtractSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count)) != NULL)
+ {
+ hex_dump("AKM suite", pSuite, 4*count);
+ }
+
+ /* PMKID*/
+ if ((pSuite = WPA_ExtractSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count)) != NULL)
+ {
+ hex_dump("PMKID", pSuite, LEN_PMKID);
+ }
+
+}
+
+VOID RTMPInsertRSNIE(
+ IN PUCHAR pFrameBuf,
+ OUT PULONG pFrameLen,
+ IN PUINT8 rsnie_ptr,
+ IN UINT8 rsnie_len,
+ IN PUINT8 pmkid_ptr,
+ IN UINT8 pmkid_len)
+{
+ PUCHAR pTmpBuf;
+ ULONG TempLen = 0;
+ UINT8 extra_len = 0;
+ UINT16 pmk_count = 0;
+ UCHAR ie_num;
+ UINT8 total_len = 0;
+ UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC};
+
+ pTmpBuf = pFrameBuf;
+
+ /* PMKID-List Must larger than 0 and the multiple of 16. */
+ if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0))
+ {
+ extra_len = sizeof(UINT16) + pmkid_len;
+
+ pmk_count = (pmkid_len >> 4);
+ pmk_count = cpu2le16(pmk_count);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s : no PMKID-List included(%d).\n", __FUNCTION__, pmkid_len));
+ }
+
+ if (rsnie_len != 0)
+ {
+ ie_num = IE_WPA;
+ total_len = rsnie_len;
+
+ if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI)))
+ {
+ ie_num = IE_RSN;
+ total_len += extra_len;
+ }
+
+ /* construct RSNIE body */
+ MakeOutgoingFrame(pTmpBuf, &TempLen,
+ 1, &ie_num,
+ 1, &total_len,
+ rsnie_len, rsnie_ptr,
+ END_OF_ARGS);
+
+ pTmpBuf += TempLen;
+ *pFrameLen = *pFrameLen + TempLen;
+
+ if (ie_num == IE_RSN)
+ {
+ /* Insert PMKID-List field */
+ if (extra_len > 0)
+ {
+ MakeOutgoingFrame(pTmpBuf, &TempLen,
+ 2, &pmk_count,
+ pmkid_len, pmkid_ptr,
+ END_OF_ARGS);
+
+ pTmpBuf += TempLen;
+ *pFrameLen = *pFrameLen + TempLen;
+ }
+ }
+ }
+
+ return;
+}
+
+
+VOID WPAInstallPairwiseKey(
+ PRTMP_ADAPTER pAd,
+ UINT8 BssIdx,
+ PMAC_TABLE_ENTRY pEntry,
+ BOOLEAN bAE)
+{
+ NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY));
+
+ /* Assign the pairwise cipher algorithm */
+ if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
+ pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP;
+ else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled)
+ pEntry->PairwiseKey.CipherAlg = CIPHER_AES;
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (wcid-%d)\n",
+ __FUNCTION__, pEntry->Aid));
+ return;
+ }
+
+ /* Assign key material and its length */
+ pEntry->PairwiseKey.KeyLen = LEN_TK;
+ NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[OFFSET_OF_PTK_TK], LEN_TK);
+ if (pEntry->PairwiseKey.CipherAlg == CIPHER_TKIP)
+ {
+ if (bAE)
+ {
+ NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pEntry->PTK[OFFSET_OF_AP_TKIP_TX_MIC], LEN_TKIP_MIC);
+ NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pEntry->PTK[OFFSET_OF_AP_TKIP_RX_MIC], LEN_TKIP_MIC);
+ }
+ else
+ {
+ NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pEntry->PTK[OFFSET_OF_STA_TKIP_TX_MIC], LEN_TKIP_MIC);
+ NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pEntry->PTK[OFFSET_OF_STA_TKIP_RX_MIC], LEN_TKIP_MIC);
+ }
+ }
+
+#ifdef SOFT_ENCRYPT
+ if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("===> SW_ENC ON(wcid=%d) \n", pEntry->Aid));
+ NdisZeroMemory(pEntry->PairwiseKey.TxTsc, LEN_WPA_TSC);
+ NdisZeroMemory(pEntry->PairwiseKey.RxTsc, LEN_WPA_TSC);
+ }
+ else
+#endif /* SOFT_ENCRYPT */
+ {
+ /* Add Pair-wise key to Asic */
+ AsicAddPairwiseKeyEntry(
+ pAd,
+ (UCHAR)pEntry->Aid,
+ &pEntry->PairwiseKey);
+
+ RTMPSetWcidSecurityInfo(pAd,
+ BssIdx,
+ 0,
+ pEntry->PairwiseKey.CipherAlg,
+ (UCHAR)pEntry->Aid,
+ PAIRWISEKEYTABLE);
+ }
+
+}
+
+VOID WPAInstallSharedKey(
+ PRTMP_ADAPTER pAd,
+ UINT8 GroupCipher,
+ UINT8 BssIdx,
+ UINT8 KeyIdx,
+ UINT8 Wcid,
+ BOOLEAN bAE,
+ PUINT8 pGtk,
+ UINT8 GtkLen)
+{
+ PCIPHER_KEY pSharedKey;
+
+ if (BssIdx >= MAX_MBSSID_NUM(pAd))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The BSS-index(%d) is out of range for MBSSID link. \n",
+ __FUNCTION__, BssIdx));
+ return;
+ }
+
+ pSharedKey = &pAd->SharedKey[BssIdx][KeyIdx];
+ NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY));
+
+ /* Set the group cipher */
+ if (GroupCipher == Ndis802_11GroupWEP40Enabled)
+ pSharedKey->CipherAlg = CIPHER_WEP64;
+ else if (GroupCipher == Ndis802_11GroupWEP104Enabled)
+ pSharedKey->CipherAlg = CIPHER_WEP128;
+ else if (GroupCipher == Ndis802_11Encryption2Enabled)
+ pSharedKey->CipherAlg = CIPHER_TKIP;
+ else if (GroupCipher == Ndis802_11Encryption3Enabled)
+ pSharedKey->CipherAlg = CIPHER_AES;
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (IF/ra%d) \n",
+ __FUNCTION__, BssIdx));
+ return;
+ }
+
+ /* Set the key material and its length */
+ if (GroupCipher == Ndis802_11GroupWEP40Enabled ||
+ GroupCipher == Ndis802_11GroupWEP104Enabled)
+ {
+ /* Sanity check the length */
+ if ((GtkLen != LEN_WEP64) && (GtkLen != LEN_WEP128))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : (IF/ra%d) WEP key invlaid(%d) \n",
+ __FUNCTION__, BssIdx, GtkLen));
+ return;
+ }
+
+ pSharedKey->KeyLen = GtkLen;
+ NdisMoveMemory(pSharedKey->Key, pGtk, GtkLen);
+ }
+ else
+ {
+ /* Sanity check the length */
+ if (GtkLen < LEN_TK)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : (IF/ra%d) WPA key invlaid(%d) \n",
+ __FUNCTION__, BssIdx, GtkLen));
+ return;
+ }
+
+ pSharedKey->KeyLen = LEN_TK;
+ NdisMoveMemory(pSharedKey->Key, pGtk, LEN_TK);
+ if (pSharedKey->CipherAlg == CIPHER_TKIP)
+ {
+ if (bAE)
+ {
+ NdisMoveMemory(pSharedKey->TxMic, pGtk + 16, LEN_TKIP_MIC);
+ NdisMoveMemory(pSharedKey->RxMic, pGtk + 24, LEN_TKIP_MIC);
+ }
+ else
+ {
+ NdisMoveMemory(pSharedKey->TxMic, pGtk + 24, LEN_TKIP_MIC);
+ NdisMoveMemory(pSharedKey->RxMic, pGtk + 16, LEN_TKIP_MIC);
+ }
+ }
+ }
+
+ /* Update group key table(0x6C00) and group key mode(0x7000) */
+ AsicAddSharedKeyEntry(
+ pAd,
+ BssIdx,
+ KeyIdx,
+ pSharedKey);
+
+ /* When Wcid isn't zero, it means that this is a Authenticator Role.
+ Only Authenticator entity needs to set HW IE/EIV table (0x6000)
+ and WCID attribute table (0x6800) for group key. */
+ if (Wcid != 0)
+ {
+ RTMPSetWcidSecurityInfo(pAd,
+ BssIdx,
+ KeyIdx,
+ pSharedKey->CipherAlg,
+ Wcid,
+ SHAREDKEYTABLE);
+ }
+}
+
+VOID RTMPSetWcidSecurityInfo(
+ PRTMP_ADAPTER pAd,
+ UINT8 BssIdx,
+ UINT8 KeyIdx,
+ UINT8 CipherAlg,
+ UINT8 Wcid,
+ UINT8 KeyTabFlag)
+{
+ UINT32 IV = 0;
+ UINT8 IV_KEYID = 0;
+
+ /* Prepare initial IV value */
+ if (CipherAlg == CIPHER_WEP64 || CipherAlg == CIPHER_WEP128)
+ {
+ INT i;
+ UCHAR TxTsc[LEN_WEP_TSC];
+
+ /* Generate 3-bytes IV randomly for encryption using */
+ for(i = 0; i < LEN_WEP_TSC; i++)
+ TxTsc[i] = RandomByte(pAd);
+
+ /* Update HW IVEIV table */
+ IV_KEYID = (KeyIdx << 6);
+ IV = (IV_KEYID << 24) |
+ (TxTsc[2] << 16) |
+ (TxTsc[1] << 8) |
+ (TxTsc[0]);
+ }
+ else if (CipherAlg == CIPHER_TKIP || CipherAlg == CIPHER_AES)
+ {
+ /* Set IVEIV as 1 in Asic -
+ In IEEE 802.11-2007 8.3.3.4.3 described :
+ The PN shall be implemented as a 48-bit monotonically incrementing
+ non-negative integer, initialized to 1 when the corresponding
+ temporal key is initialized or refreshed. */
+ IV_KEYID = (KeyIdx << 6) | 0x20;
+ IV = (IV_KEYID << 24) | 1;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : Unsupport cipher Alg (%d) for Wcid-%d \n",
+ __FUNCTION__, CipherAlg, Wcid));
+ return;
+ }
+ /* Update WCID IV/EIV table */
+ AsicUpdateWCIDIVEIV(pAd, Wcid, IV, 0);
+
+ /* Update WCID attribute entry */
+ AsicUpdateWcidAttributeEntry(pAd,
+ BssIdx,
+ KeyIdx,
+ CipherAlg,
+ Wcid,
+ KeyTabFlag);
+
+}
+
diff --git a/cleopatre/devkit/mt7601udrv/common/crypt_aes.c b/cleopatre/devkit/mt7601udrv/common/crypt_aes.c
new file mode 100644
index 0000000000..e5050e493b
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/crypt_aes.c
@@ -0,0 +1,1605 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************/
+
+/****************************************************************************
+ Module Name:
+ AES
+
+ Abstract:
+ RFC 3394: Advanced Encryption Standard (AES) Key Wrap Algorithm
+ RFC 3601: Counter with CBC-MAC (CCM)
+ RFC 4493: The AES-CMAC Algorithm
+ FIPS PUBS 197: ADVANCED ENCRYPTION STANDARD (AES)
+ NIST 800-38A: Recommendation for Block Cipher Modes of Operation
+ NIST 800-38C: The CCM Mode for Authentication and Confidentiality
+
+ Revision History:
+ Who When What
+ -------- ---------- ------------------------------------------
+ Eddy 2009/05/19 Create AES-Key Wrap
+ Eddy 2009/04/20 Create AES-CMAC, AES-CCM
+ Eddy 2009/01/19 Create AES-128, AES-192, AES-256, AES-CBC
+***************************************************************************/
+
+#include "crypt_aes.h"
+
+
+/* The value given by [x^(i-1),{00},{00},{00}], with x^(i-1) being powers of x in the field GF(2^8). */
+static const UINT32 aes_rcon[] = {
+ 0x00000000, 0x01000000, 0x02000000, 0x04000000,
+ 0x08000000, 0x10000000, 0x20000000, 0x40000000,
+ 0x80000000, 0x1B000000, 0x36000000};
+
+static const UINT8 aes_sbox_enc[] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7 ,0xab, 0x76, /* 0 */
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4 ,0x72, 0xc0, /* 1 */
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8 ,0x31, 0x15, /* 2 */
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27 ,0xb2, 0x75, /* 3 */
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3 ,0x2f, 0x84, /* 4 */
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c ,0x58, 0xcf, /* 5 */
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c ,0x9f, 0xa8, /* 6 */
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff ,0xf3, 0xd2, /* 7 */
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d ,0x19, 0x73, /* 8 */
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e ,0x0b, 0xdb, /* 9 */
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95 ,0xe4, 0x79, /* a */
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a ,0xae, 0x08, /* b */
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd ,0x8b, 0x8a, /* c */
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1 ,0x1d, 0x9e, /* d */
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55 ,0x28, 0xdf, /* e */
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54 ,0xbb, 0x16, /* f */
+};
+
+static const UINT8 aes_sbox_dec[] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, /* 0 */
+ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, /* 1 */
+ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, /* 2 */
+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, /* 3 */
+ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, /* 4 */
+ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, /* 5 */
+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, /* 6 */
+ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, /* 7 */
+ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, /* 8 */
+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, /* 9 */
+ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, /* a */
+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, /* b */
+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, /* c */
+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, /* d */
+ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, /* e */
+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, /* f */
+};
+
+/* ArrayIndex*{02} */
+static const UINT8 aes_mul_2[] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, /* 0 */
+ 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, /* 1 */
+ 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, /* 2 */
+ 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, /* 3 */
+ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, /* 4 */
+ 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, /* 5 */
+ 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, /* 6 */
+ 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, /* 7 */
+ 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, /* 8 */
+ 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, /* 9 */
+ 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, /* a */
+ 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, /* b */
+ 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, /* c */
+ 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, /* d */
+ 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, /* e */
+ 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5, /* f */
+};
+
+/* ArrayIndex*{03} */
+static const UINT8 aes_mul_3[] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, /* 0 */
+ 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, /* 1 */
+ 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, /* 2 */
+ 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, /* 3 */
+ 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, /* 4 */
+ 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, /* 5 */
+ 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, /* 6 */
+ 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, /* 7 */
+ 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, /* 8 */
+ 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, /* 9 */
+ 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, /* a */
+ 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, /* b */
+ 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, /* c */
+ 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, /* d */
+ 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, /* e */
+ 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a, /* f */
+};
+
+/* ArrayIndex*{09} */
+static const UINT8 aes_mul_9[] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, /* 0 */
+ 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, /* 1 */
+ 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, /* 2 */
+ 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, /* 3 */
+ 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, /* 4 */
+ 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, /* 5 */
+ 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, /* 6 */
+ 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, /* 7 */
+ 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, /* 8 */
+ 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, /* 9 */
+ 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, /* a */
+ 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, /* b */
+ 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, /* c */
+ 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, /* d */
+ 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, /* e */
+ 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46, /* f */
+};
+
+/* ArrayIndex*{0b} */
+static const UINT8 aes_mul_b[] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, /* 0 */
+ 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, /* 1 */
+ 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, /* 2 */
+ 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, /* 3 */
+ 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, /* 4 */
+ 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, /* 5 */
+ 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, /* 6 */
+ 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, /* 7 */
+ 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, /* 8 */
+ 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, /* 9 */
+ 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, /* a */
+ 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, /* b */
+ 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, /* c */
+ 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, /* d */
+ 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, /* e */
+ 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3, /* f */
+};
+
+/* ArrayIndex*{0d} */
+static const UINT8 aes_mul_d[] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, /* 0 */
+ 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, /* 1 */
+ 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, /* 2 */
+ 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, /* 3 */
+ 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, /* 4 */
+ 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, /* 5 */
+ 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, /* 6 */
+ 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, /* 7 */
+ 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, /* 8 */
+ 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, /* 9 */
+ 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, /* a */
+ 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, /* b */
+ 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, /* c */
+ 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, /* d */
+ 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, /* e */
+ 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97, /* f */
+};
+
+/* ArrayIndex*{0e} */
+static const UINT8 aes_mul_e[] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, /* 0 */
+ 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, /* 1 */
+ 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, /* 2 */
+ 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, /* 3 */
+ 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, /* 4 */
+ 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, /* 5 */
+ 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, /* 6 */
+ 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, /* 7 */
+ 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, /* 8 */
+ 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, /* 9 */
+ 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, /* a */
+ 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, /* b */
+ 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, /* c */
+ 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, /* d */
+ 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, /* e */
+ 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d, /* f */
+};
+
+/* For AES_CMAC */
+#define AES_MAC_LENGTH 16 /* 128-bit string */
+static UINT8 Const_Zero[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static UINT8 Const_Rb[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87};
+
+/*
+========================================================================
+Routine Description:
+ AES key expansion (key schedule)
+
+Arguments:
+ Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits)
+ KeyLength The length of cipher key in bytes
+ paes_ctx Pointer to AES_CTX_STRUC
+
+Return Value:
+ paes_ctx Retrun the KeyWordExpansion of AES_CTX_STRUC
+
+Note:
+ Pseudo code for key expansion
+ ------------------------------------------
+ Nk = (key length/4);
+
+ while (i < Nk)
+ KeyWordExpansion[i] = word(key[4*i], key[4*i + 1], key[4*i + 2], key[4*i + 3]);
+ i++;
+ end while
+
+ while (i < ((key length/4 + 6 + 1)*4) )
+ temp = KeyWordExpansion[i - 1];
+ if (i % Nk ==0)
+ temp = SubWord(RotWord(temp)) ^ Rcon[i/Nk];
+ else if ((Nk > 6) && (i % 4 == 4))
+ temp = SubWord(temp);
+ end if
+
+ KeyWordExpansion[i] = KeyWordExpansion[i - Nk]^ temp;
+ i++;
+ end while
+========================================================================
+*/
+VOID RT_AES_KeyExpansion (
+ IN UINT8 Key[],
+ IN UINT KeyLength,
+ INOUT AES_CTX_STRUC *paes_ctx)
+{
+ UINT KeyIndex = 0;
+ UINT NumberOfWordOfKey, NumberOfWordOfKeyExpansion;
+ UINT8 TempWord[AES_KEY_ROWS], Temp;
+ UINT32 Temprcon;
+
+ NumberOfWordOfKey = KeyLength >> 2;
+ while (KeyIndex < NumberOfWordOfKey)
+ {
+ paes_ctx->KeyWordExpansion[0][KeyIndex] = Key[4*KeyIndex];
+ paes_ctx->KeyWordExpansion[1][KeyIndex] = Key[4*KeyIndex + 1];
+ paes_ctx->KeyWordExpansion[2][KeyIndex] = Key[4*KeyIndex + 2];
+ paes_ctx->KeyWordExpansion[3][KeyIndex] = Key[4*KeyIndex + 3];
+ KeyIndex++;
+ }
+
+ NumberOfWordOfKeyExpansion = ((UINT) AES_KEY_ROWS) * ((KeyLength >> 2) + 6 + 1);
+ while (KeyIndex < NumberOfWordOfKeyExpansion)
+ {
+ TempWord[0] = paes_ctx->KeyWordExpansion[0][KeyIndex - 1];
+ TempWord[1] = paes_ctx->KeyWordExpansion[1][KeyIndex - 1];
+ TempWord[2] = paes_ctx->KeyWordExpansion[2][KeyIndex - 1];
+ TempWord[3] = paes_ctx->KeyWordExpansion[3][KeyIndex - 1];
+ if ((KeyIndex % NumberOfWordOfKey) == 0) {
+ Temprcon = aes_rcon[KeyIndex/NumberOfWordOfKey];
+ Temp = aes_sbox_enc[TempWord[1]]^((Temprcon >> 24) & 0xff);
+ TempWord[1] = aes_sbox_enc[TempWord[2]]^((Temprcon >> 16) & 0xff);
+ TempWord[2] = aes_sbox_enc[TempWord[3]]^((Temprcon >> 8) & 0xff);
+ TempWord[3] = aes_sbox_enc[TempWord[0]]^((Temprcon ) & 0xff);
+ TempWord[0] = Temp;
+ } else if ((NumberOfWordOfKey > 6) && ((KeyIndex % NumberOfWordOfKey) == 4)) {
+ Temp = aes_sbox_enc[TempWord[0]];
+ TempWord[1] = aes_sbox_enc[TempWord[1]];
+ TempWord[2] = aes_sbox_enc[TempWord[2]];
+ TempWord[3] = aes_sbox_enc[TempWord[3]];
+ TempWord[0] = Temp;
+ }
+ paes_ctx->KeyWordExpansion[0][KeyIndex] = paes_ctx->KeyWordExpansion[0][KeyIndex - NumberOfWordOfKey]^TempWord[0];
+ paes_ctx->KeyWordExpansion[1][KeyIndex] = paes_ctx->KeyWordExpansion[1][KeyIndex - NumberOfWordOfKey]^TempWord[1];
+ paes_ctx->KeyWordExpansion[2][KeyIndex] = paes_ctx->KeyWordExpansion[2][KeyIndex - NumberOfWordOfKey]^TempWord[2];
+ paes_ctx->KeyWordExpansion[3][KeyIndex] = paes_ctx->KeyWordExpansion[3][KeyIndex - NumberOfWordOfKey]^TempWord[3];
+ KeyIndex++;
+ }
+}
+
+
+/*
+========================================================================
+Routine Description:
+ AES encryption
+
+Arguments:
+ PlainBlock The block of plain text, 16 bytes(128 bits) each block
+ PlainBlockSize The length of block of plain text in bytes
+ Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits)
+ KeyLength The length of cipher key in bytes
+ CipherBlockSize The length of allocated cipher block in bytes
+
+Return Value:
+ CipherBlock Return cipher text
+ CipherBlockSize Return the length of real used cipher block in bytes
+
+Note:
+ Reference to FIPS-PUB 197
+ 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits)
+ 2. Transfer the plain block to state block
+ 3. Main encryption rounds
+ 4. Transfer the state block to cipher block
+ ------------------------------------------
+ NumberOfRound = (key length / 4) + 6;
+ state block = plain block;
+
+ AddRoundKey(state block, key);
+ for round = 1 to NumberOfRound
+ SubBytes(state block)
+ ShiftRows(state block)
+ MixColumns(state block)
+ AddRoundKey(state block, key);
+ end for
+
+ SubBytes(state block)
+ ShiftRows(state block)
+ AddRoundKey(state block, key);
+
+ cipher block = state block;
+========================================================================
+*/
+VOID RT_AES_Encrypt (
+ IN UINT8 PlainBlock[],
+ IN UINT PlainBlockSize,
+ IN UINT8 Key[],
+ IN UINT KeyLength,
+ OUT UINT8 CipherBlock[],
+ INOUT UINT *CipherBlockSize)
+{
+/* AES_CTX_STRUC aes_ctx;
+*/
+ AES_CTX_STRUC *paes_ctx = NULL;
+ UINT RowIndex, ColumnIndex;
+ UINT RoundIndex, NumberOfRound = 0;
+ UINT8 Temp, Row0, Row1, Row2, Row3;
+
+ /*
+ * 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits)
+ */
+ if (PlainBlockSize != AES_BLOCK_SIZES) {
+ DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Encrypt: plain block size is %d bytes, it must be %d bytes(128 bits).\n",
+ PlainBlockSize, AES_BLOCK_SIZES));
+ return;
+ }
+ if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Encrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n",
+ KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH));
+ return;
+ }
+ if (*CipherBlockSize < AES_BLOCK_SIZES) {
+ DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Encrypt: cipher block size is %d bytes, it must be %d bytes(128 bits).\n",
+ *CipherBlockSize, AES_BLOCK_SIZES));
+ return;
+ }
+
+ /* allocate memory */
+ os_alloc_mem(NULL, (UCHAR **)&paes_ctx, sizeof(AES_CTX_STRUC));
+ if (paes_ctx == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ return;
+ }
+
+ /*
+ * 2. Transfer the plain block to state block
+ */
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ paes_ctx->State[RowIndex][ColumnIndex] = PlainBlock[RowIndex + 4*ColumnIndex];
+
+ /*
+ * 3. Main encryption rounds
+ */
+ RT_AES_KeyExpansion(Key, KeyLength, paes_ctx);
+ NumberOfRound = (KeyLength >> 2) + 6;
+
+ /* AES_AddRoundKey */
+ RoundIndex = 0;
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex];
+
+ for (RoundIndex = 1; RoundIndex < NumberOfRound;RoundIndex++)
+ {
+ /* AES_SubBytes */
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ paes_ctx->State[RowIndex][ColumnIndex] = aes_sbox_enc[paes_ctx->State[RowIndex][ColumnIndex]];
+
+ /* AES_ShiftRows */
+ Temp = paes_ctx->State[1][0];
+ paes_ctx->State[1][0] = paes_ctx->State[1][1];
+ paes_ctx->State[1][1] = paes_ctx->State[1][2];
+ paes_ctx->State[1][2] = paes_ctx->State[1][3];
+ paes_ctx->State[1][3] = Temp;
+ Temp = paes_ctx->State[2][0];
+ paes_ctx->State[2][0] = paes_ctx->State[2][2];
+ paes_ctx->State[2][2] = Temp;
+ Temp = paes_ctx->State[2][1];
+ paes_ctx->State[2][1] = paes_ctx->State[2][3];
+ paes_ctx->State[2][3] = Temp;
+ Temp = paes_ctx->State[3][3];
+ paes_ctx->State[3][3] = paes_ctx->State[3][2];
+ paes_ctx->State[3][2] = paes_ctx->State[3][1];
+ paes_ctx->State[3][1] = paes_ctx->State[3][0];
+ paes_ctx->State[3][0] = Temp;
+
+ /* AES_MixColumns */
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ {
+ Row0 = paes_ctx->State[0][ColumnIndex];
+ Row1 = paes_ctx->State[1][ColumnIndex];
+ Row2 = paes_ctx->State[2][ColumnIndex];
+ Row3 = paes_ctx->State[3][ColumnIndex];
+ paes_ctx->State[0][ColumnIndex] = aes_mul_2[Row0]^aes_mul_3[Row1]^Row2^Row3;
+ paes_ctx->State[1][ColumnIndex] = Row0^aes_mul_2[Row1]^aes_mul_3[Row2]^Row3;
+ paes_ctx->State[2][ColumnIndex] = Row0^Row1^aes_mul_2[Row2]^aes_mul_3[Row3];
+ paes_ctx->State[3][ColumnIndex] = aes_mul_3[Row0]^Row1^Row2^aes_mul_2[Row3];
+ }
+
+ /* AES_AddRoundKey */
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex];
+ }
+
+ /* AES_SubBytes */
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ paes_ctx->State[RowIndex][ColumnIndex] = aes_sbox_enc[paes_ctx->State[RowIndex][ColumnIndex]];
+ /* AES_ShiftRows */
+ Temp = paes_ctx->State[1][0];
+ paes_ctx->State[1][0] = paes_ctx->State[1][1];
+ paes_ctx->State[1][1] = paes_ctx->State[1][2];
+ paes_ctx->State[1][2] = paes_ctx->State[1][3];
+ paes_ctx->State[1][3] = Temp;
+ Temp = paes_ctx->State[2][0];
+ paes_ctx->State[2][0] = paes_ctx->State[2][2];
+ paes_ctx->State[2][2] = Temp;
+ Temp = paes_ctx->State[2][1];
+ paes_ctx->State[2][1] = paes_ctx->State[2][3];
+ paes_ctx->State[2][3] = Temp;
+ Temp = paes_ctx->State[3][3];
+ paes_ctx->State[3][3] = paes_ctx->State[3][2];
+ paes_ctx->State[3][2] = paes_ctx->State[3][1];
+ paes_ctx->State[3][1] = paes_ctx->State[3][0];
+ paes_ctx->State[3][0] = Temp;
+ /* AES_AddRoundKey */
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex];
+
+ /*
+ * 4. Transfer the state block to cipher block
+ */
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ CipherBlock[RowIndex + 4*ColumnIndex] = paes_ctx->State[RowIndex][ColumnIndex];
+
+ *CipherBlockSize = ((UINT) AES_STATE_ROWS)*((UINT) AES_STATE_COLUMNS);
+
+ if (paes_ctx != NULL)
+ os_free_mem(NULL, paes_ctx);
+}
+
+
+/*
+========================================================================
+Routine Description:
+ AES decryption
+
+Arguments:
+ CipherBlock The block of cipher text, 16 bytes(128 bits) each block
+ CipherBlockSize The length of block of cipher text in bytes
+ Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits)
+ KeyLength The length of cipher key in bytes
+ PlainBlockSize The length of allocated plain block in bytes
+
+Return Value:
+ PlainBlock Return plain text
+ PlainBlockSize Return the length of real used plain block in bytes
+
+Note:
+ Reference to FIPS-PUB 197
+ 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits)
+ 2. Transfer the cipher block to state block
+ 3. Main decryption rounds
+ 4. Transfer the state block to plain block
+ ------------------------------------------
+ NumberOfRound = (key length / 4) + 6;
+ state block = cipher block;
+
+ AddRoundKey(state block, key);
+ for round = NumberOfRound to 1
+ InvSubBytes(state block)
+ InvShiftRows(state block)
+ InvMixColumns(state block)
+ AddRoundKey(state block, key);
+ end for
+
+ InvSubBytes(state block)
+ InvShiftRows(state block)
+ AddRoundKey(state block, key);
+
+ plain block = state block;
+========================================================================
+*/
+VOID RT_AES_Decrypt (
+ IN UINT8 CipherBlock[],
+ IN UINT CipherBlockSize,
+ IN UINT8 Key[],
+ IN UINT KeyLength,
+ OUT UINT8 PlainBlock[],
+ INOUT UINT *PlainBlockSize)
+{
+/* AES_CTX_STRUC aes_ctx;
+*/
+ AES_CTX_STRUC *paes_ctx = NULL;
+ UINT RowIndex, ColumnIndex;
+ UINT RoundIndex, NumberOfRound = 0;
+ UINT8 Temp, Row0, Row1, Row2, Row3;
+
+ /*
+ * 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits)
+ */
+ if (*PlainBlockSize < AES_BLOCK_SIZES) {
+ DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Decrypt: plain block size is %d bytes, it must be %d bytes(128 bits).\n",
+ *PlainBlockSize, AES_BLOCK_SIZES));
+ return;
+ }
+ if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Decrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n",
+ KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH));
+ return;
+ }
+ if (CipherBlockSize != AES_BLOCK_SIZES) {
+ DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Decrypt: cipher block size is %d bytes, it must be %d bytes(128 bits).\n",
+ CipherBlockSize, AES_BLOCK_SIZES));
+ return;
+ }
+
+ /* allocate memory */
+ os_alloc_mem(NULL, (UCHAR **)&paes_ctx, sizeof(AES_CTX_STRUC));
+ if (paes_ctx == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ return;
+ }
+
+ /*
+ * 2. Transfer the cipher block to state block
+ */
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ paes_ctx->State[RowIndex][ColumnIndex] = CipherBlock[RowIndex + 4*ColumnIndex];
+
+ /*
+ * 3. Main decryption rounds
+ */
+ RT_AES_KeyExpansion(Key, KeyLength, paes_ctx);
+ NumberOfRound = (KeyLength >> 2) + 6;
+
+ /* AES_AddRoundKey */
+ RoundIndex = NumberOfRound;
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex];
+
+ for (RoundIndex = (NumberOfRound - 1); RoundIndex > 0 ;RoundIndex--)
+ {
+ /* AES_InvShiftRows */
+ Temp = paes_ctx->State[1][3];
+ paes_ctx->State[1][3] = paes_ctx->State[1][2];
+ paes_ctx->State[1][2] = paes_ctx->State[1][1];
+ paes_ctx->State[1][1] = paes_ctx->State[1][0];
+ paes_ctx->State[1][0] = Temp;
+ Temp = paes_ctx->State[2][0];
+ paes_ctx->State[2][0] = paes_ctx->State[2][2];
+ paes_ctx->State[2][2] = Temp;
+ Temp = paes_ctx->State[2][1];
+ paes_ctx->State[2][1] = paes_ctx->State[2][3];
+ paes_ctx->State[2][3] = Temp;
+ Temp = paes_ctx->State[3][0];
+ paes_ctx->State[3][0] = paes_ctx->State[3][1];
+ paes_ctx->State[3][1] = paes_ctx->State[3][2];
+ paes_ctx->State[3][2] = paes_ctx->State[3][3];
+ paes_ctx->State[3][3] = Temp;
+
+ /* AES_InvSubBytes */
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ paes_ctx->State[RowIndex][ColumnIndex] = aes_sbox_dec[paes_ctx->State[RowIndex][ColumnIndex]];
+
+ /* AES_AddRoundKey */
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex];
+
+ /* AES_InvMixColumns */
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ {
+ Row0 = paes_ctx->State[0][ColumnIndex];
+ Row1 = paes_ctx->State[1][ColumnIndex];
+ Row2 = paes_ctx->State[2][ColumnIndex];
+ Row3 = paes_ctx->State[3][ColumnIndex];
+ paes_ctx->State[0][ColumnIndex] = aes_mul_e[Row0]^aes_mul_b[Row1]^aes_mul_d[Row2]^aes_mul_9[Row3];
+ paes_ctx->State[1][ColumnIndex] = aes_mul_9[Row0]^aes_mul_e[Row1]^aes_mul_b[Row2]^aes_mul_d[Row3];
+ paes_ctx->State[2][ColumnIndex] = aes_mul_d[Row0]^aes_mul_9[Row1]^aes_mul_e[Row2]^aes_mul_b[Row3];
+ paes_ctx->State[3][ColumnIndex] = aes_mul_b[Row0]^aes_mul_d[Row1]^aes_mul_9[Row2]^aes_mul_e[Row3];
+ }
+ }
+
+ /* AES_InvShiftRows */
+ Temp = paes_ctx->State[1][3];
+ paes_ctx->State[1][3] = paes_ctx->State[1][2];
+ paes_ctx->State[1][2] = paes_ctx->State[1][1];
+ paes_ctx->State[1][1] = paes_ctx->State[1][0];
+ paes_ctx->State[1][0] = Temp;
+ Temp = paes_ctx->State[2][0];
+ paes_ctx->State[2][0] = paes_ctx->State[2][2];
+ paes_ctx->State[2][2] = Temp;
+ Temp = paes_ctx->State[2][1];
+ paes_ctx->State[2][1] = paes_ctx->State[2][3];
+ paes_ctx->State[2][3] = Temp;
+ Temp = paes_ctx->State[3][0];
+ paes_ctx->State[3][0] = paes_ctx->State[3][1];
+ paes_ctx->State[3][1] = paes_ctx->State[3][2];
+ paes_ctx->State[3][2] = paes_ctx->State[3][3];
+ paes_ctx->State[3][3] = Temp;
+ /* AES_InvSubBytes */
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ paes_ctx->State[RowIndex][ColumnIndex] = aes_sbox_dec[paes_ctx->State[RowIndex][ColumnIndex]];
+ /* AES_AddRoundKey */
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex];
+
+ /*
+ * 4. Transfer the state block to plain block
+ */
+ for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++)
+ for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++)
+ PlainBlock[RowIndex + 4*ColumnIndex] = paes_ctx->State[RowIndex][ColumnIndex];
+
+ *PlainBlockSize = ((UINT) AES_STATE_ROWS)*((UINT) AES_STATE_COLUMNS);
+
+ if (paes_ctx != NULL)
+ os_free_mem(NULL, paes_ctx);
+}
+
+
+
+/*
+========================================================================
+Routine Description:
+ AES-CBCMAC
+
+Arguments:
+ Payload Data
+ PayloadLength The length of data in bytes
+ Key Cipher key
+ KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes)
+ Nonce Nonce
+ NonceLength The length of nonce in bytes
+ AAD Additional authenticated data
+ AADLength The length of AAD in bytes
+ MACLength The length of MAC in bytes
+
+Return Value:
+ MACText The mac
+
+Note:
+ Reference to RFC 3601, and NIST 800-38C.
+========================================================================
+*/
+VOID AES_CCM_MAC (
+ IN UINT8 Payload[],
+ IN UINT PayloadLength,
+ IN UINT8 Key[],
+ IN UINT KeyLength,
+ IN UINT8 Nonce[],
+ IN UINT NonceLength,
+ IN UINT8 AAD[],
+ IN UINT AADLength,
+ IN UINT MACLength,
+ OUT UINT8 MACText[])
+{
+ UINT8 Block[AES_BLOCK_SIZES], Block_MAC[AES_BLOCK_SIZES];
+ UINT Block_Index = 0, ADD_Index = 0, Payload_Index = 0;
+ UINT Temp_Value = 0, Temp_Index = 0, Temp_Length = 0, Copy_Length = 0;
+
+ /*
+ * 1. Formatting of the Control Information and the Nonce
+ */
+ NdisZeroMemory(Block, AES_BLOCK_SIZES);
+ if (AADLength > 0)
+ Block[0] |= 0x40; /* Set bit 6 to 1 */
+ Temp_Value = ((MACLength - 2) >> 1) << 3; /* Set bit 3-5 to (t-2)/2 */
+ Block[0] |= Temp_Value;
+ Temp_Value = (15 - NonceLength) - 1; /* Set bit 0-2 to (q-1), q = 15 - Nonce Length */
+ Block[0] |= Temp_Value;
+ for (Temp_Index = 0; Temp_Index < NonceLength; Temp_Index++)
+ Block[Temp_Index + 1] = Nonce[Temp_Index];
+ if (NonceLength < 12)
+ Block[12] = (PayloadLength >> 24) & 0xff;
+ if (NonceLength < 13)
+ Block[13] = (PayloadLength >> 16) & 0xff;
+ Block[14] = (PayloadLength >> 8) & 0xff;
+ Block[15] = PayloadLength & 0xff;
+
+ NdisZeroMemory(Block_MAC, AES_BLOCK_SIZES);
+ Temp_Length = sizeof(Block_MAC);
+ RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, Block_MAC, &Temp_Length);
+
+ /*
+ * 2. Formatting of the Associated Data
+ * If 0 < AADLength < (2^16 - 2^8), AData_Length = 2
+ * If (2^16 - 2^8) < AADLength < 2^32, AData_Length = 6
+ * If 2^32 < AADLength < 2^64, AData_Length = 10 (not implement)
+ */
+ NdisZeroMemory(Block, AES_BLOCK_SIZES);
+ if ((AADLength > 0) && (AADLength < 0xFF00)) {
+ Block_Index = 2;
+ Block[0] = (AADLength >> 8) & 0xff;
+ Block[1] = AADLength & 0xff;
+ } else {
+ Block_Index = 6;
+ Block[2] = (AADLength >> 24) & 0xff;
+ Block[3] = (AADLength >> 16) & 0xff;
+ Block[4] = (AADLength >> 8) & 0xff;
+ Block[5] = AADLength & 0xff;
+ }
+
+ while (ADD_Index < AADLength)
+ {
+ Copy_Length = AADLength - ADD_Index;
+ if (Copy_Length > AES_BLOCK_SIZES)
+ Copy_Length = AES_BLOCK_SIZES;
+ if ((Copy_Length + Block_Index) > AES_BLOCK_SIZES) {
+ Copy_Length = AES_BLOCK_SIZES - Block_Index;
+ }
+ for (Temp_Index = 0; Temp_Index < Copy_Length; Temp_Index++)
+ Block[Temp_Index + Block_Index] = AAD[ADD_Index + Temp_Index];
+ for (Temp_Index = 0; Temp_Index < AES_BLOCK_SIZES; Temp_Index++)
+ Block[Temp_Index] ^= Block_MAC[Temp_Index];
+ NdisZeroMemory(Block_MAC, AES_BLOCK_SIZES);
+ Temp_Length = sizeof(Block_MAC);
+ RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, Block_MAC, &Temp_Length);
+ ADD_Index += Copy_Length;
+ Block_Index = 0;
+ NdisZeroMemory(Block, AES_BLOCK_SIZES);
+ }
+
+ /*
+ * 3. Calculate the MAC (MIC)
+ */
+ while (Payload_Index < PayloadLength)
+ {
+ NdisZeroMemory(Block, AES_BLOCK_SIZES);
+ Copy_Length = PayloadLength - Payload_Index;
+ if (Copy_Length > AES_BLOCK_SIZES)
+ Copy_Length = AES_BLOCK_SIZES;
+ for (Temp_Index = 0; Temp_Index < Copy_Length; Temp_Index++)
+ Block[Temp_Index] = Payload[Payload_Index + Temp_Index];
+ for (Temp_Index = 0; Temp_Index < AES_BLOCK_SIZES; Temp_Index++)
+ Block[Temp_Index] ^= Block_MAC[Temp_Index];
+ NdisZeroMemory(Block_MAC, AES_BLOCK_SIZES);
+ Temp_Length = sizeof(Block_MAC);
+ RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, Block_MAC, &Temp_Length);
+ Payload_Index += Copy_Length;
+ }
+ for (Temp_Index = 0; Temp_Index < MACLength; Temp_Index++)
+ MACText[Temp_Index] = Block_MAC[Temp_Index];
+}
+
+
+/*
+========================================================================
+Routine Description:
+ AES-CBCMAC Encryption
+
+Arguments:
+ PlainText Plain text
+ PlainTextLength The length of plain text in bytes
+ Key Cipher key
+ KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes)
+ Nonce Nonce
+ NonceLength The length of nonce in bytes
+ AAD Additional authenticated data
+ AADLength The length of AAD in bytes
+ MACLength The length of MAC in bytes
+ CipherTextLength The length of allocated memory spaces in bytes
+
+Return Value:
+ CipherText The ciphertext
+ CipherTextLength Return the length of the ciphertext in bytes
+
+Function Value:
+ 0: Success
+ -1: The key length must be 16 bytes.
+ -2: A valid nonce length is 7-13 bytes.
+ -3: The MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes.
+ -4: The CipherTextLength is not enough.
+
+Note:
+ Reference to RFC 3601, and NIST 800-38C.
+ Here, the implement of AES_CCM is suitable for WI_FI.
+========================================================================
+*/
+INT AES_CCM_Encrypt (
+ IN UINT8 PlainText[],
+ IN UINT PlainTextLength,
+ IN UINT8 Key[],
+ IN UINT KeyLength,
+ IN UINT8 Nonce[],
+ IN UINT NonceLength,
+ IN UINT8 AAD[],
+ IN UINT AADLength,
+ IN UINT MACLength,
+ OUT UINT8 CipherText[],
+ INOUT UINT *CipherTextLength)
+{
+ UINT8 Block_MAC[AES_BLOCK_SIZES];
+ UINT8 Block_CTR[AES_BLOCK_SIZES], Block_CTR_Cipher[AES_BLOCK_SIZES];
+ UINT Cipher_Index = 0;
+ UINT Temp_Value = 0, Temp_Index = 0, Temp_Length = 0, Copy_Length = 0;
+
+ /*
+ * 1. Check Input Values
+ * - Key length must be 16 bytes
+ * - Nonce length range is form 7 to 13 bytes
+ * - MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes
+ * - CipherTextLength > PlainTextLength + MACLength
+ */
+ if (KeyLength != AES_KEY128_LENGTH) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: The key length must be %d bytes\n", AES_KEY128_LENGTH));
+ return -1;
+ }
+
+ if ((NonceLength < 7) || (NonceLength > 13)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: A valid nonce length is 7-13 bytes\n"));
+ return -2;
+ }
+
+ if ((MACLength != 4) && (MACLength != 6) && (MACLength != 8) && (MACLength != 10)
+ && (MACLength != 12) && (MACLength != 14) && (MACLength != 16)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: The MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes\n"));
+ return -3;
+ }
+
+ if (*CipherTextLength < (PlainTextLength + MACLength)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: The CipherTextLength is not enough.\n"));
+ return -4;
+ }
+
+
+ /*
+ * 1. Formatting of the Counter Block
+ */
+ NdisZeroMemory(Block_CTR, AES_BLOCK_SIZES);
+ Temp_Value = (15 - NonceLength) - 1; /* Set bit 0-2 to (q-1), q = 15 - Nonce Length */
+ Block_CTR[0] |= Temp_Value;
+ for (Temp_Index = 0; Temp_Index < NonceLength; Temp_Index++)
+ Block_CTR[Temp_Index + 1] = Nonce[Temp_Index];
+
+ /*
+ * 2. Calculate the MAC (MIC)
+ */
+ AES_CCM_MAC(PlainText, PlainTextLength, Key, KeyLength, Nonce, NonceLength, AAD, AADLength, MACLength, Block_MAC);
+ Temp_Length = sizeof(Block_CTR_Cipher);
+ RT_AES_Encrypt(Block_CTR, AES_BLOCK_SIZES , Key, KeyLength, Block_CTR_Cipher, &Temp_Length);
+ for (Temp_Index = 0; Temp_Index < MACLength; Temp_Index++)
+ Block_MAC[Temp_Index] ^= Block_CTR_Cipher[Temp_Index];
+
+ /*
+ * 3. Cipher Payload
+ */
+ while (Cipher_Index < PlainTextLength)
+ {
+ Block_CTR[15] += 1;
+ Temp_Length = sizeof(Block_CTR_Cipher);
+ RT_AES_Encrypt(Block_CTR, AES_BLOCK_SIZES , Key, KeyLength, Block_CTR_Cipher, &Temp_Length);
+
+ Copy_Length = PlainTextLength - Cipher_Index;
+ if (Copy_Length > AES_BLOCK_SIZES)
+ Copy_Length = AES_BLOCK_SIZES;
+ for (Temp_Index = 0; Temp_Index < Copy_Length; Temp_Index++)
+ CipherText[Cipher_Index + Temp_Index] = PlainText[Cipher_Index + Temp_Index]^Block_CTR_Cipher[Temp_Index];
+
+ Cipher_Index += Copy_Length;
+ }
+ for (Temp_Index = 0; Temp_Index < MACLength; Temp_Index++)
+ CipherText[PlainTextLength + Temp_Index] = Block_MAC[Temp_Index];
+ *CipherTextLength = PlainTextLength + MACLength;
+
+ return 0;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ AES-CBCMAC Decryption
+
+Arguments:
+ CipherText The ciphertext
+ CipherTextLength The length of cipher text in bytes
+ Key Cipher key
+ KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes)
+ Nonce Nonce
+ NonceLength The length of nonce in bytes
+ AAD Additional authenticated data
+ AADLength The length of AAD in bytes
+ CipherTextLength The length of allocated memory spaces in bytes
+
+Return Value:
+ PlainText Plain text
+ PlainTextLength Return the length of the plain text in bytes
+
+Function Value:
+ 0: Success
+ -1: The key length must be 16 bytes.
+ -2: A valid nonce length is 7-13 bytes.
+ -3: The MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes.
+ -4: The PlainTextLength is not enough.
+ -5: The MIC does not match.
+
+Note:
+ Reference to RFC 3601, and NIST 800-38C.
+ Here, the implement of AES_CCM is suitable for WI_FI.
+========================================================================
+*/
+INT AES_CCM_Decrypt (
+ IN UINT8 CipherText[],
+ IN UINT CipherTextLength,
+ IN UINT8 Key[],
+ IN UINT KeyLength,
+ IN UINT8 Nonce[],
+ IN UINT NonceLength,
+ IN UINT8 AAD[],
+ IN UINT AADLength,
+ IN UINT MACLength,
+ OUT UINT8 PlainText[],
+ INOUT UINT *PlainTextLength)
+{
+ UINT8 Block_MAC[AES_BLOCK_SIZES], Block_MAC_From_Cipher[AES_BLOCK_SIZES];
+ UINT8 Block_CTR[AES_BLOCK_SIZES], Block_CTR_Cipher[AES_BLOCK_SIZES];
+ UINT Block_Index = 0, Cipher_Index = 0;
+ UINT Temp_Value = 0, Temp_Index = 0, Temp_Length = 0, Copy_Length = 0;
+
+
+ /*
+ * 1. Check Input Values
+ * - Key length must be 16 bytes
+ * - Nonce length range is form 7 to 13 bytes
+ */
+ if (KeyLength != AES_KEY128_LENGTH) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The key length must be %d bytes\n", AES_KEY128_LENGTH));
+ return -1;
+ }
+
+ if ((NonceLength < 7) || (NonceLength > 13)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: A valid nonce length is 7-13 bytes\n"));
+ return -2;
+ }
+
+ if ((MACLength != 4) && (MACLength != 6) && (MACLength != 8) && (MACLength != 10)
+ && (MACLength != 12) && (MACLength != 14) && (MACLength != 16)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes\n"));
+ return -3;
+ }
+
+ if (*PlainTextLength < (CipherTextLength - MACLength)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The PlainTextLength is not enough.\n"));
+ return -4;
+ }
+
+ /*
+ * 2. Formatting of the Counter Block
+ */
+ NdisZeroMemory(Block_CTR, AES_BLOCK_SIZES);
+ Temp_Value = (15 - NonceLength) - 1; /* Set bit 0-2 to (q-1), q = 15 - Nonce Length */
+ Block_CTR[0] |= Temp_Value;
+ for (Temp_Index = 0; Temp_Index < NonceLength; Temp_Index++)
+ Block_CTR[Temp_Index + 1] = Nonce[Temp_Index];
+ Temp_Length = sizeof(Block_CTR_Cipher);
+ RT_AES_Encrypt(Block_CTR, AES_BLOCK_SIZES , Key, KeyLength, Block_CTR_Cipher, &Temp_Length);
+
+ /*
+ * 3. Catch the MAC (MIC) from CipherText
+ */
+ Block_Index = 0;
+ for (Temp_Index = (CipherTextLength - MACLength); Temp_Index < CipherTextLength; Temp_Index++, Block_Index++)
+ Block_MAC_From_Cipher[Block_Index] = CipherText[Temp_Index]^Block_CTR_Cipher[Block_Index];
+
+ /*
+ * 4. Decryption the Payload
+ */
+ while (Cipher_Index < (CipherTextLength - MACLength))
+ {
+ Block_CTR[15] += 1;
+ Temp_Length = sizeof(Block_CTR_Cipher);
+ RT_AES_Encrypt(Block_CTR, AES_BLOCK_SIZES , Key, KeyLength, Block_CTR_Cipher, &Temp_Length);
+
+ Copy_Length = (CipherTextLength - MACLength) - Cipher_Index;
+ if (Copy_Length > AES_BLOCK_SIZES)
+ Copy_Length = AES_BLOCK_SIZES;
+ for (Temp_Index = 0; Temp_Index < Copy_Length; Temp_Index++)
+ PlainText[Cipher_Index + Temp_Index] = CipherText[Cipher_Index + Temp_Index]^Block_CTR_Cipher[Temp_Index];
+ Cipher_Index += Copy_Length;
+ }
+ *PlainTextLength = CipherTextLength - MACLength;
+
+ /*
+ * 5. Calculate the MAC (MIC) from Payload
+ */
+ AES_CCM_MAC(PlainText, *PlainTextLength, Key, KeyLength, Nonce, NonceLength, AAD, AADLength, MACLength, Block_MAC);
+
+ /*
+ * 6. Check the MIC
+ */
+ if (NdisCmpMemory(Block_MAC_From_Cipher, Block_MAC, MACLength) != 0) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The MIC does not match.\n"));
+ return -5;
+ }
+
+ return 0;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ AES-CMAC generate subkey
+
+Arguments:
+ Key Cipher key 128 bits
+ KeyLength The length of Cipher key in bytes
+
+Return Value:
+ SubKey1 SubKey 1 128 bits
+ SubKey2 SubKey 2 128 bits
+
+Note:
+ Reference to RFC 4493
+
+ Step 1. L := AES-128(K, const_Zero);
+ Step 2. if MSB(L) is equal to 0
+ then K1 := L << 1;
+ else K1 := (L << 1) XOR const_Rb;
+ Step 3. if MSB(K1) is equal to 0
+ then K2 := K1 << 1;
+ else K2 := (K1 << 1) XOR const_Rb;
+ Step 4. return K1, K2;
+========================================================================
+*/
+VOID AES_CMAC_GenerateSubKey (
+ IN UINT8 Key[],
+ IN UINT KeyLength,
+ OUT UINT8 SubKey1[],
+ OUT UINT8 SubKey2[])
+{
+ UINT8 MSB_L = 0, MSB_K1 = 0, Top_Bit = 0;
+ UINT SubKey1_Length = 0;
+ INT Index = 0;
+
+ if (KeyLength != AES_KEY128_LENGTH) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CMAC_GenerateSubKey: key length is %d bytes, it must be %d bytes(128 bits).\n",
+ KeyLength, AES_KEY128_LENGTH));
+ return;
+ }
+
+ /* Step 1: L := AES-128(K, const_Zero); */
+ SubKey1_Length = 16;
+ RT_AES_Encrypt(Const_Zero, sizeof(Const_Zero), Key, KeyLength, SubKey1, &SubKey1_Length);
+
+ /*
+ * Step 2. if MSB(L) is equal to 0
+ * then K1 := L << 1;
+ * else K1 := (L << 1) XOR const_Rb;
+ */
+ MSB_L = SubKey1[0] & 0x80;
+ for(Index = 0; Index < 15; Index++) {
+ Top_Bit = (SubKey1[Index + 1] & 0x80)?1:0;
+ SubKey1[Index] <<= 1;
+ SubKey1[Index] |= Top_Bit;
+ }
+ SubKey1[15] <<= 1;
+ if (MSB_L > 0) {
+ for(Index = 0; Index < 16; Index++)
+ SubKey1[Index] ^= Const_Rb[Index];
+ }
+
+ /*
+ * Step 3. if MSB(K1) is equal to 0
+ * then K2 := K1 << 1;
+ * else K2 := (K1 << 1) XOR const_Rb;
+ */
+ MSB_K1 = SubKey1[0] & 0x80;
+ for(Index = 0; Index < 15; Index++) {
+ Top_Bit = (SubKey1[Index + 1] & 0x80)?1:0;
+ SubKey2[Index] = SubKey1[Index] << 1;
+ SubKey2[Index] |= Top_Bit;
+ }
+ SubKey2[15] = SubKey1[15] << 1;
+ if (MSB_K1 > 0) {
+ for(Index = 0; Index < 16; Index++)
+ SubKey2[Index] ^= Const_Rb[Index];
+ }
+}
+
+
+/*
+========================================================================
+Routine Description:
+ AES-CMAC
+
+Arguments:
+ PlainText Plain text
+ PlainTextLength The length of plain text in bytes
+ Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits)
+ KeyLength The length of cipher key in bytes
+ MACTextLength The length of allocated memory spaces in bytes
+
+Return Value:
+ MACText Message authentication code (128-bit string)
+ MACTextLength Return the length of Message authentication code in bytes
+
+Note:
+ Reference to RFC 4493
+========================================================================
+*/
+VOID AES_CMAC (
+ IN UINT8 PlainText[],
+ IN UINT PlainTextLength,
+ IN UINT8 Key[],
+ IN UINT KeyLength,
+ OUT UINT8 MACText[],
+ INOUT UINT *MACTextLength)
+{
+ UINT PlainBlockStart;
+ UINT8 X[AES_BLOCK_SIZES], Y[AES_BLOCK_SIZES];
+ UINT8 SubKey1[16];
+ UINT8 SubKey2[16];
+ INT Index;
+ UINT X_Length;
+
+ if (*MACTextLength < AES_MAC_LENGTH) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CMAC: MAC text length is less than %d bytes).\n",
+ AES_MAC_LENGTH));
+ return;
+ }
+ if (KeyLength != AES_KEY128_LENGTH) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CMAC: key length is %d bytes, it must be %d bytes(128 bits).\n",
+ KeyLength, AES_KEY128_LENGTH));
+ return;
+ }
+
+ /* Step 1. (K1,K2) := Generate_Subkey(K); */
+ NdisZeroMemory(SubKey1, 16);
+ NdisZeroMemory(SubKey2, 16);
+ AES_CMAC_GenerateSubKey(Key, KeyLength, SubKey1, SubKey2);
+
+ /*
+ * 2. Main algorithm
+ * - Plain text divide into serveral blocks (16 bytes/block)
+ * - If plain text is not divided with no remainder by block, padding size = (block - remainder plain text)
+ * - Execute RT_AES_Encrypt procedure.
+ */
+ PlainBlockStart = 0;
+ NdisMoveMemory(X, Const_Zero, AES_BLOCK_SIZES);
+ while ((PlainTextLength - PlainBlockStart) > AES_BLOCK_SIZES)
+ {
+ for (Index = 0; Index < AES_BLOCK_SIZES; Index++)
+ Y[Index] = PlainText[PlainBlockStart + Index]^X[Index];
+
+ X_Length = sizeof(X);
+ RT_AES_Encrypt(Y, sizeof(Y) , Key, KeyLength, X, &X_Length);
+ PlainBlockStart += ((UINT) AES_BLOCK_SIZES);
+ }
+ if ((PlainTextLength - PlainBlockStart) == AES_BLOCK_SIZES) {
+ for (Index = 0; Index < AES_BLOCK_SIZES; Index++)
+ Y[Index] = PlainText[PlainBlockStart + Index]^X[Index]^SubKey1[Index];
+ } else {
+ NdisZeroMemory(Y, AES_BLOCK_SIZES);
+ NdisMoveMemory(Y, &PlainText[PlainBlockStart], (PlainTextLength - PlainBlockStart));
+ Y[(PlainTextLength - PlainBlockStart)] = 0x80;
+ for (Index = 0; Index < AES_BLOCK_SIZES; Index++)
+ Y[Index] = Y[Index]^X[Index]^SubKey2[Index];
+ }
+ RT_AES_Encrypt(Y, sizeof(Y) , Key, KeyLength, MACText, MACTextLength);
+}
+
+
+/* For AES_Key_Wrap */
+#define AES_KEY_WRAP_IV_LENGTH 8 /* 64-bit */
+#define AES_KEY_WRAP_BLOCK_SIZE 8 /* 64-bit */
+static UINT8 Default_IV[8] = {
+ 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6};
+
+/*
+========================================================================
+Routine Description:
+ AES-CBC encryption
+
+Arguments:
+ PlainText Plain text
+ PlainTextLength The length of plain text in bytes
+ Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits)
+ KeyLength The length of cipher key in bytes
+ IV Initialization vector, it may be 16 bytes (128 bits)
+ IVLength The length of initialization vector in bytes
+ CipherTextLength The length of allocated cipher text in bytes
+
+Return Value:
+ CipherText Return cipher text
+ CipherTextLength Return the length of real used cipher text in bytes
+
+Note:
+ Reference to RFC 3602 and NIST 800-38A
+========================================================================
+*/
+VOID AES_CBC_Encrypt (
+ IN UINT8 PlainText[],
+ IN UINT PlainTextLength,
+ IN UINT8 Key[],
+ IN UINT KeyLength,
+ IN UINT8 IV[],
+ IN UINT IVLength,
+ OUT UINT8 CipherText[],
+ INOUT UINT *CipherTextLength)
+{
+ UINT PaddingSize, PlainBlockStart, CipherBlockStart, CipherBlockSize;
+ UINT Index;
+ UINT8 Block[AES_BLOCK_SIZES];
+
+ /*
+ * 1. Check the input parameters
+ * - CipherTextLength > (PlainTextLength + Padding size), Padding size = block size - (PlainTextLength % block size)
+ * - Key length must be 16, 24, or 32 bytes(128, 192, or 256 bits)
+ * - IV length must be 16 bytes(128 bits)
+ */
+ PaddingSize = ((UINT) AES_BLOCK_SIZES) - (PlainTextLength % ((UINT)AES_BLOCK_SIZES));
+ if (*CipherTextLength < (PlainTextLength + PaddingSize)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Encrypt: cipher text length is %d bytes < (plain text length %d bytes + padding size %d bytes).\n",
+ *CipherTextLength, PlainTextLength, PaddingSize));
+ return;
+ }
+ if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Encrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n",
+ KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH));
+ return;
+ }
+ if (IVLength != AES_CBC_IV_LENGTH) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Encrypt: IV length is %d bytes, it must be %d bytes(128bits).\n",
+ IVLength, AES_CBC_IV_LENGTH));
+ return;
+ }
+
+
+ /*
+ * 2. Main algorithm
+ * - Plain text divide into serveral blocks (16 bytes/block)
+ * - If plain text is divided with no remainder by block, add a new block and padding size = block(16 bytes)
+ * - If plain text is not divided with no remainder by block, padding size = (block - remainder plain text)
+ * - Execute RT_AES_Encrypt procedure.
+ *
+ * - Padding method: The remainder bytes will be filled with padding size (1 byte)
+ */
+ PlainBlockStart = 0;
+ CipherBlockStart = 0;
+ while ((PlainTextLength - PlainBlockStart) >= AES_BLOCK_SIZES)
+ {
+ if (CipherBlockStart == 0) {
+ for (Index = 0; Index < AES_BLOCK_SIZES; Index++)
+ Block[Index] = PlainText[PlainBlockStart + Index]^IV[Index];
+ } else {
+ for (Index = 0; Index < AES_BLOCK_SIZES; Index++)
+ Block[Index] = PlainText[PlainBlockStart + Index]^CipherText[CipherBlockStart - ((UINT) AES_BLOCK_SIZES) + Index];
+ }
+
+ CipherBlockSize = *CipherTextLength - CipherBlockStart;
+ RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, CipherText + CipherBlockStart, &CipherBlockSize);
+
+ PlainBlockStart += ((UINT) AES_BLOCK_SIZES);
+ CipherBlockStart += CipherBlockSize;
+ }
+
+ NdisMoveMemory(Block, (&PlainText[0] + PlainBlockStart), (PlainTextLength - PlainBlockStart));
+ NdisFillMemory((Block + (((UINT) AES_BLOCK_SIZES) -PaddingSize)), PaddingSize, (UINT8) PaddingSize);
+ if (CipherBlockStart == 0) {
+ for (Index = 0; Index < AES_BLOCK_SIZES; Index++)
+ Block[Index] ^= IV[Index];
+ } else {
+ for (Index = 0; Index < AES_BLOCK_SIZES; Index++)
+ Block[Index] ^= CipherText[CipherBlockStart - ((UINT) AES_BLOCK_SIZES) + Index];
+ }
+ CipherBlockSize = *CipherTextLength - CipherBlockStart;
+ RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, CipherText + CipherBlockStart, &CipherBlockSize);
+ CipherBlockStart += CipherBlockSize;
+ *CipherTextLength = CipherBlockStart;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ AES-CBC decryption
+
+Arguments:
+ CipherText Cipher text
+ CipherTextLength The length of cipher text in bytes
+ Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits)
+ KeyLength The length of cipher key in bytes
+ IV Initialization vector, it may be 16 bytes (128 bits)
+ IVLength The length of initialization vector in bytes
+ PlainTextLength The length of allocated plain text in bytes
+
+Return Value:
+ PlainText Return plain text
+ PlainTextLength Return the length of real used plain text in bytes
+
+Note:
+ Reference to RFC 3602 and NIST 800-38A
+========================================================================
+*/
+VOID AES_CBC_Decrypt (
+ IN UINT8 CipherText[],
+ IN UINT CipherTextLength,
+ IN UINT8 Key[],
+ IN UINT KeyLength,
+ IN UINT8 IV[],
+ IN UINT IVLength,
+ OUT UINT8 PlainText[],
+ INOUT UINT *PlainTextLength)
+{
+ UINT PaddingSize, PlainBlockStart, CipherBlockStart, PlainBlockSize;
+ UINT Index;
+
+ /*
+ * 1. Check the input parameters
+ * - CipherTextLength must be divided with no remainder by block
+ * - Key length must be 16, 24, or 32 bytes(128, 192, or 256 bits)
+ * - IV length must be 16 bytes(128 bits)
+ */
+ if ((CipherTextLength % AES_BLOCK_SIZES) != 0) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Decrypt: cipher text length is %d bytes, it can't be divided with no remainder by block size(%d).\n",
+ CipherTextLength, AES_BLOCK_SIZES));
+ return;
+ }
+ if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Decrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n",
+ KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH));
+ return;
+ }
+ if (IVLength != AES_CBC_IV_LENGTH) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Decrypt: IV length is %d bytes, it must be %d bytes(128bits).\n",
+ IVLength, AES_CBC_IV_LENGTH));
+ return;
+ }
+
+
+ /*
+ * 2. Main algorithm
+ * - Cypher text divide into serveral blocks (16 bytes/block)
+ * - Execute RT_AES_Decrypt procedure.
+ * - Remove padding bytes, padding size is the last byte of plain text
+ */
+ CipherBlockStart = 0;
+ PlainBlockStart = 0;
+ while ((CipherTextLength - CipherBlockStart) >= AES_BLOCK_SIZES)
+ {
+ PlainBlockSize = *PlainTextLength - PlainBlockStart;
+ RT_AES_Decrypt(CipherText + CipherBlockStart, AES_BLOCK_SIZES , Key, KeyLength, PlainText + PlainBlockStart, &PlainBlockSize);
+
+ if (PlainBlockStart == 0) {
+ for (Index = 0; Index < AES_BLOCK_SIZES; Index++)
+ PlainText[PlainBlockStart + Index] ^= IV[Index];
+ } else {
+ for (Index = 0; Index < AES_BLOCK_SIZES; Index++)
+ PlainText[PlainBlockStart + Index] ^= CipherText[CipherBlockStart + Index - ((UINT) AES_BLOCK_SIZES)];
+ }
+
+ CipherBlockStart += AES_BLOCK_SIZES;
+ PlainBlockStart += PlainBlockSize;
+ }
+
+ PaddingSize = (UINT8) PlainText[PlainBlockStart -1];
+ *PlainTextLength = PlainBlockStart - PaddingSize;
+
+}
+
+
+/*
+========================================================================
+Routine Description:
+ AES key wrap algorithm
+
+Arguments:
+ PlainText Plain text
+ PlainTextLength The length of plain text in bytes
+ Key Cipher key
+ KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes)
+
+Return Value:
+ CipherText The ciphertext
+ CipherTextLength Return the length of the ciphertext in bytes
+
+Function Value:
+ 0: Success
+ -1: The key length must be 16, 24, or 32 bytes
+ -2: Not enough memory
+
+Note:
+ Reference to RFC 3394
+========================================================================
+*/
+INT AES_Key_Wrap (
+ IN UINT8 PlainText[],
+ IN UINT PlainTextLength,
+ IN UINT8 Key[],
+ IN UINT KeyLength,
+ OUT UINT8 CipherText[],
+ OUT UINT *CipherTextLength)
+{
+ UINT8 IV[8], Block_B[16], Block_Input[16];
+ UINT8 *pResult;
+ UINT Temp_Length = 0, Number_Of_Block = 0;
+ INT Index_i = 0, Index_j = 0;
+
+ /*
+ * 0. Check input parameter
+ */
+ if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_Key_Wrap: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n",
+ KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH));
+ return -1;
+ } /* End of if */
+ os_alloc_mem(NULL, (UCHAR **)&pResult, sizeof(UINT8)*PlainTextLength);
+/* if ((pResult = (UINT8 *) kmalloc(sizeof(UINT8)*PlainTextLength, GFP_ATOMIC)) == NULL) {
+*/
+ if (pResult == NULL) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_Key_Wrap: allocate %d bytes memory failure.\n", sizeof(UINT8)*PlainTextLength));
+ return -2;
+ } /* End of if */
+
+
+ /*
+ * 1. Initialize variables
+ */
+ Number_Of_Block = PlainTextLength / AES_KEY_WRAP_BLOCK_SIZE; /* 64 bits each block
+*/
+ NdisMoveMemory(IV, Default_IV, AES_KEY_WRAP_IV_LENGTH);
+ NdisMoveMemory(pResult, PlainText, PlainTextLength);
+
+
+ /*
+ * 2. Calculate intermediate values
+ */
+ for (Index_j = 0;Index_j < 6 ;Index_j++)
+ {
+ for (Index_i = 0;Index_i < Number_Of_Block;Index_i++)
+ {
+ NdisMoveMemory(Block_Input, IV, 8);
+ NdisMoveMemory(Block_Input + 8, pResult + (Index_i*8), 8);
+ Temp_Length = sizeof(Block_B);
+ RT_AES_Encrypt(Block_Input, AES_BLOCK_SIZES , Key, KeyLength, Block_B, &Temp_Length);
+
+ NdisMoveMemory(IV, Block_B, 8);
+ IV[7] = Block_B[7] ^ ((Number_Of_Block * Index_j) + Index_i + 1);
+ NdisMoveMemory(pResult + (Index_i*8), (Block_B + 8), 8);
+ } /* End of for */
+ } /* End of for */
+
+
+ /*
+ * 3. Output the results
+ */
+ *CipherTextLength = PlainTextLength + AES_KEY_WRAP_IV_LENGTH;
+ NdisMoveMemory(CipherText, IV, AES_KEY_WRAP_IV_LENGTH);
+ NdisMoveMemory(CipherText + AES_KEY_WRAP_IV_LENGTH, pResult, PlainTextLength);
+
+/* kfree(pResult);
+*/
+ os_free_mem(NULL, pResult);
+ return 0;
+} /* End of AES_Key_Wrap */
+
+
+/*
+========================================================================
+Routine Description:
+ AES key unwrap algorithm
+
+Arguments:
+ CipherText The ciphertext
+ CipherTextLength The length of cipher text in bytes
+ Key Cipher key
+ KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes)
+
+Return Value:
+ PlainText Plain text
+ PlainTextLength Return the length of the plain text in bytes
+
+Function Value:
+ 0: Success
+
+Note:
+ Reference to RFC 3394
+========================================================================
+*/
+INT AES_Key_Unwrap (
+ IN UINT8 CipherText[],
+ IN UINT CipherTextLength,
+ IN UINT8 Key[],
+ IN UINT KeyLength,
+ OUT UINT8 PlainText[],
+ OUT UINT *PlainTextLength)
+{
+ UINT8 IV[8], Block_B[16], Block_Input[16];
+ UINT8 *pResult;
+ UINT Temp_Length = 0, Number_Of_Block = 0, PlainLength;
+ INT Index_i = 0, Index_j = 0;
+
+ /*
+ * 0. Check input parameter
+ */
+ PlainLength = CipherTextLength - AES_KEY_WRAP_IV_LENGTH;
+ if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_Key_Unwrap: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n",
+ KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH));
+ return -1;
+ } /* End of if */
+ os_alloc_mem(NULL, (UCHAR **)&pResult, sizeof(UINT8)*PlainLength);
+/* if ((pResult = (UINT8 *) kmalloc(sizeof(UINT8)*PlainLength, GFP_ATOMIC)) == NULL) {
+*/
+ if (pResult == NULL) {
+ DBGPRINT(RT_DEBUG_ERROR, ("AES_Key_Unwrap: allocate %d bytes memory failure.\n", sizeof(UINT8)*PlainLength));
+ return -2;
+ } /* End of if */
+
+
+ /*
+ * 1. Initialize variables
+ */
+ Number_Of_Block = PlainLength / AES_KEY_WRAP_BLOCK_SIZE; /* 64 bits each block
+*/
+ NdisMoveMemory(IV, CipherText, AES_KEY_WRAP_IV_LENGTH);
+ NdisMoveMemory(pResult, CipherText + AES_KEY_WRAP_IV_LENGTH, PlainLength);
+
+
+ /*
+ * 2. Calculate intermediate values
+ */
+ for (Index_j = 5;Index_j >= 0 ;Index_j--)
+ {
+ for (Index_i = (Number_Of_Block - 1);Index_i >= 0;Index_i--)
+ {
+ IV[7] = IV[7] ^ ((Number_Of_Block * Index_j) + Index_i + 1);
+ NdisMoveMemory(Block_Input, IV, 8);
+ NdisMoveMemory(Block_Input + 8, pResult + (Index_i*8), 8);
+ Temp_Length = sizeof(Block_B);
+ RT_AES_Decrypt(Block_Input, AES_BLOCK_SIZES , Key, KeyLength, Block_B, &Temp_Length);
+
+ NdisMoveMemory(IV, Block_B, 8);
+ NdisMoveMemory(pResult + (Index_i*8), (Block_B + 8), 8);
+ } /* End of for */
+ } /* End of for */
+
+ /*
+ * 3. Output the results
+ */
+ *PlainTextLength = PlainLength;
+ NdisMoveMemory(PlainText, pResult, PlainLength);
+
+/* kfree(pResult);
+*/
+ os_free_mem(NULL, pResult);
+ return 0;
+} /* End of AES_Key_Unwrap */
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/crypt_arc4.c b/cleopatre/devkit/mt7601udrv/common/crypt_arc4.c
new file mode 100644
index 0000000000..382b89631e
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/crypt_arc4.c
@@ -0,0 +1,139 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************/
+
+
+/****************************************************************************
+ Module Name:
+ RC4
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ------------------------------------------
+ Eddy 2009/05/13 ARC4
+***************************************************************************/
+
+#include "crypt_arc4.h"
+
+
+/*
+========================================================================
+Routine Description:
+ ARC4 initialize the key block
+
+Arguments:
+ pARC4_CTX Pointer to ARC4 CONTEXT
+ Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits)
+ KeyLength The length of cipher key in bytes
+
+========================================================================
+*/
+VOID ARC4_INIT (
+ IN ARC4_CTX_STRUC *pARC4_CTX,
+ IN PUCHAR pKey,
+ IN UINT KeyLength)
+{
+ UINT BlockIndex = 0, SWAPIndex = 0, KeyIndex = 0;
+ UINT8 TempValue = 0;
+
+ /*Initialize the block value*/
+ pARC4_CTX->BlockIndex1 = 0;
+ pARC4_CTX->BlockIndex2 = 0;
+ for (BlockIndex = 0; BlockIndex < ARC4_KEY_BLOCK_SIZE; BlockIndex++)
+ pARC4_CTX->KeyBlock[BlockIndex] = (UINT8) BlockIndex;
+
+ /*Key schedule*/
+ for (BlockIndex = 0; BlockIndex < ARC4_KEY_BLOCK_SIZE; BlockIndex++)
+ {
+ TempValue = pARC4_CTX->KeyBlock[BlockIndex];
+ KeyIndex = BlockIndex % KeyLength;
+ SWAPIndex = (SWAPIndex + TempValue + pKey[KeyIndex]) & 0xff;
+ pARC4_CTX->KeyBlock[BlockIndex] = pARC4_CTX->KeyBlock[SWAPIndex];
+ pARC4_CTX->KeyBlock[SWAPIndex] = TempValue;
+ } /* End of for */
+
+} /* End of ARC4_INIT */
+
+
+/*
+========================================================================
+Routine Description:
+ ARC4 encryption/decryption
+
+Arguments:
+ pARC4_CTX Pointer to ARC4 CONTEXT
+ InputText Input text
+ InputTextLength The length of input text in bytes
+
+Return Value:
+ OutputBlock Return output text
+ ========================================================================
+*/
+VOID ARC4_Compute (
+ IN ARC4_CTX_STRUC *pARC4_CTX,
+ IN UINT8 InputBlock[],
+ IN UINT InputBlockSize,
+ OUT UINT8 OutputBlock[])
+{
+ UINT InputIndex = 0;
+ UINT8 TempValue = 0;
+
+ for (InputIndex = 0; InputIndex < InputBlockSize; InputIndex++)
+ {
+ pARC4_CTX->BlockIndex1 = (pARC4_CTX->BlockIndex1 + 1) & 0xff;
+ TempValue = pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1];
+ pARC4_CTX->BlockIndex2 = (pARC4_CTX->BlockIndex2 + TempValue) & 0xff;
+
+ pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1] = pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex2];
+ pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex2] = TempValue;
+
+ TempValue = (TempValue + pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1]) & 0xff;
+ OutputBlock[InputIndex] = InputBlock[InputIndex]^pARC4_CTX->KeyBlock[TempValue];
+
+ } /* End of for */
+} /* End of ARC4_Compute */
+
+
+/*
+========================================================================
+Routine Description:
+ Discard the key length
+
+Arguments:
+ pARC4_CTX Pointer to ARC4 CONTEXT
+ Length Discard the key length
+
+========================================================================
+*/
+VOID ARC4_Discard_KeyLength (
+ IN ARC4_CTX_STRUC *pARC4_CTX,
+ IN UINT Length)
+{
+ UINT Index = 0;
+ UINT8 TempValue = 0;
+
+ for (Index = 0; Index < Length; Index++)
+ {
+ pARC4_CTX->BlockIndex1 = (pARC4_CTX->BlockIndex1 + 1) & 0xff;
+ TempValue = pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1];
+ pARC4_CTX->BlockIndex2 = (pARC4_CTX->BlockIndex2 + TempValue) & 0xff;
+
+ pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1] = pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex2];
+ pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex2] = TempValue;
+ } /* End of for */
+
+} /* End of ARC4_Discard_KeyLength */
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/crypt_biginteger.c b/cleopatre/devkit/mt7601udrv/common/crypt_biginteger.c
new file mode 100644
index 0000000000..f15012f727
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/crypt_biginteger.c
@@ -0,0 +1,1116 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************/
+#include "crypt_biginteger.h"
+
+
+#ifdef __KERNEL__
+#define DEBUGPRINT(fmt, args...) printk(KERN_ERR fmt, ## args)
+#else
+#define DEBUGPRINT(fmt, args...) printf(fmt, ## args)
+#endif /* __KERNEL__ */
+
+#define UINT32_HBITS(value) (((value) >> 0x10) & 0xffff)
+#define UINT32_LBITS(value) ((value) & 0xffff)
+#define UINT32_GETBYTE(value, index) (((value) >> ((index)*8)) & 0xff)
+#define UINT64_HBITS(value) (((value) >> 0x20) & 0xffffffff)
+#define UINT64_LBITS(value) ((value) & 0xffffffff)
+
+static UINT8 WPS_DH_P_VALUE[192] =
+{
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static UINT8 WPS_DH_R_VALUE[193] =
+{
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00,
+};
+
+static UINT8 WPS_DH_X_VALUE[184] =
+{
+ 0x36, 0xf0, 0x25, 0x5d, 0xde, 0x97, 0x3d, 0xcb,
+ 0x3b, 0x39, 0x9d, 0x74, 0x7f, 0x23, 0xe3, 0x2e,
+ 0xd6, 0xfd, 0xb1, 0xf7, 0x75, 0x98, 0x33, 0x8b,
+ 0xfd, 0xf4, 0x41, 0x59, 0xc4, 0xec, 0x64, 0xdd,
+ 0xae, 0xb5, 0xf7, 0x86, 0x71, 0xcb, 0xfb, 0x22,
+ 0x10, 0x6a, 0xe6, 0x4c, 0x32, 0xc5, 0xbc, 0xe4,
+ 0xcf, 0xd4, 0xf5, 0x92, 0x0d, 0xa0, 0xeb, 0xc8,
+ 0xb0, 0x1e, 0xca, 0x92, 0x92, 0xae, 0x3d, 0xba,
+ 0x1b, 0x7a, 0x4a, 0x89, 0x9d, 0xa1, 0x81, 0x39,
+ 0x0b, 0xb3, 0xbd, 0x16, 0x59, 0xc8, 0x12, 0x94,
+ 0xf4, 0x00, 0xa3, 0x49, 0x0b, 0xf9, 0x48, 0x12,
+ 0x11, 0xc7, 0x94, 0x04, 0xa5, 0x76, 0x60, 0x5a,
+ 0x51, 0x60, 0xdb, 0xee, 0x83, 0xb4, 0xe0, 0x19,
+ 0xb6, 0xd7, 0x99, 0xae, 0x13, 0x1b, 0xa4, 0xc2,
+ 0x3d, 0xff, 0x83, 0x47, 0x5e, 0x9c, 0x40, 0xfa,
+ 0x67, 0x25, 0xb7, 0xc9, 0xe3, 0xaa, 0x2c, 0x65,
+ 0x96, 0xe9, 0xc0, 0x57, 0x02, 0xdb, 0x30, 0xa0,
+ 0x7c, 0x9a, 0xa2, 0xdc, 0x23, 0x5c, 0x52, 0x69,
+ 0xe3, 0x9d, 0x0c, 0xa9, 0xdf, 0x7a, 0xad, 0x44,
+ 0x61, 0x2a, 0xd6, 0xf8, 0x8f, 0x69, 0x69, 0x92,
+ 0x98, 0xf3, 0xca, 0xb1, 0xb5, 0x43, 0x67, 0xfb,
+ 0x0e, 0x8b, 0x93, 0xf7, 0x35, 0xdc, 0x8c, 0xd8,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+};
+
+static UINT8 WPS_DH_RRModP_VALUE[192] =
+{
+ 0xe3, 0xb3, 0x3c, 0x72, 0x59, 0x54, 0x1c, 0x01,
+ 0xee, 0x9c, 0x9a, 0x21, 0x6c, 0xc1, 0xeb, 0xd2,
+ 0xae, 0x59, 0x41, 0x04, 0x79, 0x29, 0xa1, 0xc7,
+ 0xe9, 0xc3, 0xfa, 0x02, 0xcc, 0x24, 0x56, 0xef,
+ 0x10, 0x26, 0x30, 0xfa, 0x9a, 0x36, 0xa5, 0x1f,
+ 0x57, 0xb5, 0x93, 0x48, 0x67, 0x98, 0x44, 0x60,
+ 0x0b, 0xe4, 0x96, 0x47, 0xa8, 0x7c, 0x7b, 0x37,
+ 0xf8, 0x05, 0x65, 0x64, 0x96, 0x9b, 0x7f, 0x02,
+ 0xdc, 0x54, 0x1a, 0x4e, 0xd4, 0x05, 0x3f, 0x54,
+ 0xd6, 0x2a, 0x0e, 0xea, 0xb2, 0x70, 0x52, 0x1b,
+ 0x22, 0xc2, 0x96, 0xe9, 0xd4, 0x6f, 0xec, 0x23,
+ 0x8e, 0x1a, 0xbd, 0x78, 0x02, 0x23, 0xb7, 0x6b,
+ 0xb8, 0xfe, 0x61, 0x21, 0x19, 0x6b, 0x7e, 0x88,
+ 0x1c, 0x72, 0x9c, 0x7e, 0x04, 0xb9, 0xf7, 0x96,
+ 0x07, 0xcd, 0x0a, 0x62, 0x8e, 0x43, 0x41, 0x30,
+ 0x04, 0xa5, 0x41, 0xff, 0x93, 0xae, 0x1c, 0xeb,
+ 0xb0, 0x04, 0xa7, 0x50, 0xdb, 0x10, 0x2d, 0x39,
+ 0xb9, 0x05, 0x2b, 0xb4, 0x7a, 0x58, 0xf1, 0x70,
+ 0x7e, 0x8c, 0xd2, 0xac, 0x98, 0xb5, 0xfb, 0x62,
+ 0x8f, 0x23, 0x31, 0xb1, 0x3b, 0x01, 0xe0, 0x18,
+ 0xf4, 0x66, 0xee, 0x5f, 0xbc, 0xd4, 0x9d, 0x68,
+ 0xd0, 0xab, 0x92, 0xe1, 0x83, 0x97, 0xf2, 0x45,
+ 0x8e, 0x0e, 0x3e, 0x21, 0x67, 0x47, 0x8c, 0x73,
+ 0xf1, 0x15, 0xd2, 0x7d, 0x32, 0xc6, 0x95, 0xe0,
+};
+
+static UINT8 Value_0[1] = {0x00};
+static UINT8 Value_1[1] = {0x01};
+static PBIG_INTEGER pBI_U = NULL, pBI_S = NULL, pBI_O = NULL;
+static UINT Bits_Of_R = 0;
+
+
+VOID BigInteger_Print (
+ IN PBIG_INTEGER pBI)
+{
+ int i = 0, j = 0;
+
+ if ((pBI == NULL) || (pBI->pIntegerArray == NULL))
+ return;
+
+ if (strlen(pBI->Name) != 0)
+ DEBUGPRINT("Name=%s\n", pBI->Name);
+ DEBUGPRINT("AllocSize=%d, ArrayLength=%d, IntegerLength=%d, Signed=%d\n", pBI->AllocSize, pBI->ArrayLength, pBI->IntegerLength, pBI->Signed);
+ for (i = (pBI->ArrayLength - 1), j = 0;i >=0;i--,j++) {
+ DEBUGPRINT("%08x, ", pBI->pIntegerArray[i]);
+ if ((j%8) == 7)
+ DEBUGPRINT("\n");
+ } /* End od for */
+ DEBUGPRINT("\n\n");
+} /* End of BigInteger_Print */
+
+
+VOID BigInteger_Init (
+ INOUT PBIG_INTEGER *pBI)
+{
+ if (*pBI != NULL)
+ BigInteger_Free(pBI);
+
+ os_alloc_mem(NULL, (UCHAR **)pBI, sizeof(BIG_INTEGER));
+/* if ((*pBI = (PBIG_INTEGER) kmalloc(sizeof(BIG_INTEGER), GFP_ATOMIC)) == NULL) { */
+ if (*pBI == NULL) {
+ DEBUGPRINT("BigInteger_Init: allocate %d bytes memory failure.\n", (sizeof(BIG_INTEGER)));
+ return;
+ } /* End of if */
+
+ NdisZeroMemory(*pBI, sizeof(BIG_INTEGER));
+ (*pBI)->pIntegerArray = NULL;
+ (*pBI)->Signed = 1;
+} /* End of BigInteger_Init */
+
+
+VOID BigInteger_Free_AllocSize (
+ IN PBIG_INTEGER *pBI)
+{
+ if ((*pBI != NULL) && ((*pBI)->pIntegerArray != NULL)) {
+/* kfree((*pBI)->pIntegerArray); */
+ os_free_mem(NULL, (*pBI)->pIntegerArray);
+ NdisZeroMemory(*pBI, sizeof(BIG_INTEGER));
+ (*pBI)->pIntegerArray = NULL;
+ (*pBI)->Signed = 1;
+ } /* End of if */
+} /* End of BigInteger_Free_AllocSize */
+
+
+VOID BigInteger_Free (
+ IN PBIG_INTEGER *pBI)
+{
+ if (*pBI != NULL) {
+ BigInteger_Free_AllocSize(pBI);
+/* kfree(*pBI); */
+ os_free_mem(NULL, *pBI);
+ } /* End of if */
+
+ *pBI = NULL;
+} /* End of BigInteger_Free */
+
+
+VOID BigInteger_AllocSize (
+ IN PBIG_INTEGER *pBI,
+ IN INT Length)
+{
+ UINT ArrayLength = 0;
+
+ if (Length <= 0)
+ return;
+
+ if (*pBI == NULL)
+ BigInteger_Init(pBI);
+
+ /* Caculate array size */
+ ArrayLength = Length >> 0x2;
+ if ((Length & 0x3) != 0)
+ ArrayLength++;
+
+ if (((*pBI)->pIntegerArray != NULL) && ((*pBI)->AllocSize < (sizeof(UINT32)*ArrayLength)))
+ BigInteger_Free_AllocSize(pBI);
+
+ if ((*pBI)->pIntegerArray == NULL) {
+ os_alloc_mem(NULL, (UCHAR **)&((*pBI)->pIntegerArray), sizeof(UINT32)*ArrayLength);
+/* if (((*pBI)->pIntegerArray = (UINT32 *) kmalloc(sizeof(UINT32)*ArrayLength, GFP_ATOMIC)) == NULL) { */
+ if ((*pBI)->pIntegerArray == NULL) {
+ DEBUGPRINT("BigInteger_AllocSize: allocate %d bytes memory failure.\n", (sizeof(UINT32)*ArrayLength));
+ return;
+ } /* End of if */
+ (*pBI)->AllocSize = sizeof(UINT32)*ArrayLength;
+ } /* End of if */
+
+ NdisZeroMemory((*pBI)->pIntegerArray, (*pBI)->AllocSize);
+ (*pBI)->ArrayLength = ArrayLength;
+ (*pBI)->IntegerLength = Length;
+} /* End of BigInteger_AllocSize */
+
+
+VOID BigInteger_ClearHighBits (
+ IN PBIG_INTEGER pBI)
+{
+ INT BIArrayIndex, ShiftIndex = 0;
+ UINT8 value;
+
+ if ((pBI == NULL) || (pBI->pIntegerArray == NULL))
+ return;
+
+ BIArrayIndex = pBI->ArrayLength - 1;
+ while ((BIArrayIndex >= 0) && (pBI->pIntegerArray[BIArrayIndex] == 0))
+ BIArrayIndex--;
+
+ if (BIArrayIndex >= 0) {
+ value = 0;
+ ShiftIndex = 4;
+ while (value == 0) {
+ ShiftIndex--;
+ value = UINT32_GETBYTE(pBI->pIntegerArray[BIArrayIndex], ShiftIndex);
+ } /* End of while */
+ } /* End of if */
+
+ if (BIArrayIndex < 0) {
+ pBI->IntegerLength = 1;
+ pBI->ArrayLength = 1;
+ pBI->Signed = 1;
+ } else {
+ pBI->IntegerLength = (BIArrayIndex*4) + ShiftIndex + 1;
+ pBI->ArrayLength = BIArrayIndex + 1;
+ } /* End of if */
+} /* End of BigInteger_ClearHighBits */
+
+
+VOID BigInteger_BI2Bin (
+ IN PBIG_INTEGER pBI,
+ OUT UINT8 *pValue,
+ OUT UINT *Length)
+{
+ INT ValueIndex, BIArrayIndex, ShiftIndex;
+ UINT32 Number;
+
+ if (pBI == NULL) {
+ DEBUGPRINT("BigInteger_BI2Bin: pBI is NUll\n");
+ *Length = 0;
+ return;
+ } /* End of if */
+
+ if (*Length < (sizeof(UINT8) * pBI->IntegerLength)) {
+ DEBUGPRINT("BigInteger_BI2Bin: length(%d) is not enough.\n", *Length);
+ *Length = 0;
+ return;
+ } /* End of if */
+
+ if (pBI->pIntegerArray == NULL) {
+ *Length = 0;
+ return;
+ } /* End of if */
+
+ BigInteger_ClearHighBits(pBI);
+ if ((ShiftIndex = pBI->IntegerLength & 0x3) == 0)
+ ShiftIndex = 4;
+ BIArrayIndex = pBI->ArrayLength - 1;
+ ValueIndex = 0;
+
+ Number = pBI->pIntegerArray[BIArrayIndex];
+ while (ValueIndex < pBI->IntegerLength)
+ {
+ pValue[ValueIndex++] = (UINT8) UINT32_GETBYTE(Number, ShiftIndex - 1);
+ if ((--ShiftIndex) == 0) {
+ ShiftIndex = 4;
+ BIArrayIndex--;
+ Number = pBI->pIntegerArray[BIArrayIndex];
+ } /* End of if */
+ } /* End of while */
+ *Length = pBI->IntegerLength;
+} /* End of BigInteger_BI2Bin */
+
+
+VOID BigInteger_Bin2BI (
+ IN UINT8 *pValue,
+ IN UINT Length,
+ OUT PBIG_INTEGER *pBI)
+{
+ INT ValueIndex, BIArrayIndex, ShiftIndex;
+ UINT32 Number;
+
+ BigInteger_AllocSize(pBI, Length);
+
+ if ((*pBI)->pIntegerArray != NULL) {
+ Number = 0;
+ if ((ShiftIndex = Length & 0x3) == 0)
+ ShiftIndex = 4;
+ BIArrayIndex = (*pBI)->ArrayLength - 1;
+ ValueIndex = 0;
+ while (ValueIndex < Length)
+ {
+ Number = (Number << 8) | (UINT8) pValue[ValueIndex++];
+ if ((--ShiftIndex) == 0) {
+ (*pBI)->pIntegerArray[BIArrayIndex] = Number;
+ ShiftIndex = 4;
+ BIArrayIndex--;
+ Number = 0;
+ } /* End of if */
+ } /* End of while */
+ } /* End of if */
+} /* End of BigInteger_Bin2BI */
+
+
+/* Calculate the bits of BigInteger, the highest bit is 1 */
+VOID BigInteger_BitsOfBI (
+ IN PBIG_INTEGER pBI,
+ OUT UINT *Bits_Of_P)
+{
+ UINT32 Number, Index;
+
+ Number = pBI->pIntegerArray[pBI->ArrayLength - 1];
+ Index = 0;
+ while ((!(Number & 0x80000000)) && (Index < 32)) {
+ Number <<= 1;
+ Index++;
+ } /* End of while */
+ *Bits_Of_P = (pBI->ArrayLength*sizeof(UINT32)) - Index;
+} /* End of BigInteger_BitsOfBN */
+
+
+INT BigInteger_GetBitValue (
+ IN PBIG_INTEGER pBI,
+ IN UINT Index)
+{
+ UINT Array = 0;
+ UINT Shift = 0;
+
+ if (Index > 0) {
+ Array = (Index - 1) >> 0x5;
+ Shift = (Index - 1) & 0x1F;
+ }
+ if (Array > pBI->ArrayLength)
+ return 0;
+
+ return ((pBI->pIntegerArray[Array] >> Shift) & 0x1);
+} /* End of BigInteger_GetBitValue */
+
+
+UINT8 BigInteger_GetByteValue (
+ IN PBIG_INTEGER pBI,
+ IN UINT Index)
+{
+ UINT Array = 0;
+ UINT Shift = 0;
+
+ if (Index > 0) {
+ Array = (Index - 1) >> 0x2;
+ Shift = (Index - 1) & 0x3;
+ }
+ if ((Array > pBI->ArrayLength) || (Index > pBI->IntegerLength))
+ return 0;
+
+
+ return (UINT8) UINT32_GETBYTE(pBI->pIntegerArray[Array], Shift - 1);
+} /* End of BigInteger_GetByteValue */
+
+
+VOID BigInteger_Copy (
+ IN PBIG_INTEGER pBI_Copied,
+ OUT PBIG_INTEGER *pBI_Result)
+{
+ BigInteger_AllocSize(pBI_Result, pBI_Copied->IntegerLength);
+ NdisCopyMemory((*pBI_Result)->pIntegerArray, pBI_Copied->pIntegerArray, (sizeof(UINT32)*(*pBI_Result)->ArrayLength));
+ (*pBI_Result)->ArrayLength = pBI_Copied->ArrayLength;
+ (*pBI_Result)->IntegerLength = pBI_Copied->IntegerLength;
+ (*pBI_Result)->Signed = pBI_Copied->Signed;
+} /* End of BigInteger_Copy */
+
+
+INT BigInteger_UnsignedCompare (
+ IN PBIG_INTEGER pFirstOperand,
+ IN PBIG_INTEGER pSecondOperand)
+{
+ INT BIArrayIndex;
+
+ if (pFirstOperand->IntegerLength > pSecondOperand->IntegerLength)
+ return 1;
+
+ if (pFirstOperand->IntegerLength < pSecondOperand->IntegerLength)
+ return -1;
+
+ if (pFirstOperand->IntegerLength == pSecondOperand->IntegerLength) {
+ for(BIArrayIndex = (pFirstOperand->ArrayLength - 1);BIArrayIndex >= 0 ; BIArrayIndex--)
+ {
+ if (pFirstOperand->pIntegerArray[BIArrayIndex] > pSecondOperand->pIntegerArray[BIArrayIndex])
+ return 1;
+ else if (pFirstOperand->pIntegerArray[BIArrayIndex] < pSecondOperand->pIntegerArray[BIArrayIndex])
+ return -1;
+ } /* End of for */
+ } /* End of if */
+
+ return 0;
+} /* End of BigInteger_Compare */
+
+
+VOID BigInteger_Add (
+ IN PBIG_INTEGER pFirstOperand,
+ IN PBIG_INTEGER pSecondOperand,
+ OUT PBIG_INTEGER *pBI_Result)
+{
+ INT CompareResult;
+ UINT32 BIArrayIndex;
+ UINT64 Sum, Carry;
+ PBIG_INTEGER pTempBI = NULL;
+
+ if ((pFirstOperand == NULL) || (pFirstOperand->pIntegerArray == NULL)
+ || (pSecondOperand == NULL) || (pSecondOperand->pIntegerArray == NULL)) {
+ DEBUGPRINT("BigInteger_Add: first or second operand is NULL.\n");
+ return;
+ } /* End of if */
+
+ if (*pBI_Result == NULL)
+ BigInteger_Init(pBI_Result);
+
+ CompareResult = BigInteger_UnsignedCompare(pFirstOperand, pSecondOperand);
+ if ((CompareResult == 0) & ((pFirstOperand->Signed * pSecondOperand->Signed) < 0)) {
+ BigInteger_AllocSize(pBI_Result, 1);
+ return ;
+ } /* End of if */
+
+ /*
+ * Singed table
+ * A + B || A > B || A < B
+ * ------------------------
+ * + + || + || +
+ * + - || + || -
+ * - + || - || +
+ * - - || - || -
+ */
+ if ((pFirstOperand->Signed * pSecondOperand->Signed) > 0) {
+ if (pFirstOperand->IntegerLength > pSecondOperand->IntegerLength) {
+ BigInteger_AllocSize(pBI_Result, pFirstOperand->IntegerLength + 1);
+ } else {
+ BigInteger_AllocSize(pBI_Result, pSecondOperand->IntegerLength + 1);
+ } /* End of if */
+
+ Carry = 0;
+ for (BIArrayIndex=0; BIArrayIndex < (*pBI_Result)->ArrayLength; BIArrayIndex++)
+ {
+
+ Sum = 0;
+ if (BIArrayIndex < pFirstOperand->ArrayLength)
+ Sum += (UINT64) pFirstOperand->pIntegerArray[BIArrayIndex];
+
+ if (BIArrayIndex < pSecondOperand->ArrayLength)
+ Sum += (UINT64) pSecondOperand->pIntegerArray[BIArrayIndex];
+
+ Sum += Carry;
+ Carry = Sum >> 32;
+ (*pBI_Result)->pIntegerArray[BIArrayIndex] = (UINT32) (Sum & 0xffffffffUL);
+ } /* End of for */
+ (*pBI_Result)->Signed = pFirstOperand->Signed;
+ BigInteger_ClearHighBits(*pBI_Result);
+ } else {
+ if ((pFirstOperand->Signed == 1) & (pSecondOperand->Signed == -1)) {
+ BigInteger_Copy(pSecondOperand, &pTempBI);
+ pTempBI->Signed = 1;
+ BigInteger_Sub(pFirstOperand, pTempBI, pBI_Result);
+ } else if ((pFirstOperand->Signed == -1) & (pSecondOperand->Signed == 1)) {
+ BigInteger_Copy(pFirstOperand, &pTempBI);
+ pTempBI->Signed = 1;
+ BigInteger_Sub(pSecondOperand, pTempBI, pBI_Result);
+ } /* End of if */
+ } /* End of if */
+
+ BigInteger_Free(&pTempBI);
+} /* End of BigInteger_Add */
+
+
+VOID BigInteger_Sub (
+ IN PBIG_INTEGER pFirstOperand,
+ IN PBIG_INTEGER pSecondOperand,
+ OUT PBIG_INTEGER *pBI_Result)
+{
+ INT CompareResult;
+ UINT32 BIArrayIndex, Carry;
+ PBIG_INTEGER pTempBI = NULL, pTempBI2 = NULL;
+
+ if ((pFirstOperand == NULL) || (pFirstOperand->pIntegerArray == NULL)
+ || (pSecondOperand == NULL) || (pSecondOperand->pIntegerArray == NULL)) {
+ DEBUGPRINT("BigInteger_Sub: first or second operand is NULL.\n");
+ return;
+ } /* End of if */
+
+ if (*pBI_Result == NULL)
+ BigInteger_Init(pBI_Result);
+
+ CompareResult = BigInteger_UnsignedCompare(pFirstOperand, pSecondOperand);
+ if ((CompareResult == 0) & ((pFirstOperand->Signed * pSecondOperand->Signed) > 0)) {
+ BigInteger_AllocSize(pBI_Result, 1);
+ return ;
+ } /* End of if */
+
+ BigInteger_Init(&pTempBI);
+ BigInteger_Init(&pTempBI2);
+
+ /*
+ * Singed table
+ * A - B || A > B || A < B
+ * ------------------------
+ * + + || + || -
+ * + - || + || +
+ * - + || - || -
+ * - - || - || +
+ */
+ if ((pFirstOperand->Signed * pSecondOperand->Signed) > 0) {
+ if (CompareResult == 1) {
+ BigInteger_Copy(pFirstOperand, &pTempBI);
+ BigInteger_Copy(pSecondOperand, &pTempBI2);
+ } else if (CompareResult == -1) {
+ BigInteger_Copy(pSecondOperand, &pTempBI);
+ BigInteger_Copy(pFirstOperand, &pTempBI2);
+ } /* End of if */
+
+ BigInteger_Copy(pTempBI, pBI_Result);
+ Carry = 0;
+ for (BIArrayIndex=0; BIArrayIndex < (*pBI_Result)->ArrayLength; BIArrayIndex++)
+ {
+ if (BIArrayIndex < pTempBI2->ArrayLength) {
+ if ((*pBI_Result)->pIntegerArray[BIArrayIndex] >= (pTempBI2->pIntegerArray[BIArrayIndex] - Carry)) {
+ (*pBI_Result)->pIntegerArray[BIArrayIndex] = (*pBI_Result)->pIntegerArray[BIArrayIndex] - pTempBI2->pIntegerArray[BIArrayIndex] - Carry;
+ Carry = 0;
+ } else {
+ (*pBI_Result)->pIntegerArray[BIArrayIndex] = 0xffffffffUL - pTempBI2->pIntegerArray[BIArrayIndex] - Carry + (*pBI_Result)->pIntegerArray[BIArrayIndex] + 1;
+ Carry = 1;
+ } /* End of if */
+ } else {
+ if ((*pBI_Result)->pIntegerArray[BIArrayIndex] >= Carry) {
+ (*pBI_Result)->pIntegerArray[BIArrayIndex] -= Carry;
+ Carry = 0;
+ } else {
+ (*pBI_Result)->pIntegerArray[BIArrayIndex] = 0xffffffffUL - Carry;
+ Carry = 1;
+ } /* End of if */
+ } /* End of if */
+ } /* End of for */
+
+ if (((pFirstOperand->Signed == 1) & (pSecondOperand->Signed == 1) & (CompareResult == -1))
+ || ((pFirstOperand->Signed == -1) & (pSecondOperand->Signed == -1) & (CompareResult == 1)))
+ (*pBI_Result)->Signed = -1;
+
+ BigInteger_ClearHighBits(*pBI_Result);
+ } else {
+ if ((pFirstOperand->Signed == 1) & (pSecondOperand->Signed == -1)) {
+ BigInteger_Copy(pSecondOperand, &pTempBI);
+ pTempBI->Signed = 1;
+ BigInteger_Add(pFirstOperand, pTempBI, pBI_Result);
+ } else if ((pFirstOperand->Signed == -1) & (pSecondOperand->Signed == 1)) {
+ BigInteger_Copy(pFirstOperand, &pTempBI);
+ pTempBI->Signed = 1;
+ BigInteger_Add(pTempBI, pSecondOperand, pBI_Result);
+ (*pBI_Result)->Signed = -1;
+ } /* End of if */
+ } /* End of if */
+
+ BigInteger_Free(&pTempBI);
+ BigInteger_Free(&pTempBI2);
+} /* End of BigInteger_Sub */
+
+
+VOID BigInteger_Mul (
+ IN PBIG_INTEGER pFirstOperand,
+ IN PBIG_INTEGER pSecondOperand,
+ OUT PBIG_INTEGER *pBI_Result)
+{
+
+ UINT32 BIFirstIndex, BISecondIndex;
+ UINT64 FirstValue, SecondValue, Sum, Carry;
+
+ if ((pFirstOperand == NULL) || (pFirstOperand->pIntegerArray == NULL)
+ || (pSecondOperand == NULL) || (pSecondOperand->pIntegerArray == NULL)) {
+ DEBUGPRINT("BigInteger_Mul: first or second operand is NULL.\n");
+ return;
+ } /* End of if */
+
+ /* The first or second operand is zero */
+ if (((pFirstOperand->IntegerLength == 1) && (pFirstOperand->pIntegerArray[0] == 0))
+ ||((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 0))) {
+ BigInteger_AllocSize(pBI_Result, 1);
+ goto output;
+ } /* End of if */
+
+ /* The first or second operand is one */
+ if ((pFirstOperand->IntegerLength == 1) && (pFirstOperand->pIntegerArray[0] == 1)) {
+ BigInteger_Copy(pSecondOperand, pBI_Result);
+ goto output;
+ } /* End of if */
+ if ((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 1)) {
+ BigInteger_Copy(pFirstOperand, pBI_Result);
+ goto output;
+ } /* End of if */
+
+ BigInteger_AllocSize(pBI_Result, pFirstOperand->IntegerLength + pSecondOperand->IntegerLength);
+
+ for (BIFirstIndex=0; BIFirstIndex < pFirstOperand->ArrayLength; BIFirstIndex++)
+ {
+ Carry = 0;
+ FirstValue = (UINT64) pFirstOperand->pIntegerArray[BIFirstIndex];
+ if (FirstValue == 0) {
+ continue;
+ } else {
+ for (BISecondIndex=0; BISecondIndex < pSecondOperand->ArrayLength; BISecondIndex++)
+ {
+ SecondValue = ((UINT64) pSecondOperand->pIntegerArray[BISecondIndex])*FirstValue;
+ Sum = (UINT64) ((*pBI_Result)->pIntegerArray[BIFirstIndex + BISecondIndex] + SecondValue + Carry);
+ Carry = Sum >> 32;
+ (*pBI_Result)->pIntegerArray[BIFirstIndex + BISecondIndex] = (UINT32) (Sum & 0xffffffffUL);
+ } /* End of for */
+ while (Carry != 0) {
+ Sum = (UINT64) (*pBI_Result)->pIntegerArray[BIFirstIndex + BISecondIndex];
+ Sum += Carry;
+
+ Carry = Sum >> 32;
+ (*pBI_Result)->pIntegerArray[BIFirstIndex + BISecondIndex] = (UINT32) (Sum & 0xffffffffUL);
+ BISecondIndex++;
+ } /* End of while */
+ } /* End of if */
+ } /* End of for */
+
+output:
+ (*pBI_Result)->Signed = pFirstOperand->Signed * pSecondOperand->Signed;
+ BigInteger_ClearHighBits(*pBI_Result);
+} /* End of BigInteger_Mul */
+
+
+VOID BigInteger_Square (
+ IN PBIG_INTEGER pBI,
+ OUT PBIG_INTEGER *pBI_Result)
+{
+ INT BIFirstIndex, BISecondIndex;
+ UINT32 HBITS_Value, LBITS_Value, Temp1_Value, Temp2_Value, Carry32;
+ UINT32 *Point_Of_S, *Point_Of_Result, *Point_Of_BI;
+ UINT64 Result64_1, Result64_2, Carry64, TempValue64;
+
+ if ((pBI == NULL) || (pBI->pIntegerArray == NULL)) {
+ DEBUGPRINT("\tBigInteger_Square: the operand is NULL.\n");
+ return;
+ } /* End of if */
+
+ /* The operand is zero */
+ if ((pBI->IntegerLength == 1) && (pBI->pIntegerArray[0] == 0)) {
+ BigInteger_AllocSize(pBI_Result, 1);
+ goto output;
+ } /* End of if */
+
+ BigInteger_AllocSize(pBI_Result, (pBI->IntegerLength*2) + 20);
+ BigInteger_AllocSize(&pBI_S, (pBI->IntegerLength*2) + 20);
+ BigInteger_AllocSize(&pBI_O, (pBI->IntegerLength*2) + 20);
+
+ /*
+ * Input: pBI = {a_0, a_1, a_2, a_3, ..., a_n}
+ * Step1. calculate a_0^2, a_1^2, a_2^2, a_3^2 ... a_n^2
+ */
+ Point_Of_S = pBI_S->pIntegerArray;
+ for (BIFirstIndex=0; BIFirstIndex < pBI->ArrayLength; BIFirstIndex++)
+ {
+ HBITS_Value = UINT32_HBITS(pBI->pIntegerArray[BIFirstIndex]);
+ LBITS_Value = UINT32_LBITS(pBI->pIntegerArray[BIFirstIndex]);
+ Temp1_Value = HBITS_Value*LBITS_Value;
+ Temp2_Value = (Temp1_Value & 0x7fff) << 0x11;
+ Point_Of_S[0] = (LBITS_Value*LBITS_Value) + Temp2_Value;
+ Point_Of_S[1] = (HBITS_Value*HBITS_Value) + ((Temp1_Value >> 0xf) & 0x1ffff);
+ if (Point_Of_S[0] < Temp2_Value)
+ Point_Of_S[1] += 1;
+
+ Point_Of_S += 2;
+ } /* End of for */
+
+ /*
+ * Step2. calculate a_0*{a_1, a_2, a_3, a_4, ..., a_n}
+ */
+ Point_Of_BI = pBI->pIntegerArray;
+ Point_Of_Result = (*pBI_Result)->pIntegerArray;
+ Point_Of_Result[0] = 0;
+ TempValue64 = (UINT64) Point_Of_BI[0];
+ Point_Of_Result++;
+ Carry64 = 0;
+ for (BIFirstIndex=1; BIFirstIndex < pBI->ArrayLength; BIFirstIndex++)
+ {
+ Result64_1 = (UINT64) Point_Of_BI[BIFirstIndex]*TempValue64;
+ Result64_1 += Carry64;
+ Carry64 = (Result64_1 >> 32);
+ Point_Of_Result[0] = (UINT32) (Result64_1 & 0xffffffffUL);
+ Point_Of_Result++;
+ } /* End of for */
+ if (Carry64 > 0)
+ Point_Of_Result[0] = (UINT32) (Carry64 & 0xffffffffUL);
+
+ /*
+ * Step3. calculate
+ * a_1*{a_2, a_3, a_4, ..., a_n}
+ * a_2*{a_3, a_4, a_5, ..., a_n}
+ * a_3*{a_4, a_5, a_6, ..., a_n}
+ * a_4*{a_5, a_6, a_7, ..., a_n}
+ * ...
+ * a_n-1*{a_n}
+ */
+ Point_Of_BI = pBI->pIntegerArray;
+ for (BIFirstIndex=1; BIFirstIndex < (pBI->ArrayLength - 1); BIFirstIndex++)
+ {
+ Point_Of_Result = (*pBI_Result)->pIntegerArray;
+ Point_Of_Result += (BIFirstIndex*2) + 1;
+ TempValue64 = (UINT64) Point_Of_BI[BIFirstIndex];
+ Carry64 = 0;
+ for (BISecondIndex=(BIFirstIndex + 1); BISecondIndex < pBI->ArrayLength; BISecondIndex++)
+ {
+ Result64_1 = ((UINT64) Point_Of_Result[0]) + Carry64;
+ Result64_2 = (UINT64) Point_Of_BI[BISecondIndex]*TempValue64;
+ Carry64 = (Result64_1 >> 32);
+ Result64_1 = (Result64_1 & 0xffffffffUL);
+ Result64_1 = Result64_1 + Result64_2;
+ Carry64 += (Result64_1 >> 32);
+ Point_Of_Result[0] = (UINT32) (Result64_1 & 0xffffffffUL);
+ Point_Of_Result++;
+ } /* End of for */
+ if (Carry64 > 0)
+ Point_Of_Result[0] += (UINT32) (Carry64 & 0xffffffffUL);
+ } /* End of for */
+
+ BigInteger_ClearHighBits(*pBI_Result);
+ BigInteger_Copy(*pBI_Result, &pBI_O);
+
+ Carry32 = 0;
+ for (BIFirstIndex=0; BIFirstIndex < pBI_O->ArrayLength; BIFirstIndex++) {
+ pBI_O->pIntegerArray[BIFirstIndex] = (pBI_O->pIntegerArray[BIFirstIndex] << 1) | Carry32;
+ if (pBI_O->pIntegerArray[BIFirstIndex] < (*pBI_Result)->pIntegerArray[BIFirstIndex])
+ Carry32 = 1;
+ else
+ Carry32 = 0;
+ } /* End of for */
+ pBI_O->pIntegerArray[BIFirstIndex] = Carry32;
+ pBI_O->IntegerLength++;
+ pBI_O->ArrayLength++;
+ BigInteger_ClearHighBits(pBI_O);
+
+ BigInteger_Add(pBI_O, pBI_S, pBI_Result);
+output:
+ (*pBI_Result)->Signed = 1;
+ BigInteger_ClearHighBits(*pBI_Result);
+} /* End of BigInteger_Square */
+
+
+VOID BigInteger_Div (
+ IN PBIG_INTEGER pFirstOperand,
+ IN PBIG_INTEGER pSecondOperand,
+ OUT PBIG_INTEGER *pBI_Result,
+ OUT PBIG_INTEGER *pBI_Remainder)
+{
+ INT CompareResult;
+ INT Index, MulIndex, ComputeSize;
+ UINT32 MulStart;
+ UINT AllocLength, ArrayIndex, ShiftIndex;
+ PBIG_INTEGER pTempBI = NULL, pTempBI2 = NULL, pMulBI = NULL;
+ UINT8 SecondHighByte;
+
+ if ((pFirstOperand == NULL) || (pFirstOperand->pIntegerArray == NULL)
+ || (pSecondOperand == NULL) || (pSecondOperand->pIntegerArray == NULL)) {
+ DEBUGPRINT("BigInteger_Div: first or second operand is NULL.\n");
+ return;
+ } /* End of if */
+
+ /* The second operand is zero */
+ if ((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 0)) {
+ DEBUGPRINT("BigInteger_Div: second operand is zero.\n");
+ return;
+ } /* End of if */
+
+ if (*pBI_Result == NULL)
+ BigInteger_Init(pBI_Result);
+ if (*pBI_Remainder == NULL)
+ BigInteger_Init(pBI_Remainder);
+
+ /* The second operand is one */
+ if ((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 1)) {
+ BigInteger_Copy(pFirstOperand, pBI_Result);
+ BigInteger_Bin2BI(Value_0, 1, pBI_Remainder);
+ goto output;
+ } /* End of if */
+
+ CompareResult = BigInteger_UnsignedCompare(pFirstOperand, pSecondOperand);
+ if (CompareResult == 0) {
+ BigInteger_Bin2BI(Value_1, 1, pBI_Result);
+ BigInteger_Bin2BI(Value_0, 1, pBI_Remainder);
+ goto output;
+ } else if (CompareResult == -1) {
+ BigInteger_Bin2BI(Value_0, 1, pBI_Result);
+ BigInteger_Copy(pFirstOperand, pBI_Remainder);
+ goto output;
+ } /* End of if */
+ BigInteger_AllocSize(pBI_Result, pFirstOperand->IntegerLength - pSecondOperand->IntegerLength + 1);
+ BigInteger_AllocSize(pBI_Remainder, pSecondOperand->IntegerLength);
+
+ AllocLength = (UINT) (pFirstOperand->IntegerLength << 1);
+ BigInteger_AllocSize(&pTempBI, AllocLength);
+ BigInteger_AllocSize(&pTempBI2, AllocLength);
+ BigInteger_AllocSize(&pMulBI, AllocLength);
+
+ BigInteger_Copy(pFirstOperand, pBI_Remainder);
+ SecondHighByte = BigInteger_GetByteValue(pSecondOperand, pSecondOperand->IntegerLength);
+ ComputeSize = (INT) pFirstOperand->IntegerLength - pSecondOperand->IntegerLength + 1;
+ for (Index = (INT) ComputeSize;Index >= 0;Index--) {
+ if (BigInteger_UnsignedCompare(*pBI_Remainder, pSecondOperand) == -1)
+ break;
+
+ if (((pSecondOperand->IntegerLength + Index) - (*pBI_Remainder)->IntegerLength) <= 1) {
+ BigInteger_AllocSize(&pMulBI, Index + 1);
+ ArrayIndex = 0;
+ if (Index > 0)
+ ArrayIndex = (UINT) (Index - 1) >> 2 ;
+ ShiftIndex = (Index & 0x03);
+ if (ShiftIndex == 0)
+ ShiftIndex = 4;
+ ShiftIndex--;
+ MulStart = 0;
+ MulStart = (BigInteger_GetByteValue((*pBI_Remainder), pFirstOperand->IntegerLength + Index - ComputeSize + 1) & 0xFF) << 8;
+ MulStart = MulStart | (BigInteger_GetByteValue((*pBI_Remainder), pFirstOperand->IntegerLength + Index - ComputeSize) & 0xFF);
+ if (MulStart < (UINT32) SecondHighByte)
+ continue;
+
+ MulStart = MulStart / (UINT32) SecondHighByte;
+
+ if (MulStart > 0xFF)
+ MulStart = 0x100;
+
+ for (MulIndex = (INT) MulStart;MulIndex <= 0x101;MulIndex++) { /* 0xFFFF / 0xFF = 0x101 */
+ if ((MulIndex > 0xFF) && (ShiftIndex == 3))
+ pMulBI->pIntegerArray[ArrayIndex + 1] = 0x01;
+ pMulBI->pIntegerArray[ArrayIndex] = ((UINT) MulIndex << (8*ShiftIndex));
+ BigInteger_Mul(pSecondOperand, pMulBI , &pTempBI);
+ CompareResult = BigInteger_UnsignedCompare(*pBI_Remainder, pTempBI);
+ if (CompareResult < 1) {
+ if (MulIndex > 1) {
+ if (CompareResult != 0) {
+ if ((MulIndex == 0x100) && (ShiftIndex == 3))
+ pMulBI->pIntegerArray[ArrayIndex + 1] = 0;
+ pMulBI->pIntegerArray[ArrayIndex] = ((UINT) (MulIndex - 1) << (8*ShiftIndex));
+ } /* End of if */
+
+ BigInteger_Mul(pSecondOperand, pMulBI, &pTempBI);
+ BigInteger_Sub(*pBI_Remainder, pTempBI, &pTempBI2);
+ BigInteger_Copy(pTempBI2, pBI_Remainder);
+ BigInteger_Add(*pBI_Result, pMulBI, &pTempBI2);
+ BigInteger_Copy(pTempBI2, pBI_Result);
+ } /* End of if */
+ break;
+ } /* End of if */
+
+ if ((MulIndex >= 0x100) && (ShiftIndex == 3))
+ pMulBI->pIntegerArray[ArrayIndex++] = 0;
+ pMulBI->pIntegerArray[ArrayIndex] = 0;
+ } /* End of for */
+ } /* End of if */
+ } /* End of for */
+
+ BigInteger_Free(&pTempBI);
+ BigInteger_Free(&pTempBI2);
+ BigInteger_Free(&pMulBI);
+output:
+ (*pBI_Result)->Signed = pFirstOperand->Signed * pSecondOperand->Signed;
+ (*pBI_Remainder)->Signed = pFirstOperand->Signed * pSecondOperand->Signed;
+ BigInteger_ClearHighBits(*pBI_Result);
+ BigInteger_ClearHighBits(*pBI_Remainder);
+} /* End of BigInteger_Div */
+
+
+VOID BigInteger_Montgomery_Reduction (
+ IN PBIG_INTEGER pBI_A,
+ IN PBIG_INTEGER pBI_P,
+ IN PBIG_INTEGER pBI_R,
+ OUT PBIG_INTEGER *pBI_Result)
+{
+ UINT32 *Point_P, *Point_Result;
+ UINT32 LoopCount;
+ UINT64 Result64_1, Result64_2, Carry64, TempValue64;
+ INT FirstLoop, SecondLoop;
+
+ BigInteger_AllocSize(pBI_Result, pBI_A->IntegerLength+ pBI_P->IntegerLength + 20);
+ BigInteger_Copy(pBI_A, pBI_Result);
+
+ Point_P = pBI_P->pIntegerArray;
+ Point_Result = (*pBI_Result)->pIntegerArray;
+
+ LoopCount = Bits_Of_R >> 0x5;
+ for (FirstLoop = 0;FirstLoop < LoopCount;FirstLoop++) {
+ Carry64 = 0;
+ TempValue64 = (UINT64) Point_Result[0];
+ for (SecondLoop = 0;SecondLoop < pBI_P->ArrayLength;SecondLoop++) {
+ Result64_1 = ((UINT64) Point_Result[SecondLoop]) + Carry64;
+ Result64_2 = (UINT64) Point_P[SecondLoop]*TempValue64;
+ Carry64 = (Result64_1 >> 32);
+ Result64_1 = (Result64_1 & 0xffffffffUL);
+ Result64_1 = Result64_1 + Result64_2;
+ Carry64 += (Result64_1 >> 32);
+ Point_Result[SecondLoop] = (UINT32) (Result64_1 & 0xffffffffUL);
+ } /* End of for */
+ while (Carry64 != 0) {
+ Result64_1 = ((UINT64) Point_Result[SecondLoop]) + Carry64;
+ Carry64 = Result64_1 >> 32;
+ Point_Result[SecondLoop] = (UINT32) (Result64_1 & 0xffffffffUL);
+ SecondLoop++;
+ } /* End of while */
+ Point_Result++;
+ } /* End of for */
+
+ for (FirstLoop = 0;FirstLoop <= LoopCount;FirstLoop++) {
+ (*pBI_Result)->pIntegerArray[FirstLoop] = (*pBI_Result)->pIntegerArray[FirstLoop + LoopCount];
+ } /* End of for */
+ if ((*pBI_Result)->pIntegerArray[LoopCount] != 0)
+ (*pBI_Result)->ArrayLength = LoopCount + 1;
+ else
+ (*pBI_Result)->ArrayLength = LoopCount;
+
+ (*pBI_Result)->IntegerLength = (*pBI_Result)->ArrayLength*4;
+ BigInteger_ClearHighBits(*pBI_Result);
+
+ if (BigInteger_UnsignedCompare(*pBI_Result, pBI_P) >= 0) {
+ BigInteger_Sub(*pBI_Result, pBI_P, &pBI_U);
+ BigInteger_Copy(pBI_U, pBI_Result);
+ } /* End of if */
+ BigInteger_ClearHighBits(*pBI_Result);
+} /* End of BigInteger_Montgomery_Reduction */
+
+
+VOID BigInteger_Montgomery_ExpMod (
+ IN PBIG_INTEGER pBI_G,
+ IN PBIG_INTEGER pBI_E,
+ IN PBIG_INTEGER pBI_P,
+ OUT PBIG_INTEGER *pBI_Result)
+{
+ UINT Bits_Of_P;
+ UINT32 Index, Index2, AllocLength;
+ UINT32 Sliding_Value , Sliding_HighValue, Sliding_LowValue;
+ PBIG_INTEGER pBI_Temp1 = NULL, pBI_Temp2 = NULL;
+ PBIG_INTEGER pBI_X = NULL, pBI_R = NULL, pBI_RR = NULL, pBI_1 = NULL;
+ BIG_INTEGER *pBI_A[SLIDING_WINDOW];
+ UINT8 *pRValue = NULL;
+
+ AllocLength = (pBI_G->IntegerLength + pBI_E->IntegerLength + pBI_P->IntegerLength + 300);
+ BigInteger_AllocSize(&pBI_Temp1, AllocLength);
+ BigInteger_AllocSize(&pBI_Temp2, AllocLength);
+
+ /* Calculate the bits of P and E, the highest bit is 1 */
+ BigInteger_BitsOfBI(pBI_P, &Bits_Of_P);
+
+ if ((pBI_G->IntegerLength == 1) && (pBI_G->pIntegerArray[0] == 0)) {
+ BigInteger_Bin2BI(Value_0, 1, pBI_Result);
+ goto memory_free;
+ } /* End of if */
+
+ if ((pBI_G->IntegerLength == 1) && (pBI_G->pIntegerArray[0] == 1)) {
+ BigInteger_Div(pBI_G, pBI_P, &pBI_Temp1, pBI_Result);
+ goto memory_free;
+ } /* End of if */
+
+ if ((pBI_E->IntegerLength == 1) && (pBI_E->pIntegerArray[0] == 1)) {
+ BigInteger_Div(pBI_G, pBI_P, &pBI_Temp1, pBI_Result);
+ goto memory_free;
+ } /* End of if */
+
+ if ((pBI_E->IntegerLength == 1) && (pBI_E->pIntegerArray[0] == 2)) {
+ BigInteger_Mul(pBI_G, pBI_G, &pBI_Temp1);
+ BigInteger_Div(pBI_Temp1, pBI_P, &pBI_Temp2, pBI_Result);
+ goto memory_free;
+ } /* End of if */
+
+ /*
+ * Main algorithm
+ */
+ BigInteger_Init(&pBI_R);
+ BigInteger_Init(&pBI_RR);
+ BigInteger_Bin2BI(Value_1, 1, &pBI_1);
+ BigInteger_AllocSize(&pBI_X, AllocLength);
+ BigInteger_AllocSize(&pBI_U, AllocLength); /* for BigInteger_Montgomery_Reduction */
+ BigInteger_AllocSize(&pBI_S, AllocLength); /* for BigInteger_Square */
+ BigInteger_AllocSize(&pBI_O, AllocLength); /* for BigInteger_Square */
+
+ for (Index = 0; Index < SLIDING_WINDOW; Index++) {
+ pBI_A[Index] = NULL;
+ BigInteger_AllocSize(&pBI_A[Index], 193);
+ } /* End of for */
+ BigInteger_Bin2BI(WPS_DH_P_VALUE, 192, &pBI_Temp1);
+ if (NdisCmpMemory(pBI_P->pIntegerArray, pBI_Temp1->pIntegerArray, pBI_P->IntegerLength) == 0) {
+ BigInteger_Bin2BI(WPS_DH_X_VALUE, 184, &pBI_X);
+ BigInteger_Bin2BI(WPS_DH_R_VALUE, 193, &pBI_R);
+ BigInteger_Bin2BI(WPS_DH_RRModP_VALUE, 192, &pBI_RR);
+ Bits_Of_R = 1537;
+ } else {
+ if ((Bits_Of_P % 8) == 0) {
+ AllocLength = pBI_P->IntegerLength + 1;
+ } else {
+ AllocLength = pBI_P->IntegerLength;
+ } /* End of if */
+/* pRValue = (UINT8 *) kmalloc(sizeof(UINT8)*AllocLength, GFP_ATOMIC); */
+ os_alloc_mem(NULL, (UCHAR **)&pRValue, sizeof(UINT8)*AllocLength);
+ if (pRValue == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__));
+ goto memory_free;
+ }
+ NdisZeroMemory(pRValue, sizeof(UINT8)*AllocLength);
+ pRValue[0] = (UINT8) (1 << (Bits_Of_P & 0x7));
+ BigInteger_Bin2BI(pRValue, AllocLength , &pBI_R);
+
+ BigInteger_Mul(pBI_R, pBI_R, &pBI_Temp1);
+ BigInteger_Div(pBI_Temp1, pBI_P, &pBI_A[1], &pBI_RR);
+
+ /* X = 1*R (mod P) */
+ BigInteger_Div(pBI_R, pBI_P, &pBI_Temp2, &pBI_X);
+ } /* End of if */
+
+ /* A = G*R (mod P) => A = MonMod(G, R^2 mod P) */
+ BigInteger_Mul(pBI_G, pBI_RR, &pBI_Temp1);
+ BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P , pBI_R, &pBI_A[1]);
+ for (Index = 2; Index < SLIDING_WINDOW; Index++) {
+ BigInteger_Mul(pBI_A[Index - 1], pBI_A[1], &pBI_Temp1);
+ BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_A[Index]);
+ } /* End of for */
+
+ for (Index = pBI_E->IntegerLength ; Index > 0 ; Index--) {
+ for (Index2 = 0; Index2 < 4 ; Index2++) {
+ BigInteger_Square(pBI_X, &pBI_Temp1);
+ BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_X);
+ } /* End of for */
+
+ Sliding_Value = BigInteger_GetByteValue(pBI_E, Index);
+ Sliding_HighValue = (Sliding_Value >> 4);
+ if (Sliding_HighValue != 0) {
+ BigInteger_Mul(pBI_A[Sliding_HighValue], pBI_X, &pBI_Temp1);
+ BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_X);
+ } /* End of if */
+
+ for (Index2 = 0; Index2 < 4 ; Index2++) {
+ BigInteger_Square(pBI_X, &pBI_Temp1);
+ BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_X);
+ } /* End of for */
+
+ Sliding_LowValue = Sliding_Value & 0x0f;
+ if (Sliding_LowValue != 0) {
+ BigInteger_Mul(pBI_A[Sliding_LowValue], pBI_X, &pBI_Temp1);
+ BigInteger_Montgomery_Reduction(pBI_Temp1, pBI_P, pBI_R, &pBI_X);
+ } /* End of if */
+ } /* End of for */
+ BigInteger_Montgomery_Reduction(pBI_X, pBI_P , pBI_R, pBI_Result);
+
+ BigInteger_Free(&pBI_X);
+ BigInteger_Free(&pBI_1);
+ BigInteger_Free(&pBI_U);
+ BigInteger_Free(&pBI_S);
+ BigInteger_Free(&pBI_O);
+ for(Index = 0; Index < SLIDING_WINDOW; Index++)
+ BigInteger_Free(&pBI_A[Index]);
+ if (pRValue != NULL)
+/* kfree(pRValue); */
+ os_free_mem(NULL, pRValue);
+
+memory_free:
+ BigInteger_Free(&pBI_R);
+ BigInteger_Free(&pBI_RR);
+ BigInteger_Free(&pBI_Temp1);
+ BigInteger_Free(&pBI_Temp2);
+} /* End of BigInteger_Montgomery_ExpMod */
+
+/* End of crypt_biginteger.c */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/crypt_dh.c b/cleopatre/devkit/mt7601udrv/common/crypt_dh.c
new file mode 100644
index 0000000000..0939143fe5
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/crypt_dh.c
@@ -0,0 +1,227 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************/
+
+/****************************************************************************
+ Module Name:
+ DH
+
+ Abstract:
+ RFC 2631: Diffie-Hellman Key Agreement Method
+
+ Revision History:
+ Who When What
+ -------- ---------- ------------------------------------------
+ Eddy 2009/01/21 Create Diffie-Hellman
+***************************************************************************/
+
+
+#include "crypt_dh.h"
+#include "crypt_biginteger.h"
+
+
+/*
+========================================================================
+Routine Description:
+ Diffie-Hellman public key generation
+
+Arguments:
+ GValue Array in UINT8
+ GValueLength The length of G in bytes
+ PValue Array in UINT8
+ PValueLength The length of P in bytes
+ PrivateKey Private key
+ PrivateKeyLength The length of Private key in bytes
+
+Return Value:
+ PublicKey Public key
+ PublicKeyLength The length of public key in bytes
+
+Note:
+ Reference to RFC2631
+ PublicKey = G^PrivateKey (mod P)
+========================================================================
+*/
+void DH_PublicKey_Generate (
+ IN UINT8 GValue[],
+ IN UINT GValueLength,
+ IN UINT8 PValue[],
+ IN UINT PValueLength,
+ IN UINT8 PrivateKey[],
+ IN UINT PrivateKeyLength,
+ OUT UINT8 PublicKey[],
+ INOUT UINT *PublicKeyLength)
+{
+ PBIG_INTEGER pBI_G = NULL;
+ PBIG_INTEGER pBI_P = NULL;
+ PBIG_INTEGER pBI_PrivateKey = NULL;
+ PBIG_INTEGER pBI_PublicKey = NULL;
+
+ /*
+ * 1. Check the input parameters
+ * - GValueLength, PValueLength and PrivateLength must be large than zero
+ * - PublicKeyLength must be large or equal than PValueLength
+ * - PValue must be odd
+ *
+ * - PValue must be prime number (no implement)
+ * - GValue must be greater than 0 but less than the PValue (no implement)
+ */
+ if (GValueLength == 0) {
+ DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: G length is (%d)\n", GValueLength));
+ return;
+ } /* End of if */
+ if (PValueLength == 0) {
+ DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: P length is (%d)\n", PValueLength));
+ return;
+ } /* End of if */
+ if (PrivateKeyLength == 0) {
+ DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: private key length is (%d)\n", PrivateKeyLength));
+ return;
+ } /* End of if */
+ if (*PublicKeyLength < PValueLength) {
+ DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: public key length(%d) must be large or equal than P length(%d)\n",
+ *PublicKeyLength, PValueLength));
+ return;
+ } /* End of if */
+ if (!(PValue[PValueLength - 1] & 0x1)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: P value must be odd\n"));
+ return;
+ } /* End of if */
+
+ /*
+ * 2. Transfer parameters to BigInteger structure
+ */
+ BigInteger_Init(&pBI_G);
+ BigInteger_Init(&pBI_P);
+ BigInteger_Init(&pBI_PrivateKey);
+ BigInteger_Init(&pBI_PublicKey);
+ BigInteger_Bin2BI(GValue, GValueLength, &pBI_G);
+ BigInteger_Bin2BI(PValue, PValueLength, &pBI_P);
+ BigInteger_Bin2BI(PrivateKey, PrivateKeyLength, &pBI_PrivateKey);
+
+ /*
+ * 3. Calculate PublicKey = G^PrivateKey (mod P)
+ * - BigInteger Operation
+ * - Montgomery reduction
+ */
+ BigInteger_Montgomery_ExpMod(pBI_G, pBI_PrivateKey, pBI_P, &pBI_PublicKey);
+
+ /*
+ * 4. Transfer BigInteger structure to char array
+ */
+ BigInteger_BI2Bin(pBI_PublicKey, PublicKey, PublicKeyLength);
+
+ BigInteger_Free(&pBI_G);
+ BigInteger_Free(&pBI_P);
+ BigInteger_Free(&pBI_PrivateKey);
+ BigInteger_Free(&pBI_PublicKey);
+} /* End of DH_PublicKey_Generate */
+
+
+/*
+========================================================================
+Routine Description:
+ Diffie-Hellman secret key generation
+
+Arguments:
+ PublicKey Public key
+ PublicKeyLength The length of Public key in bytes
+ PValue Array in UINT8
+ PValueLength The length of P in bytes
+ PrivateKey Private key
+ PrivateKeyLength The length of Private key in bytes
+
+Return Value:
+ SecretKey Secret key
+ SecretKeyLength The length of secret key in bytes
+
+Note:
+ Reference to RFC2631
+ SecretKey = PublicKey^PrivateKey (mod P)
+========================================================================
+*/
+void DH_SecretKey_Generate (
+ IN UINT8 PublicKey[],
+ IN UINT PublicKeyLength,
+ IN UINT8 PValue[],
+ IN UINT PValueLength,
+ IN UINT8 PrivateKey[],
+ IN UINT PrivateKeyLength,
+ OUT UINT8 SecretKey[],
+ INOUT UINT *SecretKeyLength)
+{
+ PBIG_INTEGER pBI_P = NULL;
+ PBIG_INTEGER pBI_SecretKey = NULL;
+ PBIG_INTEGER pBI_PrivateKey = NULL;
+ PBIG_INTEGER pBI_PublicKey = NULL;
+
+ /*
+ * 1. Check the input parameters
+ * - PublicKeyLength, PValueLength and PrivateLength must be large than zero
+ * - SecretKeyLength must be large or equal than PValueLength
+ * - PValue must be odd
+ *
+ * - PValue must be prime number (no implement)
+ */
+ if (PublicKeyLength == 0) {
+ DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: public key length is (%d)\n", PublicKeyLength));
+ return;
+ } /* End of if */
+ if (PValueLength == 0) {
+ DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: P length is (%d)\n", PValueLength));
+ return;
+ } /* End of if */
+ if (PrivateKeyLength == 0) {
+ DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: private key length is (%d)\n", PrivateKeyLength));
+ return;
+ } /* End of if */
+ if (*SecretKeyLength < PValueLength) {
+ DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: secret key length(%d) must be large or equal than P length(%d)\n",
+ *SecretKeyLength, PValueLength));
+ return;
+ } /* End of if */
+ if (!(PValue[PValueLength - 1] & 0x1)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: P value must be odd\n"));
+ return;
+ } /* End of if */
+
+ /*
+ * 2. Transfer parameters to BigInteger structure
+ */
+ BigInteger_Init(&pBI_P);
+ BigInteger_Init(&pBI_PrivateKey);
+ BigInteger_Init(&pBI_PublicKey);
+ BigInteger_Init(&pBI_SecretKey);
+
+ BigInteger_Bin2BI(PublicKey, PublicKeyLength, &pBI_PublicKey);
+ BigInteger_Bin2BI(PValue, PValueLength, &pBI_P);
+ BigInteger_Bin2BI(PrivateKey, PrivateKeyLength, &pBI_PrivateKey);
+
+ /*
+ * 3. Calculate SecretKey = PublicKey^PrivateKey (mod P)
+ * - BigInteger Operation
+ * - Montgomery reduction
+ */
+ BigInteger_Montgomery_ExpMod(pBI_PublicKey, pBI_PrivateKey, pBI_P, &pBI_SecretKey);
+
+ /*
+ * 4. Transfer BigInteger structure to char array
+ */
+ BigInteger_BI2Bin(pBI_SecretKey, SecretKey, SecretKeyLength);
+
+ BigInteger_Free(&pBI_P);
+ BigInteger_Free(&pBI_PrivateKey);
+ BigInteger_Free(&pBI_PublicKey);
+ BigInteger_Free(&pBI_SecretKey);
+} /* End of DH_SecretKey_Generate */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/crypt_hmac.c b/cleopatre/devkit/mt7601udrv/common/crypt_hmac.c
new file mode 100644
index 0000000000..2e3a6dcc08
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/crypt_hmac.c
@@ -0,0 +1,282 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************/
+
+/****************************************************************************
+ Module Name:
+ HMAC
+
+ Abstract:
+ FIPS 198: The Keyed-Hash Message Authentication Code (HMAC)
+
+ Revision History:
+ Who When What
+ -------- ---------- ------------------------------------------
+ Eddy 2008/11/24 Create HMAC-SHA1, HMAC-SHA256
+***************************************************************************/
+
+#include "crypt_hmac.h"
+
+
+#ifdef HMAC_SHA1_SUPPORT
+/*
+========================================================================
+Routine Description:
+ HMAC using SHA1 hash function
+
+Arguments:
+ key Secret key
+ key_len The length of the key in bytes
+ message Message context
+ message_len The length of message in bytes
+ macLen Request the length of message authentication code
+
+Return Value:
+ mac Message authentication code
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_HMAC_SHA1 (
+ IN const UINT8 Key[],
+ IN UINT KeyLen,
+ IN const UINT8 Message[],
+ IN UINT MessageLen,
+ OUT UINT8 MAC[],
+ IN UINT MACLen)
+{
+ SHA1_CTX_STRUC sha_ctx1;
+ SHA1_CTX_STRUC sha_ctx2;
+ UINT8 K0[SHA1_BLOCK_SIZE];
+ UINT8 Digest[SHA1_DIGEST_SIZE];
+ UINT index;
+
+ NdisZeroMemory(&sha_ctx1, sizeof(SHA1_CTX_STRUC));
+ NdisZeroMemory(&sha_ctx2, sizeof(SHA1_CTX_STRUC));
+ /*
+ * If the length of K = B(Block size): K0 = K.
+ * If the length of K > B: hash K to obtain an L byte string,
+ * then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00).
+ * If the length of K < B: append zeros to the end of K to create a B-byte string K0
+ */
+ NdisZeroMemory(K0, SHA1_BLOCK_SIZE);
+ if (KeyLen <= SHA1_BLOCK_SIZE)
+ NdisMoveMemory(K0, Key, KeyLen);
+ else
+ RT_SHA1(Key, KeyLen, K0);
+ /* End of if */
+
+ /* Exclusive-Or K0 with ipad */
+ /* ipad: Inner pad; the byte x¡¦36¡¦ repeated B times. */
+ for (index = 0; index < SHA1_BLOCK_SIZE; index++)
+ K0[index] ^= 0x36;
+ /* End of for */
+
+ RT_SHA1_Init(&sha_ctx1);
+ /* H(K0^ipad) */
+ RT_SHA1_Append(&sha_ctx1, K0, sizeof(K0));
+ /* H((K0^ipad)||text) */
+ RT_SHA1_Append(&sha_ctx1, Message, MessageLen);
+ RT_SHA1_End(&sha_ctx1, Digest);
+
+ /* Exclusive-Or K0 with opad and remove ipad */
+ /* opad: Outer pad; the byte x¡¦5c¡¦ repeated B times. */
+ for (index = 0; index < SHA1_BLOCK_SIZE; index++)
+ K0[index] ^= 0x36^0x5c;
+ /* End of for */
+
+ RT_SHA1_Init(&sha_ctx2);
+ /* H(K0^opad) */
+ RT_SHA1_Append(&sha_ctx2, K0, sizeof(K0));
+ /* H( (K0^opad) || H((K0^ipad)||text) ) */
+ RT_SHA1_Append(&sha_ctx2, Digest, SHA1_DIGEST_SIZE);
+ RT_SHA1_End(&sha_ctx2, Digest);
+
+ if (MACLen > SHA1_DIGEST_SIZE)
+ NdisMoveMemory(MAC, Digest, SHA1_DIGEST_SIZE);
+ else
+ NdisMoveMemory(MAC, Digest, MACLen);
+} /* End of RT_HMAC_SHA1 */
+#endif /* HMAC_SHA1_SUPPORT */
+
+
+#ifdef HMAC_SHA256_SUPPORT
+/*
+========================================================================
+Routine Description:
+ HMAC using SHA256 hash function
+
+Arguments:
+ key Secret key
+ key_len The length of the key in bytes
+ message Message context
+ message_len The length of message in bytes
+ macLen Request the length of message authentication code
+
+Return Value:
+ mac Message authentication code
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_HMAC_SHA256 (
+ IN const UINT8 Key[],
+ IN UINT KeyLen,
+ IN const UINT8 Message[],
+ IN UINT MessageLen,
+ OUT UINT8 MAC[],
+ IN UINT MACLen)
+{
+ SHA256_CTX_STRUC sha_ctx1;
+ SHA256_CTX_STRUC sha_ctx2;
+ UINT8 K0[SHA256_BLOCK_SIZE];
+ UINT8 Digest[SHA256_DIGEST_SIZE];
+ UINT index;
+
+ NdisZeroMemory(&sha_ctx1, sizeof(SHA256_CTX_STRUC));
+ NdisZeroMemory(&sha_ctx2, sizeof(SHA256_CTX_STRUC));
+ /*
+ * If the length of K = B(Block size): K0 = K.
+ * If the length of K > B: hash K to obtain an L byte string,
+ * then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00).
+ * If the length of K < B: append zeros to the end of K to create a B-byte string K0
+ */
+ NdisZeroMemory(K0, SHA256_BLOCK_SIZE);
+ if (KeyLen <= SHA256_BLOCK_SIZE) {
+ NdisMoveMemory(K0, Key, KeyLen);
+ } else {
+ RT_SHA256(Key, KeyLen, K0);
+ }
+
+ /* Exclusive-Or K0 with ipad */
+ /* ipad: Inner pad; the byte x¡¦36¡¦ repeated B times. */
+ for (index = 0; index < SHA256_BLOCK_SIZE; index++)
+ K0[index] ^= 0x36;
+ /* End of for */
+
+ RT_SHA256_Init(&sha_ctx1);
+ /* H(K0^ipad) */
+ RT_SHA256_Append(&sha_ctx1, K0, sizeof(K0));
+ /* H((K0^ipad)||text) */
+ RT_SHA256_Append(&sha_ctx1, Message, MessageLen);
+ RT_SHA256_End(&sha_ctx1, Digest);
+
+ /* Exclusive-Or K0 with opad and remove ipad */
+ /* opad: Outer pad; the byte x¡¦5c¡¦ repeated B times. */
+ for (index = 0; index < SHA256_BLOCK_SIZE; index++)
+ K0[index] ^= 0x36^0x5c;
+ /* End of for */
+
+ RT_SHA256_Init(&sha_ctx2);
+ /* H(K0^opad) */
+ RT_SHA256_Append(&sha_ctx2, K0, sizeof(K0));
+ /* H( (K0^opad) || H((K0^ipad)||text) ) */
+ RT_SHA256_Append(&sha_ctx2, Digest, SHA256_DIGEST_SIZE);
+ RT_SHA256_End(&sha_ctx2, Digest);
+
+ if (MACLen > SHA256_DIGEST_SIZE)
+ NdisMoveMemory(MAC, Digest,SHA256_DIGEST_SIZE);
+ else
+ NdisMoveMemory(MAC, Digest, MACLen);
+
+} /* End of RT_HMAC_SHA256 */
+#endif /* HMAC_SHA256_SUPPORT */
+
+
+#ifdef HMAC_MD5_SUPPORT
+/*
+========================================================================
+Routine Description:
+ HMAC using MD5 hash function
+
+Arguments:
+ key Secret key
+ key_len The length of the key in bytes
+ message Message context
+ message_len The length of message in bytes
+ macLen Request the length of message authentication code
+
+Return Value:
+ mac Message authentication code
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_HMAC_MD5(
+ IN const UINT8 Key[],
+ IN UINT KeyLen,
+ IN const UINT8 Message[],
+ IN UINT MessageLen,
+ OUT UINT8 MAC[],
+ IN UINT MACLen)
+{
+ MD5_CTX_STRUC md5_ctx1;
+ MD5_CTX_STRUC md5_ctx2;
+ UINT8 K0[MD5_BLOCK_SIZE];
+ UINT8 Digest[MD5_DIGEST_SIZE];
+ UINT index;
+
+ NdisZeroMemory(&md5_ctx1, sizeof(MD5_CTX_STRUC));
+ NdisZeroMemory(&md5_ctx2, sizeof(MD5_CTX_STRUC));
+ /*
+ * If the length of K = B(Block size): K0 = K.
+ * If the length of K > B: hash K to obtain an L byte string,
+ * then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00).
+ * If the length of K < B: append zeros to the end of K to create a B-byte string K0
+ */
+ NdisZeroMemory(K0, MD5_BLOCK_SIZE);
+ if (KeyLen <= MD5_BLOCK_SIZE) {
+ NdisMoveMemory(K0, Key, KeyLen);
+ } else {
+ RT_MD5(Key, KeyLen, K0);
+ }
+
+ /* Exclusive-Or K0 with ipad */
+ /* ipad: Inner pad; the byte x¡¦36¡¦ repeated B times. */
+ for (index = 0; index < MD5_BLOCK_SIZE; index++)
+ K0[index] ^= 0x36;
+ /* End of for */
+
+ RT_MD5_Init(&md5_ctx1);
+ /* H(K0^ipad) */
+ RT_MD5_Append(&md5_ctx1, K0, sizeof(K0));
+ /* H((K0^ipad)||text) */
+ RT_MD5_Append(&md5_ctx1, Message, MessageLen);
+ RT_MD5_End(&md5_ctx1, Digest);
+
+ /* Exclusive-Or K0 with opad and remove ipad */
+ /* opad: Outer pad; the byte x¡¦5c¡¦ repeated B times. */
+ for (index = 0; index < MD5_BLOCK_SIZE; index++)
+ K0[index] ^= 0x36^0x5c;
+ /* End of for */
+
+ RT_MD5_Init(&md5_ctx2);
+ /* H(K0^opad) */
+ RT_MD5_Append(&md5_ctx2, K0, sizeof(K0));
+ /* H( (K0^opad) || H((K0^ipad)||text) ) */
+ RT_MD5_Append(&md5_ctx2, Digest, MD5_DIGEST_SIZE);
+ RT_MD5_End(&md5_ctx2, Digest);
+
+ if (MACLen > MD5_DIGEST_SIZE)
+ NdisMoveMemory(MAC, Digest, MD5_DIGEST_SIZE);
+ else
+ NdisMoveMemory(MAC, Digest, MACLen);
+} /* End of RT_HMAC_SHA256 */
+#endif /* HMAC_MD5_SUPPORT */
+
+
+/* End of crypt_hmac.c */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/crypt_md5.c b/cleopatre/devkit/mt7601udrv/common/crypt_md5.c
new file mode 100644
index 0000000000..a49c1113d9
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/crypt_md5.c
@@ -0,0 +1,356 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************/
+
+/****************************************************************************
+ Module Name:
+ MD5
+
+ Abstract:
+ RFC1321: The MD5 Message-Digest Algorithm
+
+ Revision History:
+ Who When What
+ -------- ---------- ------------------------------------------
+ Eddy 2008/11/24 Create md5
+***************************************************************************/
+
+#include "rt_config.h"
+
+
+#ifdef MD5_SUPPORT
+/*
+ * F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+#define ROTL(x,n,w) ((x << n) | (x >> (w - n)))
+#define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */
+
+#define ROUND1(a, b, c, d, x, s, ac) { \
+ (a) += F((b),(c),(d)) + (x) + (UINT32)(ac); \
+ (a) = ROTL32((a),(s)); \
+ (a) += (b); \
+}
+#define ROUND2(a, b, c, d, x, s, ac) { \
+ (a) += G((b),(c),(d)) + (x) + (UINT32)(ac); \
+ (a) = ROTL32((a),(s)); \
+ (a) += (b); \
+}
+#define ROUND3(a, b, c, d, x, s, ac) { \
+ (a) += H((b),(c),(d)) + (x) + (UINT32)(ac); \
+ (a) = ROTL32((a),(s)); \
+ (a) += (b); \
+}
+#define ROUND4(a, b, c, d, x, s, ac) { \
+ (a) += I((b),(c),(d)) + (x) + (UINT32)(ac); \
+ (a) = ROTL32((a),(s)); \
+ (a) += (b); \
+}
+static const UINT32 MD5_DefaultHashValue[4] = {
+ 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL
+};
+#endif /* MD5_SUPPORT */
+
+
+#ifdef MD5_SUPPORT
+/*
+========================================================================
+Routine Description:
+ Initial Md5_CTX_STRUC
+
+Arguments:
+ pMD5_CTX Pointer to Md5_CTX_STRUC
+
+Return Value:
+ None
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_MD5_Init (
+ IN MD5_CTX_STRUC *pMD5_CTX)
+{
+ NdisMoveMemory(pMD5_CTX->HashValue, MD5_DefaultHashValue,
+ sizeof(MD5_DefaultHashValue));
+ NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE);
+ pMD5_CTX->BlockLen = 0;
+ pMD5_CTX->MessageLen = 0;
+} /* End of RT_MD5_Init */
+
+
+/*
+========================================================================
+Routine Description:
+ MD5 computation for one block (512 bits)
+
+Arguments:
+ pMD5_CTX Pointer to Md5_CTX_STRUC
+
+Return Value:
+ None
+
+Note:
+ T[i] := floor(abs(sin(i + 1)) * (2 pow 32)), i is number of round
+========================================================================
+*/
+VOID RT_MD5_Hash (
+ IN MD5_CTX_STRUC *pMD5_CTX)
+{
+ UINT32 X_i;
+ UINT32 X[16];
+ UINT32 a,b,c,d;
+
+ /* Prepare the message schedule, {X_i} */
+ NdisMoveMemory(X, pMD5_CTX->Block, MD5_BLOCK_SIZE);
+ for (X_i = 0; X_i < 16; X_i++)
+ X[X_i] = cpu2le32(X[X_i]); /* Endian Swap */
+ /* End of for */
+
+ /* MD5 hash computation */
+ /* Initialize the working variables */
+ a = pMD5_CTX->HashValue[0];
+ b = pMD5_CTX->HashValue[1];
+ c = pMD5_CTX->HashValue[2];
+ d = pMD5_CTX->HashValue[3];
+
+ /*
+ * Round 1
+ * Let [abcd k s i] denote the operation
+ * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
+ */
+ ROUND1(a, b, c, d, X[ 0], 7, 0xd76aa478); /* 1 */
+ ROUND1(d, a, b, c, X[ 1], 12, 0xe8c7b756); /* 2 */
+ ROUND1(c, d, a, b, X[ 2], 17, 0x242070db); /* 3 */
+ ROUND1(b, c, d, a, X[ 3], 22, 0xc1bdceee); /* 4 */
+ ROUND1(a, b, c, d, X[ 4], 7, 0xf57c0faf); /* 5 */
+ ROUND1(d, a, b, c, X[ 5], 12, 0x4787c62a); /* 6 */
+ ROUND1(c, d, a, b, X[ 6], 17, 0xa8304613); /* 7 */
+ ROUND1(b, c, d, a, X[ 7], 22, 0xfd469501); /* 8 */
+ ROUND1(a, b, c, d, X[ 8], 7, 0x698098d8); /* 9 */
+ ROUND1(d, a, b, c, X[ 9], 12, 0x8b44f7af); /* 10 */
+ ROUND1(c, d, a, b, X[10], 17, 0xffff5bb1); /* 11 */
+ ROUND1(b, c, d, a, X[11], 22, 0x895cd7be); /* 12 */
+ ROUND1(a, b, c, d, X[12], 7, 0x6b901122); /* 13 */
+ ROUND1(d, a, b, c, X[13], 12, 0xfd987193); /* 14 */
+ ROUND1(c, d, a, b, X[14], 17, 0xa679438e); /* 15 */
+ ROUND1(b, c, d, a, X[15], 22, 0x49b40821); /* 16 */
+
+ /*
+ * Round 2
+ * Let [abcd k s i] denote the operation
+ * a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s)
+ */
+ ROUND2(a, b, c, d, X[ 1], 5, 0xf61e2562); /* 17 */
+ ROUND2(d, a, b, c, X[ 6], 9, 0xc040b340); /* 18 */
+ ROUND2(c, d, a, b, X[11], 14, 0x265e5a51); /* 19 */
+ ROUND2(b, c, d, a, X[ 0], 20, 0xe9b6c7aa); /* 20 */
+ ROUND2(a, b, c, d, X[ 5], 5, 0xd62f105d); /* 21 */
+ ROUND2(d, a, b, c, X[10], 9, 0x2441453); /* 22 */
+ ROUND2(c, d, a, b, X[15], 14, 0xd8a1e681); /* 23 */
+ ROUND2(b, c, d, a, X[ 4], 20, 0xe7d3fbc8); /* 24 */
+ ROUND2(a, b, c, d, X[ 9], 5, 0x21e1cde6); /* 25 */
+ ROUND2(d, a, b, c, X[14], 9, 0xc33707d6); /* 26 */
+ ROUND2(c, d, a, b, X[ 3], 14, 0xf4d50d87); /* 27 */
+ ROUND2(b, c, d, a, X[ 8], 20, 0x455a14ed); /* 28 */
+ ROUND2(a, b, c, d, X[13], 5, 0xa9e3e905); /* 29 */
+ ROUND2(d, a, b, c, X[ 2], 9, 0xfcefa3f8); /* 30 */
+ ROUND2(c, d, a, b, X[ 7], 14, 0x676f02d9); /* 31 */
+ ROUND2(b, c, d, a, X[12], 20, 0x8d2a4c8a); /* 32 */
+
+ /*
+ * Round 3
+ * Let [abcd k s t] denote the operation
+ * a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s)
+ */
+ ROUND3(a, b, c, d, X[ 5], 4, 0xfffa3942); /* 33 */
+ ROUND3(d, a, b, c, X[ 8], 11, 0x8771f681); /* 34 */
+ ROUND3(c, d, a, b, X[11], 16, 0x6d9d6122); /* 35 */
+ ROUND3(b, c, d, a, X[14], 23, 0xfde5380c); /* 36 */
+ ROUND3(a, b, c, d, X[ 1], 4, 0xa4beea44); /* 37 */
+ ROUND3(d, a, b, c, X[ 4], 11, 0x4bdecfa9); /* 38 */
+ ROUND3(c, d, a, b, X[ 7], 16, 0xf6bb4b60); /* 39 */
+ ROUND3(b, c, d, a, X[10], 23, 0xbebfbc70); /* 40 */
+ ROUND3(a, b, c, d, X[13], 4, 0x289b7ec6); /* 41 */
+ ROUND3(d, a, b, c, X[ 0], 11, 0xeaa127fa); /* 42 */
+ ROUND3(c, d, a, b, X[ 3], 16, 0xd4ef3085); /* 43 */
+ ROUND3(b, c, d, a, X[ 6], 23, 0x4881d05); /* 44 */
+ ROUND3(a, b, c, d, X[ 9], 4, 0xd9d4d039); /* 45 */
+ ROUND3(d, a, b, c, X[12], 11, 0xe6db99e5); /* 46 */
+ ROUND3(c, d, a, b, X[15], 16, 0x1fa27cf8); /* 47 */
+ ROUND3(b, c, d, a, X[ 2], 23, 0xc4ac5665); /* 48 */
+
+ /*
+ * Round 4
+ * Let [abcd k s t] denote the operation
+ * a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s)
+ */
+ ROUND4(a, b, c, d, X[ 0], 6, 0xf4292244); /* 49 */
+ ROUND4(d, a, b, c, X[ 7], 10, 0x432aff97); /* 50 */
+ ROUND4(c, d, a, b, X[14], 15, 0xab9423a7); /* 51 */
+ ROUND4(b, c, d, a, X[ 5], 21, 0xfc93a039); /* 52 */
+ ROUND4(a, b, c, d, X[12], 6, 0x655b59c3); /* 53 */
+ ROUND4(d, a, b, c, X[ 3], 10, 0x8f0ccc92); /* 54 */
+ ROUND4(c, d, a, b, X[10], 15, 0xffeff47d); /* 55 */
+ ROUND4(b, c, d, a, X[ 1], 21, 0x85845dd1); /* 56 */
+ ROUND4(a, b, c, d, X[ 8], 6, 0x6fa87e4f); /* 57 */
+ ROUND4(d, a, b, c, X[15], 10, 0xfe2ce6e0); /* 58 */
+ ROUND4(c, d, a, b, X[ 6], 15, 0xa3014314); /* 59 */
+ ROUND4(b, c, d, a, X[13], 21, 0x4e0811a1); /* 60 */
+ ROUND4(a, b, c, d, X[ 4], 6, 0xf7537e82); /* 61 */
+ ROUND4(d, a, b, c, X[11], 10, 0xbd3af235); /* 62 */
+ ROUND4(c, d, a, b, X[ 2], 15, 0x2ad7d2bb); /* 63 */
+ ROUND4(b, c, d, a, X[ 9], 21, 0xeb86d391); /* 64 */
+
+ /* Compute the i^th intermediate hash value H^(i) */
+ pMD5_CTX->HashValue[0] += a;
+ pMD5_CTX->HashValue[1] += b;
+ pMD5_CTX->HashValue[2] += c;
+ pMD5_CTX->HashValue[3] += d;
+
+ NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE);
+ pMD5_CTX->BlockLen = 0;
+} /* End of RT_MD5_Hash */
+
+
+/*
+========================================================================
+Routine Description:
+ The message is appended to block. If block size > 64 bytes, the MD5_Hash
+will be called.
+
+Arguments:
+ pMD5_CTX Pointer to MD5_CTX_STRUC
+ message Message context
+ messageLen The length of message in bytes
+
+Return Value:
+ None
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_MD5_Append (
+ IN MD5_CTX_STRUC *pMD5_CTX,
+ IN const UINT8 Message[],
+ IN UINT MessageLen)
+{
+ UINT appendLen = 0;
+ UINT diffLen = 0;
+
+ while (appendLen != MessageLen) {
+ diffLen = MessageLen - appendLen;
+ if ((pMD5_CTX->BlockLen + diffLen) < MD5_BLOCK_SIZE) {
+ NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen,
+ Message + appendLen, diffLen);
+ pMD5_CTX->BlockLen += diffLen;
+ appendLen += diffLen;
+ }
+ else
+ {
+ NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen,
+ Message + appendLen, MD5_BLOCK_SIZE - pMD5_CTX->BlockLen);
+ appendLen += (MD5_BLOCK_SIZE - pMD5_CTX->BlockLen);
+ pMD5_CTX->BlockLen = MD5_BLOCK_SIZE;
+ RT_MD5_Hash(pMD5_CTX);
+ } /* End of if */
+ } /* End of while */
+ pMD5_CTX->MessageLen += MessageLen;
+} /* End of RT_MD5_Append */
+
+
+/*
+========================================================================
+Routine Description:
+ 1. Append bit 1 to end of the message
+ 2. Append the length of message in rightmost 64 bits
+ 3. Transform the Hash Value to digest message
+
+Arguments:
+ pMD5_CTX Pointer to MD5_CTX_STRUC
+
+Return Value:
+ digestMessage Digest message
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_MD5_End (
+ IN MD5_CTX_STRUC *pMD5_CTX,
+ OUT UINT8 DigestMessage[])
+{
+ UINT index;
+ UINT64 message_length_bits;
+
+ /* append 1 bits to end of the message */
+ NdisFillMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, 1, 0x80);
+
+ /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */
+ if (pMD5_CTX->BlockLen > 55)
+ RT_MD5_Hash(pMD5_CTX);
+ /* End of if */
+
+ /* Append the length of message in rightmost 64 bits */
+ message_length_bits = pMD5_CTX->MessageLen*8;
+ message_length_bits = cpu2le64(message_length_bits);
+ NdisMoveMemory(&pMD5_CTX->Block[56], &message_length_bits, 8);
+ RT_MD5_Hash(pMD5_CTX);
+
+ /* Return message digest, transform the UINT32 hash value to bytes */
+ for (index = 0; index < 4;index++)
+ pMD5_CTX->HashValue[index] = cpu2le32(pMD5_CTX->HashValue[index]);
+ /* End of for */
+ NdisMoveMemory(DigestMessage, pMD5_CTX->HashValue, MD5_DIGEST_SIZE);
+} /* End of RT_MD5_End */
+
+
+/*
+========================================================================
+Routine Description:
+ MD5 algorithm
+
+Arguments:
+ message Message context
+ messageLen The length of message in bytes
+
+Return Value:
+ digestMessage Digest message
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_MD5 (
+ IN const UINT8 Message[],
+ IN UINT MessageLen,
+ OUT UINT8 DigestMessage[])
+{
+ MD5_CTX_STRUC md5_ctx;
+
+ NdisZeroMemory(&md5_ctx, sizeof(MD5_CTX_STRUC));
+ RT_MD5_Init(&md5_ctx);
+ RT_MD5_Append(&md5_ctx, Message, MessageLen);
+ RT_MD5_End(&md5_ctx, DigestMessage);
+} /* End of RT_MD5 */
+
+#endif /* MD5_SUPPORT */
+
+
+/* End of crypt_md5.c */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/crypt_sha2.c b/cleopatre/devkit/mt7601udrv/common/crypt_sha2.c
new file mode 100644
index 0000000000..75de87cd3f
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/crypt_sha2.c
@@ -0,0 +1,555 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************/
+
+/****************************************************************************
+ Module Name:
+ SHA2
+
+ Abstract:
+ FIPS 180-2: Secure Hash Standard (SHS)
+
+ Revision History:
+ Who When What
+ -------- ---------- ------------------------------------------
+ Eddy 2008/11/24 Create SHA1
+ Eddy 2008/07/23 Create SHA256
+***************************************************************************/
+
+#include "rt_config.h"
+
+
+/* Basic operations */
+#define SHR(x,n) (x >> n) /* SHR(x)^n, right shift n bits , x is w-bit word, 0 <= n <= w */
+#define ROTR(x,n,w) ((x >> n) | (x << (w - n))) /* ROTR(x)^n, circular right shift n bits , x is w-bit word, 0 <= n <= w */
+#define ROTL(x,n,w) ((x << n) | (x >> (w - n))) /* ROTL(x)^n, circular left shift n bits , x is w-bit word, 0 <= n <= w */
+#define ROTR32(x,n) ROTR(x,n,32) /* 32 bits word */
+#define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */
+
+/* Basic functions */
+#define Ch(x,y,z) ((x & y) ^ ((~x) & z))
+#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
+#define Parity(x,y,z) (x ^ y ^ z)
+
+#ifdef SHA1_SUPPORT
+/* SHA1 constants */
+#define SHA1_MASK 0x0000000f
+static const UINT32 SHA1_K[4] = {
+ 0x5a827999UL, 0x6ed9eba1UL, 0x8f1bbcdcUL, 0xca62c1d6UL
+};
+static const UINT32 SHA1_DefaultHashValue[5] = {
+ 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL, 0xc3d2e1f0UL
+};
+#endif /* SHA1_SUPPORT */
+
+
+#ifdef SHA256_SUPPORT
+/* SHA256 functions */
+#define Zsigma_256_0(x) (ROTR32(x,2) ^ ROTR32(x,13) ^ ROTR32(x,22))
+#define Zsigma_256_1(x) (ROTR32(x,6) ^ ROTR32(x,11) ^ ROTR32(x,25))
+#define Sigma_256_0(x) (ROTR32(x,7) ^ ROTR32(x,18) ^ SHR(x,3))
+#define Sigma_256_1(x) (ROTR32(x,17) ^ ROTR32(x,19) ^ SHR(x,10))
+/* SHA256 constants */
+static const UINT32 SHA256_K[64] = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+ 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+ 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+ 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+ 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+ 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+ 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+ 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+ 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+ 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+ 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+ 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+ 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+ 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+ 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+static const UINT32 SHA256_DefaultHashValue[8] = {
+ 0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL,
+ 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL
+};
+#endif /* SHA256_SUPPORT */
+
+
+#ifdef SHA1_SUPPORT
+/*
+========================================================================
+Routine Description:
+ Initial SHA1_CTX_STRUC
+
+Arguments:
+ pSHA_CTX Pointer to SHA1_CTX_STRUC
+
+Return Value:
+ None
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_SHA1_Init (
+ IN SHA1_CTX_STRUC *pSHA_CTX)
+{
+ NdisMoveMemory(pSHA_CTX->HashValue, SHA1_DefaultHashValue,
+ sizeof(SHA1_DefaultHashValue));
+ NdisZeroMemory(pSHA_CTX->Block, SHA1_BLOCK_SIZE);
+ pSHA_CTX->MessageLen = 0;
+ pSHA_CTX->BlockLen = 0;
+} /* End of RT_SHA1_Init */
+
+
+/*
+========================================================================
+Routine Description:
+ SHA1 computation for one block (512 bits)
+
+Arguments:
+ pSHA_CTX Pointer to SHA1_CTX_STRUC
+
+Return Value:
+ None
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_SHA1_Hash (
+ IN SHA1_CTX_STRUC *pSHA_CTX)
+{
+ UINT32 W_i,t;
+ UINT32 W[80];
+ UINT32 a,b,c,d,e,T,f_t = 0;
+
+ /* Prepare the message schedule, {W_i}, 0 < t < 15 */
+ NdisMoveMemory(W, pSHA_CTX->Block, SHA1_BLOCK_SIZE);
+ for (W_i = 0; W_i < 16; W_i++) {
+ W[W_i] = cpu2be32(W[W_i]); /* Endian Swap */
+ } /* End of for */
+
+ for (W_i = 16; W_i < 80; W_i++) {
+ W[W_i] = ROTL32((W[W_i - 3] ^ W[W_i - 8] ^ W[W_i - 14] ^ W[W_i - 16]),1);
+ } /* End of for */
+
+
+ /* SHA256 hash computation */
+ /* Initialize the working variables */
+ a = pSHA_CTX->HashValue[0];
+ b = pSHA_CTX->HashValue[1];
+ c = pSHA_CTX->HashValue[2];
+ d = pSHA_CTX->HashValue[3];
+ e = pSHA_CTX->HashValue[4];
+
+ /* 80 rounds */
+ for (t = 0;t < 20;t++) {
+ f_t = Ch(b,c,d);
+ T = ROTL32(a,5) + f_t + e + SHA1_K[0] + W[t];
+ e = d;
+ d = c;
+ c = ROTL32(b,30);
+ b = a;
+ a = T;
+ } /* End of for */
+ for (t = 20;t < 40;t++) {
+ f_t = Parity(b,c,d);
+ T = ROTL32(a,5) + f_t + e + SHA1_K[1] + W[t];
+ e = d;
+ d = c;
+ c = ROTL32(b,30);
+ b = a;
+ a = T;
+ } /* End of for */
+ for (t = 40;t < 60;t++) {
+ f_t = Maj(b,c,d);
+ T = ROTL32(a,5) + f_t + e + SHA1_K[2] + W[t];
+ e = d;
+ d = c;
+ c = ROTL32(b,30);
+ b = a;
+ a = T;
+ } /* End of for */
+ for (t = 60;t < 80;t++) {
+ f_t = Parity(b,c,d);
+ T = ROTL32(a,5) + f_t + e + SHA1_K[3] + W[t];
+ e = d;
+ d = c;
+ c = ROTL32(b,30);
+ b = a;
+ a = T;
+ } /* End of for */
+
+
+ /* Compute the i^th intermediate hash value H^(i) */
+ pSHA_CTX->HashValue[0] += a;
+ pSHA_CTX->HashValue[1] += b;
+ pSHA_CTX->HashValue[2] += c;
+ pSHA_CTX->HashValue[3] += d;
+ pSHA_CTX->HashValue[4] += e;
+
+ NdisZeroMemory(pSHA_CTX->Block, SHA1_BLOCK_SIZE);
+ pSHA_CTX->BlockLen = 0;
+} /* End of RT_SHA1_Hash */
+
+
+/*
+========================================================================
+Routine Description:
+ The message is appended to block. If block size > 64 bytes, the SHA1_Hash
+will be called.
+
+Arguments:
+ pSHA_CTX Pointer to SHA1_CTX_STRUC
+ message Message context
+ messageLen The length of message in bytes
+
+Return Value:
+ None
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_SHA1_Append (
+ IN SHA1_CTX_STRUC *pSHA_CTX,
+ IN const UINT8 Message[],
+ IN UINT MessageLen)
+{
+ UINT appendLen = 0;
+ UINT diffLen = 0;
+
+ while (appendLen != MessageLen) {
+ diffLen = MessageLen - appendLen;
+ if ((pSHA_CTX->BlockLen + diffLen) < SHA1_BLOCK_SIZE) {
+ NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen,
+ Message + appendLen, diffLen);
+ pSHA_CTX->BlockLen += diffLen;
+ appendLen += diffLen;
+ }
+ else
+ {
+ NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen,
+ Message + appendLen, SHA1_BLOCK_SIZE - pSHA_CTX->BlockLen);
+ appendLen += (SHA1_BLOCK_SIZE - pSHA_CTX->BlockLen);
+ pSHA_CTX->BlockLen = SHA1_BLOCK_SIZE;
+ RT_SHA1_Hash(pSHA_CTX);
+ } /* End of if */
+ } /* End of while */
+ pSHA_CTX->MessageLen += MessageLen;
+} /* End of RT_SHA1_Append */
+
+
+/*
+========================================================================
+Routine Description:
+ 1. Append bit 1 to end of the message
+ 2. Append the length of message in rightmost 64 bits
+ 3. Transform the Hash Value to digest message
+
+Arguments:
+ pSHA_CTX Pointer to SHA1_CTX_STRUC
+
+Return Value:
+ digestMessage Digest message
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_SHA1_End (
+ IN SHA1_CTX_STRUC *pSHA_CTX,
+ OUT UINT8 DigestMessage[])
+{
+ UINT index;
+ UINT64 message_length_bits;
+
+ /* Append bit 1 to end of the message */
+ NdisFillMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, 1, 0x80);
+
+ /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */
+ if (pSHA_CTX->BlockLen > 55)
+ RT_SHA1_Hash(pSHA_CTX);
+ /* End of if */
+
+ /* Append the length of message in rightmost 64 bits */
+ message_length_bits = pSHA_CTX->MessageLen*8;
+ message_length_bits = cpu2be64(message_length_bits);
+ NdisMoveMemory(&pSHA_CTX->Block[56], &message_length_bits, 8);
+ RT_SHA1_Hash(pSHA_CTX);
+
+ /* Return message digest, transform the UINT32 hash value to bytes */
+ for (index = 0; index < 5;index++)
+ pSHA_CTX->HashValue[index] = cpu2be32(pSHA_CTX->HashValue[index]);
+ /* End of for */
+ NdisMoveMemory(DigestMessage, pSHA_CTX->HashValue, SHA1_DIGEST_SIZE);
+} /* End of RT_SHA1_End */
+
+
+/*
+========================================================================
+Routine Description:
+ SHA1 algorithm
+
+Arguments:
+ message Message context
+ messageLen The length of message in bytes
+
+Return Value:
+ digestMessage Digest message
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_SHA1 (
+ IN const UINT8 Message[],
+ IN UINT MessageLen,
+ OUT UINT8 DigestMessage[])
+{
+
+ SHA1_CTX_STRUC sha_ctx;
+
+ NdisZeroMemory(&sha_ctx, sizeof(SHA1_CTX_STRUC));
+ RT_SHA1_Init(&sha_ctx);
+ RT_SHA1_Append(&sha_ctx, Message, MessageLen);
+ RT_SHA1_End(&sha_ctx, DigestMessage);
+} /* End of RT_SHA1 */
+#endif /* SHA1_SUPPORT */
+
+
+#ifdef SHA256_SUPPORT
+/*
+========================================================================
+Routine Description:
+ Initial SHA256_CTX_STRUC
+
+Arguments:
+ pSHA_CTX Pointer to SHA256_CTX_STRUC
+
+Return Value:
+ None
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_SHA256_Init (
+ IN SHA256_CTX_STRUC *pSHA_CTX)
+{
+ NdisMoveMemory(pSHA_CTX->HashValue, SHA256_DefaultHashValue,
+ sizeof(SHA256_DefaultHashValue));
+ NdisZeroMemory(pSHA_CTX->Block, SHA256_BLOCK_SIZE);
+ pSHA_CTX->MessageLen = 0;
+ pSHA_CTX->BlockLen = 0;
+} /* End of RT_SHA256_Init */
+
+
+/*
+========================================================================
+Routine Description:
+ SHA256 computation for one block (512 bits)
+
+Arguments:
+ pSHA_CTX Pointer to SHA256_CTX_STRUC
+
+Return Value:
+ None
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_SHA256_Hash (
+ IN SHA256_CTX_STRUC *pSHA_CTX)
+{
+ UINT32 W_i,t;
+ UINT32 W[64];
+ UINT32 a,b,c,d,e,f,g,h,T1,T2;
+
+ /* Prepare the message schedule, {W_i}, 0 < t < 15 */
+ NdisMoveMemory(W, pSHA_CTX->Block, SHA256_BLOCK_SIZE);
+ for (W_i = 0; W_i < 16; W_i++)
+ W[W_i] = cpu2be32(W[W_i]); /* Endian Swap */
+ /* End of for */
+
+ /* SHA256 hash computation */
+ /* Initialize the working variables */
+ a = pSHA_CTX->HashValue[0];
+ b = pSHA_CTX->HashValue[1];
+ c = pSHA_CTX->HashValue[2];
+ d = pSHA_CTX->HashValue[3];
+ e = pSHA_CTX->HashValue[4];
+ f = pSHA_CTX->HashValue[5];
+ g = pSHA_CTX->HashValue[6];
+ h = pSHA_CTX->HashValue[7];
+
+ /* 64 rounds */
+ for (t = 0;t < 64;t++) {
+ if (t > 15) /* Prepare the message schedule, {W_i}, 16 < t < 63 */
+ W[t] = Sigma_256_1(W[t-2]) + W[t-7] + Sigma_256_0(W[t-15]) + W[t-16];
+ /* End of if */
+ T1 = h + Zsigma_256_1(e) + Ch(e,f,g) + SHA256_K[t] + W[t];
+ T2 = Zsigma_256_0(a) + Maj(a,b,c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+ } /* End of for */
+
+ /* Compute the i^th intermediate hash value H^(i) */
+ pSHA_CTX->HashValue[0] += a;
+ pSHA_CTX->HashValue[1] += b;
+ pSHA_CTX->HashValue[2] += c;
+ pSHA_CTX->HashValue[3] += d;
+ pSHA_CTX->HashValue[4] += e;
+ pSHA_CTX->HashValue[5] += f;
+ pSHA_CTX->HashValue[6] += g;
+ pSHA_CTX->HashValue[7] += h;
+
+ NdisZeroMemory(pSHA_CTX->Block, SHA256_BLOCK_SIZE);
+ pSHA_CTX->BlockLen = 0;
+} /* End of RT_SHA256_Hash */
+
+
+/*
+========================================================================
+Routine Description:
+ The message is appended to block. If block size > 64 bytes, the SHA256_Hash
+will be called.
+
+Arguments:
+ pSHA_CTX Pointer to SHA256_CTX_STRUC
+ message Message context
+ messageLen The length of message in bytes
+
+Return Value:
+ None
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_SHA256_Append (
+ IN SHA256_CTX_STRUC *pSHA_CTX,
+ IN const UINT8 Message[],
+ IN UINT MessageLen)
+{
+ UINT appendLen = 0;
+ UINT diffLen = 0;
+
+ while (appendLen != MessageLen) {
+ diffLen = MessageLen - appendLen;
+ if ((pSHA_CTX->BlockLen + diffLen) < SHA256_BLOCK_SIZE) {
+ NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen,
+ Message + appendLen, diffLen);
+ pSHA_CTX->BlockLen += diffLen;
+ appendLen += diffLen;
+ }
+ else
+ {
+ NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen,
+ Message + appendLen, SHA256_BLOCK_SIZE - pSHA_CTX->BlockLen);
+ appendLen += (SHA256_BLOCK_SIZE - pSHA_CTX->BlockLen);
+ pSHA_CTX->BlockLen = SHA256_BLOCK_SIZE;
+ RT_SHA256_Hash(pSHA_CTX);
+ } /* End of if */
+ } /* End of while */
+ pSHA_CTX->MessageLen += MessageLen;
+} /* End of RT_SHA256_Append */
+
+
+/*
+========================================================================
+Routine Description:
+ 1. Append bit 1 to end of the message
+ 2. Append the length of message in rightmost 64 bits
+ 3. Transform the Hash Value to digest message
+
+Arguments:
+ pSHA_CTX Pointer to SHA256_CTX_STRUC
+
+Return Value:
+ digestMessage Digest message
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_SHA256_End (
+ IN SHA256_CTX_STRUC *pSHA_CTX,
+ OUT UINT8 DigestMessage[])
+{
+ UINT index;
+ UINT64 message_length_bits;
+
+ /* Append bit 1 to end of the message */
+ NdisFillMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, 1, 0x80);
+
+ /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */
+ if (pSHA_CTX->BlockLen > 55)
+ RT_SHA256_Hash(pSHA_CTX);
+ /* End of if */
+
+ /* Append the length of message in rightmost 64 bits */
+ message_length_bits = pSHA_CTX->MessageLen*8;
+ message_length_bits = cpu2be64(message_length_bits);
+ NdisMoveMemory(&pSHA_CTX->Block[56], &message_length_bits, 8);
+ RT_SHA256_Hash(pSHA_CTX);
+
+ /* Return message digest, transform the UINT32 hash value to bytes */
+ for (index = 0; index < 8;index++)
+ pSHA_CTX->HashValue[index] = cpu2be32(pSHA_CTX->HashValue[index]);
+ /* End of for */
+ NdisMoveMemory(DigestMessage, pSHA_CTX->HashValue, SHA256_DIGEST_SIZE);
+} /* End of RT_SHA256_End */
+
+
+/*
+========================================================================
+Routine Description:
+ SHA256 algorithm
+
+Arguments:
+ message Message context
+ messageLen The length of message in bytes
+
+Return Value:
+ digestMessage Digest message
+
+Note:
+ None
+========================================================================
+*/
+VOID RT_SHA256 (
+ IN const UINT8 Message[],
+ IN UINT MessageLen,
+ OUT UINT8 DigestMessage[])
+{
+ SHA256_CTX_STRUC sha_ctx;
+
+ NdisZeroMemory(&sha_ctx, sizeof(SHA256_CTX_STRUC));
+ RT_SHA256_Init(&sha_ctx);
+ RT_SHA256_Append(&sha_ctx, Message, MessageLen);
+ RT_SHA256_End(&sha_ctx, DigestMessage);
+} /* End of RT_SHA256 */
+#endif /* SHA256_SUPPORT */
+
+
+/* End of crypt_sha2.c */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/ee_efuse.c b/cleopatre/devkit/mt7601udrv/common/ee_efuse.c
new file mode 100644
index 0000000000..0067ca2362
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/ee_efuse.c
@@ -0,0 +1,1893 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ ee_efuse.c
+
+ Abstract:
+ Miniport generic portion header file
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+*/
+
+#ifdef RTMP_EFUSE_SUPPORT
+
+#include "rt_config.h"
+
+#if defined(RT65xx) || defined(MT7601)
+/* eFuse registers */
+#define EFUSE_CTRL 0x24
+#define EFUSE_DATA0 0x28
+#define EFUSE_DATA1 0x2c
+#define EFUSE_DATA2 0x30
+#define EFUSE_DATA3 0x34
+#else
+/* eFuse registers */
+#define EFUSE_CTRL 0x0580
+#define EFUSE_DATA0 0x0590
+#define EFUSE_DATA1 0x0594
+#define EFUSE_DATA2 0x0598
+#define EFUSE_DATA3 0x059c
+#endif /* RT65xx */
+
+
+#define EFUSE_CTRL_3290 0x24
+#define EFUSE_DATA0_3290 0x28
+#define EFUSE_DATA1_3290 0x2c
+#define EFUSE_DATA2_3290 0x30
+#define EFUSE_DATA3_3290 0x34
+
+#ifdef RT65xx
+#define EFUSE_EEPROM_DEFULT_FILE "RT30xxEEPROM.bin"
+#define EFUSE_BUFFER_PATH "/var/lib/share/MT7650/RT30xxEEPROM.bin"
+#define MAX_EEPROM_BIN_FILE_SIZE 512
+#endif /* RT65xx */
+
+#ifdef MT7601
+#define EFUSE_EEPROM_DEFULT_FILE "MT7601EEPROM.bin"
+#define EFUSE_BUFFER_PATH "/var/lib/share/MT7601/MT7601EEPROM.bin"
+#define MAX_EEPROM_BIN_FILE_SIZE 512
+#endif /* MT7601 */
+
+#ifdef RTMP_MAC
+#define EFUSE_EEPROM_DEFULT_FILE "RT30xxEEPROM.bin"
+#define EFUSE_BUFFER_PATH "/var/lib/share/RT2870/RT30xxEEPROM.bin"
+#define MAX_EEPROM_BIN_FILE_SIZE 512
+#endif /* RTMP_MAC */
+
+#define EFUSE_TAG 0x2fe
+
+#ifdef RT_BIG_ENDIAN
+typedef union _EFUSE_CTRL_STRUC {
+ struct {
+ UINT32 SEL_EFUSE:1;
+ UINT32 EFSROM_KICK:1;
+ UINT32 RESERVED:4;
+ UINT32 EFSROM_AIN:10;
+ UINT32 EFSROM_LDO_ON_TIME:2;
+ UINT32 EFSROM_LDO_OFF_TIME:6;
+ UINT32 EFSROM_MODE:2;
+ UINT32 EFSROM_AOUT:6;
+ } field;
+ UINT32 word;
+} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC;
+#else
+typedef union _EFUSE_CTRL_STRUC {
+ struct {
+ UINT32 EFSROM_AOUT:6;
+ UINT32 EFSROM_MODE:2;
+ UINT32 EFSROM_LDO_OFF_TIME:6;
+ UINT32 EFSROM_LDO_ON_TIME:2;
+ UINT32 EFSROM_AIN:10;
+ UINT32 RESERVED:4;
+ UINT32 EFSROM_KICK:1;
+ UINT32 SEL_EFUSE:1;
+ } field;
+ UINT32 word;
+} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC;
+#endif /* RT_BIG_ENDIAN */
+
+static UCHAR eFuseReadRegisters(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN USHORT Length,
+ OUT USHORT* pData);
+
+VOID eFuseReadPhysical(
+ IN PRTMP_ADAPTER pAd,
+ IN PUSHORT lpInBuffer,
+ IN ULONG nInBufferSize,
+ OUT PUSHORT lpOutBuffer,
+ IN ULONG nOutBufferSize);
+
+static VOID eFusePhysicalWriteRegisters(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN USHORT Length,
+ OUT USHORT* pData);
+
+static NTSTATUS eFuseWriteRegisters(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN USHORT Length,
+ IN USHORT* pData);
+
+static VOID eFuseWritePhysical(
+ IN PRTMP_ADAPTER pAd,
+ PUSHORT lpInBuffer,
+ ULONG nInBufferSize,
+ PUCHAR lpOutBuffer,
+ ULONG nOutBufferSize);
+
+
+static NTSTATUS eFuseWriteRegistersFromBin(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN USHORT Length,
+ IN USHORT* pData);
+
+
+/*
+========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+========================================================================
+*/
+UCHAR eFuseReadRegisters(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN USHORT Length,
+ OUT USHORT* pData)
+{
+ EFUSE_CTRL_STRUC eFuseCtrlStruc;
+ int i;
+ USHORT efuseDataOffset;
+ UINT32 data;
+ UINT32 efuse_ctrl_reg = EFUSE_CTRL;
+
+#if defined(RT3290) || defined(RT65xx) || defined(MT7601)
+ if (IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd))
+ efuse_ctrl_reg = EFUSE_CTRL_3290;
+#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) */
+
+ RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word);
+
+ /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/
+ /*Use the eeprom logical address and covert to address to block number*/
+ eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
+
+ /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0.*/
+ eFuseCtrlStruc.field.EFSROM_MODE = 0;
+
+ /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.*/
+ eFuseCtrlStruc.field.EFSROM_KICK = 1;
+
+ NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
+ RTMP_IO_WRITE32(pAd, efuse_ctrl_reg, data);
+
+ /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.*/
+ i = 0;
+ while(i < 500)
+ {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return 0;
+
+ /*rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4);*/
+ RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word);
+ if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
+ {
+ break;
+ }
+ RTMPusecDelay(2);
+ i++;
+ }
+
+ /*if EFSROM_AOUT is not found in physical address, write 0xffff*/
+ if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f)
+ {
+ for(i=0; i<Length/2; i++)
+ *(pData+2*i) = 0xffff;
+ }
+ else
+ {
+ /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x590-0x59C)*/
+#if defined(RT3290) || defined(RT65xx) || defined(MT7601)
+ if (IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd))
+ efuseDataOffset = EFUSE_DATA0_3290 + (Offset & 0xC);
+ else
+#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) */
+ efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC);
+ /*data hold 4 bytes data.*/
+ /*In RTMP_IO_READ32 will automatically execute 32-bytes swapping*/
+ RTMP_IO_READ32(pAd, efuseDataOffset, &data);
+ /*Decide the upper 2 bytes or the bottom 2 bytes.*/
+ /* Little-endian S | S Big-endian*/
+ /* addr 3 2 1 0 | 0 1 2 3*/
+ /* Ori-V D C B A | A B C D*/
+ /*After swapping*/
+ /* D C B A | D C B A*/
+ /*Return 2-bytes*/
+ /*The return byte statrs from S. Therefore, the little-endian will return BA, the Big-endian will return DC.*/
+ /*For returning the bottom 2 bytes, the Big-endian should shift right 2-bytes.*/
+#ifdef RT_BIG_ENDIAN
+ data = data << (8*((Offset & 0x3)^0x2));
+#else
+ data = data >> (8*(Offset & 0x3));
+#endif /* RT_BIG_ENDIAN */
+
+ NdisMoveMemory(pData, &data, Length);
+ }
+
+ return (UCHAR) eFuseCtrlStruc.field.EFSROM_AOUT;
+
+}
+
+/*
+========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+========================================================================
+*/
+VOID eFusePhysicalReadRegisters(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN USHORT Length,
+ OUT USHORT* pData)
+{
+ EFUSE_CTRL_STRUC eFuseCtrlStruc;
+ int i;
+ USHORT efuseDataOffset;
+ UINT32 data;
+ UINT32 efuse_ctrl_reg = EFUSE_CTRL;
+
+#if defined(RT3290) || defined(RT65xx) || defined(MT7601)
+ if (IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd))
+ efuse_ctrl_reg = EFUSE_CTRL_3290;
+#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) */
+
+ RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word);
+
+ /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/
+ eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
+
+ /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1.*/
+ /*Read in physical view*/
+ eFuseCtrlStruc.field.EFSROM_MODE = 1;
+
+ /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.*/
+ eFuseCtrlStruc.field.EFSROM_KICK = 1;
+
+ NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
+ RTMP_IO_WRITE32(pAd, efuse_ctrl_reg, data);
+
+ /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.*/
+ i = 0;
+ while(i < 500)
+ {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
+ if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
+ break;
+ RTMPusecDelay(2);
+ i++;
+ }
+
+ /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590)*/
+ /*Because the size of each EFUSE_DATA is 4 Bytes, the size of address of each is 2 bits.*/
+ /*The previous 2 bits is the EFUSE_DATA number, the last 2 bits is used to decide which bytes*/
+ /*Decide which EFUSE_DATA to read*/
+ /*590:F E D C */
+ /*594:B A 9 8 */
+ /*598:7 6 5 4*/
+ /*59C:3 2 1 0*/
+#if defined(RT3290) || defined(RT65xx) || defined(MT7601)
+ if (IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd))
+ efuseDataOffset = EFUSE_DATA0_3290 + (Offset & 0xC) ;
+ else
+#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) */
+ efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC) ;
+
+ RTMP_IO_READ32(pAd, efuseDataOffset, &data);
+
+#ifdef RT_BIG_ENDIAN
+ data = data << (8*((Offset & 0x3)^0x2));
+#else
+ data = data >> (8*(Offset & 0x3));
+#endif /* RT_BIG_ENDIAN */
+
+ NdisMoveMemory(pData, &data, Length);
+
+}
+
+/*
+========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+========================================================================
+*/
+VOID eFuseReadPhysical(
+ IN PRTMP_ADAPTER pAd,
+ IN PUSHORT lpInBuffer,
+ IN ULONG nInBufferSize,
+ OUT PUSHORT lpOutBuffer,
+ IN ULONG nOutBufferSize
+)
+{
+ USHORT* pInBuf = (USHORT*)lpInBuffer;
+ USHORT* pOutBuf = (USHORT*)lpOutBuffer;
+
+ USHORT Offset = pInBuf[0]; /*addr*/
+ USHORT Length = pInBuf[1]; /*length*/
+ int i;
+
+ for(i=0; i<Length; i+=2)
+ {
+ eFusePhysicalReadRegisters(pAd,Offset+i, 2, &pOutBuf[i/2]);
+ }
+}
+
+/*
+========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+========================================================================
+*/
+NTSTATUS eFuseRead(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ OUT PUSHORT pData,
+ IN USHORT Length)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ UCHAR EFSROM_AOUT;
+ int i;
+
+ for(i=0; i<Length; i+=2)
+ {
+ EFSROM_AOUT = eFuseReadRegisters(pAd, Offset+i, 2, &pData[i/2]);
+ }
+ return Status;
+}
+
+/*
+========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+========================================================================
+*/
+static VOID eFusePhysicalWriteRegisters(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN USHORT Length,
+ OUT USHORT* pData)
+{
+ EFUSE_CTRL_STRUC eFuseCtrlStruc;
+ int i;
+ USHORT efuseDataOffset;
+ UINT32 data, eFuseDataBuffer[4];
+ UINT32 efuse_ctrl_reg = EFUSE_CTRL;
+
+#if defined(RT3290) || defined(RT65xx) || defined(MT7601)
+ if (IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd))
+ efuse_ctrl_reg = EFUSE_CTRL_3290;
+#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) */
+
+ /*Step0. Write 16-byte of data to EFUSE_DATA0-3 (0x590-0x59C), where EFUSE_DATA0 is the LSB DW, EFUSE_DATA3 is the MSB DW.*/
+
+ /*read current values of 16-byte block */
+ RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word);
+
+ /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/
+ eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
+
+ /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1.*/
+ eFuseCtrlStruc.field.EFSROM_MODE = 1;
+
+ /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.*/
+ eFuseCtrlStruc.field.EFSROM_KICK = 1;
+
+ NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
+ RTMP_IO_WRITE32(pAd, efuse_ctrl_reg, data);
+
+ /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.*/
+ i = 0;
+ while(i < 500)
+ {
+ RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word);
+
+ if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
+ break;
+ RTMPusecDelay(2);
+ i++;
+ }
+
+ /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590)*/
+#if defined(RT3290) || defined(RT65xx) || defined(MT7601)
+ if (IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd))
+ efuseDataOffset = EFUSE_DATA0_3290;
+ else
+#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) */
+ efuseDataOffset = EFUSE_DATA3;
+ for(i=0; i< 4; i++)
+ {
+ RTMP_IO_READ32(pAd, efuseDataOffset, (PUINT32) &eFuseDataBuffer[i]);
+#if defined(RT3290) || defined(RT65xx) || defined(MT7601)
+ if (IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd))
+ efuseDataOffset += 4;
+ else
+#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) */
+ efuseDataOffset -= 4;
+ }
+
+ /*Update the value, the offset is multiple of 2, length is 2*/
+ efuseDataOffset = (Offset & 0xc) >> 2;
+ data = pData[0] & 0xffff;
+ /*The offset should be 0x***10 or 0x***00*/
+ if((Offset % 4) != 0)
+ {
+ eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff) | (data << 16);
+ }
+ else
+ {
+ eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff0000) | data;
+ }
+
+#if defined(RT3290) || defined(RT65xx) || defined(MT7601)
+ efuseDataOffset = EFUSE_DATA0;
+#else
+ efuseDataOffset = EFUSE_DATA3;
+#endif
+
+ for(i=0; i< 4; i++)
+ {
+ RTMP_IO_WRITE32(pAd, efuseDataOffset, eFuseDataBuffer[i]);
+#if defined(RT3290) || defined(RT65xx) || defined(MT7601)
+ if (IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd))
+ efuseDataOffset += 4;
+ else
+#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) */
+ efuseDataOffset -= 4;
+ }
+
+ /*Step1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/
+ // TODO: shiang, for below line, windows driver didn't have this read, why we have ??
+ RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word);
+
+ eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
+
+ /*Step2. Write EFSROM_MODE (0x580, bit7:bit6) to 3.*/
+ eFuseCtrlStruc.field.EFSROM_MODE = 3;
+
+ /*Step3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure.*/
+ eFuseCtrlStruc.field.EFSROM_KICK = 1;
+
+ NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
+ RTMP_IO_WRITE32(pAd, efuse_ctrl_reg, data);
+
+ /*Step4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. It¡¦s done.*/
+ i = 0;
+
+ while(i < 500)
+ {
+ RTMP_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word);
+
+ if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
+ break;
+
+ RTMPusecDelay(2);
+ i++;
+ }
+}
+
+/*
+========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+========================================================================
+*/
+static NTSTATUS eFuseWriteRegisters(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN USHORT Length,
+ IN USHORT* pData)
+{
+ USHORT i,Loop=0, StartBlock=0, EndBlock=0;
+ USHORT eFuseData;
+ USHORT LogicalAddress, BlkNum = 0xffff;
+ UCHAR EFSROM_AOUT;
+
+ USHORT addr,tmpaddr, InBuf[3], tmpOffset;
+ USHORT buffer[8];
+ BOOLEAN bWriteSuccess = TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters Offset=%x, pData=%x\n", Offset, *pData));
+ /*set start block and end block number, start from tail of mapping table*/
+ if( (pAd->chipCap.EFUSE_USAGE_MAP_END % 2) != 0)
+ {
+ StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_END-1;
+ }
+ else
+ {
+ StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_END;
+ }
+
+ if( (pAd->chipCap.EFUSE_USAGE_MAP_START % 2) != 0)
+ {
+ EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_START-1;
+ }
+ else
+ {
+ EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_START;
+ }
+ /*Step 0. find the entry in the mapping table*/
+ /*The address of EEPROM is 2-bytes alignment.*/
+ /*The last bit is used for alignment, so it must be 0.*/
+ tmpOffset = Offset & 0xfffe;
+ EFSROM_AOUT = eFuseReadRegisters(pAd, tmpOffset, 2, &eFuseData);
+ if( EFSROM_AOUT == 0x3f)
+ { /*find available logical address pointer */
+ /*the logical address does not exist, find an empty one*/
+ /*from the first address of block 45=16*45=0x2d0 to the last address of block 47*/
+ /*==>48*16-3(reserved)=2FC*/
+ for (i=StartBlock; i >= EndBlock; i-=2)
+ {
+ /*Retrive the logical block nubmer form each logical address pointer*/
+ /*It will access two logical address pointer each time.*/
+ eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
+ /*To avoid the odd byte problem, ex. We read the 21|20 bytes and if 21 is the */
+ /* end byte. Then, the EFUSE_USAGE_MAP_END which is 21 is not equal to*/
+ /* i which is 20. Therefore, this 21th byte could be used.*/
+ /*Otherwise, if 20 is the stop byte, i which is 20 is equal EFUSE_USAGE_MAP_END.*/
+ /* It means the 21th byte could not be used.*/
+ if(( (LogicalAddress >> 8) & 0xff) == 0)
+ {/*Not used logical address pointer*/
+ if (i != pAd->chipCap.EFUSE_USAGE_MAP_END)
+ {
+ BlkNum = i-pAd->chipCap.EFUSE_USAGE_MAP_START+1;
+ break;
+ }
+
+ }
+
+ if( (LogicalAddress & 0xff) == 0)
+ {/*Not used logical address pointer*/
+ if (i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1))
+ {
+ BlkNum = i-pAd->chipCap.EFUSE_USAGE_MAP_START;
+ break;
+ }
+ }
+
+ }
+ }
+ else
+ {
+ BlkNum = EFSROM_AOUT;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum));
+
+ if(BlkNum == 0xffff)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n"));
+ return FALSE;
+ }
+
+ /*Step 1. Save data of this block which is pointed by the avaible logical address pointer*/
+ /* read and save the original block data*/
+ for(i =0; i<8; i++)
+ {
+ addr = BlkNum * 0x10 ;
+
+ InBuf[0] = addr+2*i;
+ InBuf[1] = 2;
+ InBuf[2] = 0x0;
+
+ eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
+
+ buffer[i] = InBuf[2];
+ }
+
+ /*Step 2. Update the data in buffer, and write the data to Efuse*/
+ buffer[ (Offset >> 1) % 8] = pData[0];
+
+ do
+ { Loop++;
+ /*Step 3. Write the data to Efuse*/
+ if(!bWriteSuccess)
+ {
+ for(i =0; i<8; i++)
+ {
+ addr = BlkNum * 0x10 ;
+
+ InBuf[0] = addr+2*i;
+ InBuf[1] = 2;
+ InBuf[2] = buffer[i];
+
+ eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2);
+ }
+ }
+ else
+ {
+ addr = BlkNum * 0x10 ;
+
+ InBuf[0] = addr+(Offset % 16);
+ InBuf[1] = 2;
+ InBuf[2] = pData[0];
+
+ eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2);
+ }
+
+ /*Step 4. Write mapping table*/
+ addr = pAd->chipCap.EFUSE_USAGE_MAP_START+BlkNum;
+
+ tmpaddr = addr;
+
+ if(addr % 2 != 0)
+ addr = addr -1;
+ InBuf[0] = addr;
+ InBuf[1] = 2;
+
+ /*convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry*/
+ tmpOffset = Offset;
+ tmpOffset >>= 4;
+ tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^ (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01))) << 6) & 0x40;
+ tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80;
+
+ /* write the logical address*/
+ if(tmpaddr%2 != 0)
+ InBuf[2] = tmpOffset<<8;
+ else
+ InBuf[2] = tmpOffset;
+
+ eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0);
+
+ /*Step 5. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted*/
+ bWriteSuccess = TRUE;
+ for(i =0; i<8; i++)
+ {
+ addr = BlkNum * 0x10 ;
+
+ InBuf[0] = addr+2*i;
+ InBuf[1] = 2;
+ InBuf[2] = 0x0;
+
+ eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
+
+ if(buffer[i] != InBuf[2])
+ {
+ bWriteSuccess = FALSE;
+ break;
+ }
+ }
+
+ /*Step 6. invlidate mapping entry and find a free mapping entry if not succeed*/
+ if (!bWriteSuccess)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess BlkNum = %d\n", BlkNum));
+
+ /* the offset of current mapping entry*/
+ addr = pAd->chipCap.EFUSE_USAGE_MAP_START+BlkNum;
+
+ /*find a new mapping entry*/
+ BlkNum = 0xffff;
+ for (i=StartBlock; i >= EndBlock; i-=2)
+ {
+ eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
+ if(( (LogicalAddress >> 8) & 0xff) == 0)
+ {
+ if(i != pAd->chipCap.EFUSE_USAGE_MAP_END)
+ {
+ BlkNum = i+1-pAd->chipCap.EFUSE_USAGE_MAP_START;
+ break;
+ }
+ }
+
+ if( (LogicalAddress & 0xff) == 0)
+ {
+ if(i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1))
+ {
+ BlkNum = i-pAd->chipCap.EFUSE_USAGE_MAP_START;
+ break;
+ }
+ }
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess and allocate new BlkNum = %d\n", BlkNum));
+ if(BlkNum == 0xffff)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n"));
+ return FALSE;
+ }
+
+ /*invalidate the original mapping entry if new entry is not found*/
+ tmpaddr = addr;
+
+ if(addr % 2 != 0)
+ addr = addr -1;
+ InBuf[0] = addr;
+ InBuf[1] = 2;
+
+ eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
+
+ /* write the logical address*/
+ if(tmpaddr%2 != 0)
+ {
+ /* Invalidate the high byte*/
+ for (i=8; i<15; i++)
+ {
+ if( ( (InBuf[2] >> i) & 0x01) == 0)
+ {
+ InBuf[2] |= (0x1 <<i);
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* invalidate the low byte*/
+ for (i=0; i<8; i++)
+ {
+ if( ( (InBuf[2] >> i) & 0x01) == 0)
+ {
+ InBuf[2] |= (0x1 <<i);
+ break;
+ }
+ }
+ }
+ eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 0);
+ }
+ }
+ while (!bWriteSuccess&&Loop<2);
+ if(!bWriteSuccess)
+ DBGPRINT(RT_DEBUG_ERROR,("Efsue Write Failed!!\n"));
+ return TRUE;
+}
+
+
+/*
+========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+========================================================================
+*/
+static VOID eFuseWritePhysical(
+ IN PRTMP_ADAPTER pAd,
+ PUSHORT lpInBuffer,
+ ULONG nInBufferSize,
+ PUCHAR lpOutBuffer,
+ ULONG nOutBufferSize
+)
+{
+ USHORT* pInBuf = (USHORT*)lpInBuffer;
+ int i;
+ /*USHORT* pOutBuf = (USHORT*)ioBuffer;*/
+ USHORT Offset = pInBuf[0]; /* addr*/
+ USHORT Length = pInBuf[1]; /* length*/
+ USHORT* pValueX = &pInBuf[2]; /* value ... */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseWritePhysical Offset=0x%x, length=%d\n", Offset, Length));
+
+ {
+ /* Little-endian S | S Big-endian*/
+ /* addr 3 2 1 0 | 0 1 2 3*/
+ /* Ori-V D C B A | A B C D*/
+ /* After swapping*/
+ /* D C B A | D C B A*/
+ /* Both the little and big-endian use the same sequence to write data.*/
+ /* Therefore, we only need swap data when read the data.*/
+ for (i=0; i<Length; i+=2)
+ {
+ eFusePhysicalWriteRegisters(pAd, Offset+i, 2, &pValueX[i/2]);
+ }
+ }
+}
+
+
+/*
+========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+========================================================================
+*/
+NTSTATUS eFuseWrite(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN PUSHORT pData,
+ IN USHORT length)
+{
+ int i;
+ USHORT* pValueX = (PUSHORT) pData; /*value ... */
+ PUSHORT OddWriteByteBuf;
+/* OddWriteByteBuf=(PUSHORT)kmalloc(sizeof(USHORT)*2, MEM_ALLOC_FLAG);*/
+ os_alloc_mem(NULL, (UCHAR **)&OddWriteByteBuf, sizeof(USHORT)*2);
+ /* The input value=3070 will be stored as following*/
+ /* Little-endian S | S Big-endian*/
+ /* addr 1 0 | 0 1 */
+ /* Ori-V 30 70 | 30 70 */
+ /* After swapping*/
+ /* 30 70 | 70 30*/
+ /* Casting*/
+ /* 3070 | 7030 (x)*/
+ /* The swapping should be removed for big-endian*/
+ if (OddWriteByteBuf == NULL)
+ return FALSE;
+ if((Offset%2)!=0)
+ {
+ length+=2;
+ Offset-=1;
+ eFuseRead(pAd,Offset,OddWriteByteBuf,2);
+ eFuseRead(pAd,Offset+2,(OddWriteByteBuf+1),2);
+ *OddWriteByteBuf&=0x00ff;
+ *OddWriteByteBuf|=((*pData)&0xff)<<8;
+ *(OddWriteByteBuf+1)&=0xff00;
+ *(OddWriteByteBuf+1)|=(*pData&0xff00)>>8;
+ pValueX=OddWriteByteBuf;
+
+ }
+
+ for(i=0; i<length; i+=2)
+ {
+ eFuseWriteRegisters(pAd, Offset+i, 2, &pValueX[i/2]);
+ }
+/* kfree(OddWriteByteBuf);*/
+ os_free_mem(NULL, OddWriteByteBuf);
+ return TRUE;
+}
+
+
+/*
+========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+========================================================================
+*/
+INT set_eFuseGetFreeBlockCount_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UINT efusefreenum=0;
+ if (pAd->bUseEfuse == FALSE && pAd->bFroceEEPROMBuffer == FALSE)
+ return FALSE;
+ eFuseGetFreeBlockCount(pAd,&efusefreenum);
+ printk("efuseFreeNumber is %d\n",efusefreenum);
+ return TRUE;
+}
+
+
+INT set_eFusedump_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ USHORT InBuf[3];
+ INT i=0;
+
+ if (pAd->bUseEfuse == FALSE && pAd->bFroceEEPROMBuffer == FALSE)
+ return FALSE;
+
+ for(i =0; i<pAd->chipCap.EFUSE_USAGE_MAP_END/2; i++)
+ {
+ InBuf[0] = 2*i;
+ InBuf[1] = 2;
+ InBuf[2] = 0x0;
+
+ eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
+ if(i%4==0)
+ printk("\nBlock %x:",i/8);
+ printk("%04x ",InBuf[2]);
+ }
+ return TRUE;
+}
+
+
+INT set_eFuseLoadFromBin_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PSTRING src;
+ RTMP_OS_FD srcf;
+ RTMP_OS_FS_INFO osfsInfo;
+ INT retval, memSize;
+ PSTRING buffer, memPtr;
+ INT TotalByte= 0,ReadedByte=0,CompareBuf=1;
+ USHORT *PDATA;
+ USHORT DATA;
+
+ memSize = 128 + MAX_EEPROM_BIN_FILE_SIZE + sizeof(USHORT) * 8;
+/* memPtr = kmalloc(memSize, MEM_ALLOC_FLAG);*/
+ os_alloc_mem(NULL, (UCHAR **)&memPtr, memSize);
+ if (memPtr == NULL)
+ return FALSE;
+
+ NdisZeroMemory(memPtr, memSize);
+ src = memPtr; /* kmalloc(128, MEM_ALLOC_FLAG);*/
+ buffer = src + 128; /* kmalloc(MAX_EEPROM_BIN_FILE_SIZE, MEM_ALLOC_FLAG);*/
+ PDATA = (USHORT*)(buffer + MAX_EEPROM_BIN_FILE_SIZE); /* kmalloc(sizeof(USHORT)*8,MEM_ALLOC_FLAG);*/
+
+ if(strlen(arg)>0)
+ NdisMoveMemory(src, arg, strlen(arg));
+ else
+ NdisMoveMemory(src, EFUSE_EEPROM_DEFULT_FILE, strlen(EFUSE_EEPROM_DEFULT_FILE));
+ DBGPRINT(RT_DEBUG_OFF, ("FileName=%s\n",src));
+
+ RtmpOSFSInfoChange(&osfsInfo, TRUE);
+
+ srcf = RtmpOSFileOpen(src, O_RDONLY, 0);
+ if (IS_FILE_OPEN_ERR(srcf))
+ {
+ DBGPRINT_ERR(("--> Error opening file %s\n", src));
+ retval = FALSE;
+ goto recoverFS;
+ }
+ else
+ {
+ /* The object must have a read method*/
+ while(RtmpOSFileRead(srcf, &buffer[TotalByte], 1)==1)
+ {
+ TotalByte++;
+ if(TotalByte>MAX_EEPROM_BIN_FILE_SIZE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("--> Error reading file %s, file size too large[>%d]\n", src, MAX_EEPROM_BIN_FILE_SIZE));
+ retval = FALSE;
+ goto closeFile;
+ }
+ }
+
+ retval = RtmpOSFileClose(srcf);
+ if (retval)
+ DBGPRINT(RT_DEBUG_TRACE, ("--> Error closing file %s\n", src));
+ }
+
+
+ RtmpOSFSInfoChange(&osfsInfo, FALSE);
+
+ for(ReadedByte=0;ReadedByte<TotalByte;ReadedByte++)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%02X ",buffer[ReadedByte]&0xff));
+ if((ReadedByte+1)%2==0)
+ PDATA[ReadedByte/2%8]=((buffer[ReadedByte]<<8)&0xff00)|(buffer[ReadedByte-1]&0xff);
+ if(ReadedByte%16==0)
+ {
+ CompareBuf=buffer[ReadedByte]&0xff;
+
+ }
+ else
+ {
+ CompareBuf&=(buffer[ReadedByte]&0xff);
+ if((ReadedByte+1)%16==0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, (" result=%02X,blk=%02x\n",CompareBuf,ReadedByte/16));
+
+ if(CompareBuf!=0xff)
+ eFuseWriteRegistersFromBin(pAd,(USHORT)ReadedByte-15, 16, PDATA);
+ else
+ {
+ if(eFuseReadRegisters(pAd,ReadedByte, 2,(PUSHORT)&DATA)!=0x3f)
+ eFuseWriteRegistersFromBin(pAd,(USHORT)ReadedByte-15, 16, PDATA);
+ }
+ /*
+ for(l=0;l<8;l++)
+ printk("%04x ",PDATA[l]);
+ printk("\n");
+ */
+ NdisZeroMemory(PDATA,16);
+ }
+ }
+ }
+
+ return TRUE;
+
+closeFile:
+ if (srcf)
+ if (RtmpOSFileClose(srcf) != 0)
+ retval = FALSE;
+
+recoverFS:
+ RtmpOSFSInfoChange(&osfsInfo, FALSE);
+
+
+ if (memPtr)
+/* kfree(memPtr);*/
+ os_free_mem(NULL, memPtr);
+
+ return retval;
+}
+
+
+static NTSTATUS eFuseWriteRegistersFromBin(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN USHORT Length,
+ IN USHORT* pData)
+{
+ USHORT i,StartBlock=0,EndBlock=0;
+ USHORT eFuseData;
+ USHORT LogicalAddress, BlkNum = 0xffff;
+ UCHAR EFSROM_AOUT,Loop=0;
+ EFUSE_CTRL_STRUC eFuseCtrlStruc;
+ USHORT efuseDataOffset;
+ UINT32 data,tempbuffer;
+ USHORT addr,tmpaddr, InBuf[3], tmpOffset;
+ UINT32 buffer[4];
+ BOOLEAN bWriteSuccess = TRUE;
+ BOOLEAN bNotWrite=TRUE;
+ BOOLEAN bAllocateNewBlk=TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin Offset=%x, pData=%04x:%04x:%04x:%04x\n", Offset, *pData,*(pData+1),*(pData+2),*(pData+3)));
+ /*set start block and end block number, start from tail of mapping table*/
+ if( (pAd->chipCap.EFUSE_USAGE_MAP_END % 2) != 0)
+ {
+ StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_END-1;
+ }
+ else
+ {
+ StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_END;
+ }
+
+ if( (pAd->chipCap.EFUSE_USAGE_MAP_START % 2) != 0)
+ {
+ EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_START-1;
+ }
+ else
+ {
+ EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_START;
+ }
+
+ do
+ {
+ /*Step 0. find the entry in the mapping table*/
+ /*The address of EEPROM is 2-bytes alignment.*/
+ /*The last bit is used for alignment, so it must be 0.*/
+ Loop++;
+ tmpOffset = Offset & 0xfffe;
+ EFSROM_AOUT = eFuseReadRegisters(pAd, tmpOffset, 2, &eFuseData);
+
+ if( EFSROM_AOUT == 0x3f)
+ { /*find available logical address pointer */
+ /*the logical address does not exist, find an empty one*/
+ /*from the first address of block 45=16*45=0x2d0 to the last address of block 47*/
+ /*==>48*16-3(reserved)=2FC*/
+ bAllocateNewBlk=TRUE;
+ for (i=StartBlock; i>=EndBlock; i-=2)
+ {
+ /*Retrive the logical block nubmer form each logical address pointer*/
+ /*It will access two logical address pointer each time.*/
+ eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
+ if(( (LogicalAddress >> 8) & 0xff) == 0)
+ {
+ if(i != pAd->chipCap.EFUSE_USAGE_MAP_END)
+ {
+ BlkNum = i+1-pAd->chipCap.EFUSE_USAGE_MAP_START;
+ break;
+ }
+ }
+
+ if( (LogicalAddress & 0xff) == 0)
+ {
+ if(i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1))
+ {
+ BlkNum = i-pAd->chipCap.EFUSE_USAGE_MAP_START;
+ break;
+ }
+ }
+
+ }
+ }
+ else
+ {
+ bAllocateNewBlk=FALSE;
+ BlkNum = EFSROM_AOUT;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum));
+
+ if(BlkNum == 0xffff)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n"));
+ return FALSE;
+ }
+ /*Step 1.1.0*/
+ /*If the block is not existing in mapping table, create one */
+ /*and write down the 16-bytes data to the new block*/
+ if(bAllocateNewBlk)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Allocate New Blk\n"));
+ efuseDataOffset = EFUSE_DATA3;
+ for(i=0; i< 4; i++)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Allocate New Blk, Data%d=%04x%04x\n",3-i,pData[2*i+1],pData[2*i]));
+ tempbuffer=((pData[2*i+1]<<16)&0xffff0000)|pData[2*i];
+
+
+ RTMP_IO_WRITE32(pAd, efuseDataOffset,tempbuffer);
+ efuseDataOffset -= 4;
+
+ }
+
+ /*Step1.1.1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/
+ RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
+ eFuseCtrlStruc.field.EFSROM_AIN = BlkNum* 0x10 ;
+
+ /*Step1.1.2. Write EFSROM_MODE (0x580, bit7:bit6) to 3.*/
+ eFuseCtrlStruc.field.EFSROM_MODE = 3;
+
+ /*Step1.1.3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure.*/
+ eFuseCtrlStruc.field.EFSROM_KICK = 1;
+
+ NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
+
+ RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
+
+ /*Step1.1.4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. It¡¦s done.*/
+ i = 0;
+ while(i < 100)
+ {
+ RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc);
+
+ if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
+ break;
+
+ RTMPusecDelay(2);
+ i++;
+ }
+
+ }
+ else
+ { /*Step1.2.*/
+ /*If the same logical number is existing, check if the writting data and the data */
+ /*saving in this block are the same.*/
+ /*read current values of 16-byte block */
+ RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word);
+
+ /*Step1.2.0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/
+ eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0;
+
+ /*Step1.2.1. Write EFSROM_MODE (0x580, bit7:bit6) to 1.*/
+ eFuseCtrlStruc.field.EFSROM_MODE = 0;
+
+ /*Step1.2.2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.*/
+ eFuseCtrlStruc.field.EFSROM_KICK = 1;
+
+ NdisMoveMemory(&data, &eFuseCtrlStruc, 4);
+ RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data);
+
+ /*Step1.2.3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.*/
+ i = 0;
+ while(i < 500)
+ {
+ RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc);
+
+ if(eFuseCtrlStruc.field.EFSROM_KICK == 0)
+ break;
+ RTMPusecDelay(2);
+ i++;
+ }
+
+ /*Step1.2.4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590)*/
+ efuseDataOffset = EFUSE_DATA3;
+ for(i=0; i< 4; i++)
+ {
+ RTMP_IO_READ32(pAd, efuseDataOffset, (PUINT32) &buffer[i]);
+ efuseDataOffset -= 4;
+ }
+ /*Step1.2.5. Check if the data of efuse and the writing data are the same.*/
+ for(i =0; i<4; i++)
+ {
+ tempbuffer=((pData[2*i+1]<<16)&0xffff0000)|pData[2*i];
+ DBGPRINT(RT_DEBUG_TRACE, ("buffer[%d]=%x,pData[%d]=%x,pData[%d]=%x,tempbuffer=%x\n",i,buffer[i],2*i,pData[2*i],2*i+1,pData[2*i+1],tempbuffer));
+
+ if(((buffer[i]&0xffff0000)==(pData[2*i+1]<<16))&&((buffer[i]&0xffff)==pData[2*i]))
+ bNotWrite&=TRUE;
+ else
+ {
+ bNotWrite&=FALSE;
+ break;
+ }
+ }
+ if(!bNotWrite)
+ {
+ printk("The data is not the same\n");
+
+ for(i =0; i<8; i++)
+ {
+ addr = BlkNum * 0x10 ;
+
+ InBuf[0] = addr+2*i;
+ InBuf[1] = 2;
+ InBuf[2] = pData[i];
+
+ eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2);
+ }
+
+ }
+ else
+ return TRUE;
+ }
+
+
+
+ /*Step 2. Write mapping table*/
+ addr = pAd->chipCap.EFUSE_USAGE_MAP_START+BlkNum;
+
+ tmpaddr = addr;
+
+ if(addr % 2 != 0)
+ addr = addr -1;
+ InBuf[0] = addr;
+ InBuf[1] = 2;
+
+ /*convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry*/
+ tmpOffset = Offset;
+ tmpOffset >>= 4;
+ tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^ (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01))) << 6) & 0x40;
+ tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80;
+
+ /* write the logical address*/
+ if(tmpaddr%2 != 0)
+ InBuf[2] = tmpOffset<<8;
+ else
+ InBuf[2] = tmpOffset;
+
+ eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0);
+
+ /*Step 3. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted*/
+ bWriteSuccess = TRUE;
+ for(i =0; i<8; i++)
+ {
+ addr = BlkNum * 0x10 ;
+
+ InBuf[0] = addr+2*i;
+ InBuf[1] = 2;
+ InBuf[2] = 0x0;
+
+ eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
+ DBGPRINT(RT_DEBUG_TRACE, ("addr=%x, buffer[i]=%x,InBuf[2]=%x\n",InBuf[0],pData[i],InBuf[2]));
+ if(pData[i] != InBuf[2])
+ {
+ bWriteSuccess = FALSE;
+ break;
+ }
+ }
+
+ /*Step 4. invlidate mapping entry and find a free mapping entry if not succeed*/
+
+ if (!bWriteSuccess&&Loop<2)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin::Not bWriteSuccess BlkNum = %d\n", BlkNum));
+
+ /* the offset of current mapping entry*/
+ addr = pAd->chipCap.EFUSE_USAGE_MAP_START+BlkNum;
+
+ /*find a new mapping entry*/
+ BlkNum = 0xffff;
+ for (i=StartBlock; i>=EndBlock; i-=2)
+ {
+ /*Retrive the logical block nubmer form each logical address pointer*/
+ /*It will access two logical address pointer each time.*/
+ eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
+ if(( (LogicalAddress >> 8) & 0xff) == 0)
+ {
+ if(i !=pAd->chipCap.EFUSE_USAGE_MAP_END)
+ {
+ BlkNum = i+1-pAd->chipCap.EFUSE_USAGE_MAP_START;
+ break;
+ }
+ }
+
+ if( (LogicalAddress & 0xff) == 0)
+ {
+ if(i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1))
+ {
+ BlkNum = i-pAd->chipCap.EFUSE_USAGE_MAP_START;
+ break;
+ }
+ }
+
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin::Not bWriteSuccess new BlkNum = %d\n", BlkNum));
+ if(BlkNum == 0xffff)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin: out of free E-fuse space!!!\n"));
+ return FALSE;
+ }
+
+ /*invalidate the original mapping entry if new entry is not found*/
+ tmpaddr = addr;
+
+ if(addr % 2 != 0)
+ addr = addr -1;
+ InBuf[0] = addr;
+ InBuf[1] = 2;
+
+ eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2);
+
+ /* write the logical address*/
+ if(tmpaddr%2 != 0)
+ {
+ /* Invalidate the high byte*/
+ for (i=8; i<15; i++)
+ {
+ if( ( (InBuf[2] >> i) & 0x01) == 0)
+ {
+ InBuf[2] |= (0x1 <<i);
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* invalidate the low byte*/
+ for (i=0; i<8; i++)
+ {
+ if( ( (InBuf[2] >> i) & 0x01) == 0)
+ {
+ InBuf[2] |= (0x1 <<i);
+ break;
+ }
+ }
+ }
+ eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 0);
+ }
+
+ }
+ while(!bWriteSuccess&&Loop<2);
+
+ return TRUE;
+}
+
+
+int rtmp_ee_efuse_read16(
+ IN RTMP_ADAPTER *pAd,
+ IN USHORT Offset,
+ OUT USHORT *pValue)
+{
+
+ if (pAd->bFroceEEPROMBuffer
+#ifdef RALINK_ATE
+ ||pAd->bEEPROMFile
+#endif /* RALINK_ATE */
+ )
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Read from EEPROM Buffer\n"));
+ NdisMoveMemory(pValue, &(pAd->EEPROMImage[Offset]), 2);
+ *pValue = le2cpu16(*pValue);
+ }
+ else
+ eFuseReadRegisters(pAd, Offset, 2, pValue);
+ return (*pValue);
+}
+
+
+int rtmp_ee_efuse_write16(
+ IN RTMP_ADAPTER *pAd,
+ IN USHORT Offset,
+ IN USHORT data)
+{
+ if (pAd->bFroceEEPROMBuffer
+#ifdef RALINK_ATE
+ ||pAd->bEEPROMFile
+#endif /* RALINK_ATE */
+ )
+ {
+ data = le2cpu16(data);
+ DBGPRINT(RT_DEBUG_TRACE, ("Write to EEPROM Buffer\n"));
+ NdisMoveMemory(&(pAd->EEPROMImage[Offset]), &data, 2);
+ }
+ else
+ eFuseWrite(pAd,Offset ,&data, 2);
+ return 0;
+}
+
+
+int RtmpEfuseSupportCheck(
+ IN RTMP_ADAPTER *pAd)
+{
+ USHORT value;
+
+ if (IS_RT30xx(pAd) || IS_RT3593(pAd))
+ {
+ eFusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value);
+ pAd->EFuseTag = (value & 0xff);
+ }
+ return 0;
+}
+
+
+#ifdef RALINK_ATE
+INT set_eFuseBufferModeWriteBack_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UINT Enable;
+
+
+ if(strlen(arg)>0)
+ {
+ Enable= simple_strtol(arg, 0, 16);
+ }
+ else
+ return FALSE;
+ if(Enable==1)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("set_eFuseBufferMode_Proc:: Call WRITEEEPROMBUF"));
+ eFuseWriteEeeppromBuf(pAd);
+ }
+ else
+ return FALSE;
+ return TRUE;
+}
+#endif /* RALINK_ATE */
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Load EEPROM from bin file for eFuse mode
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ NDIS_STATUS_SUCCESS firmware image load ok
+ NDIS_STATUS_FAILURE image not found
+
+ IRQL = PASSIVE_LEVEL
+
+ ========================================================================
+*/
+INT eFuseLoadEEPROM(
+ IN PRTMP_ADAPTER pAd)
+{
+ PSTRING src = NULL;
+ INT retval;
+ RTMP_OS_FD srcf;
+ RTMP_OS_FS_INFO osFSInfo;
+
+
+ src=EFUSE_BUFFER_PATH;
+ DBGPRINT(RT_DEBUG_TRACE, ("FileName=%s\n",src));
+
+
+ RtmpOSFSInfoChange(&osFSInfo, TRUE);
+
+ if (src && *src)
+ {
+ srcf = RtmpOSFileOpen(src, O_RDONLY, 0);
+ if (IS_FILE_OPEN_ERR(srcf))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("--> Error opening %s\n", src));
+ return FALSE;
+ }
+ else
+ {
+
+ memset(pAd->EEPROMImage, 0x00, MAX_EEPROM_BIN_FILE_SIZE);
+
+
+ retval =RtmpOSFileRead(srcf, (PSTRING)pAd->EEPROMImage, MAX_EEPROM_BIN_FILE_SIZE);
+ if (retval > 0)
+ {
+
+ retval = NDIS_STATUS_SUCCESS;
+ }
+ else
+ DBGPRINT(RT_DEBUG_ERROR, ("Read file \"%s\" failed(errCode=%d)!\n", src, retval));
+
+ }
+
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("--> Error src or srcf is null\n"));
+ return FALSE;
+
+ }
+
+ retval=RtmpOSFileClose(srcf);
+
+ if (retval)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src));
+ }
+
+
+ RtmpOSFSInfoChange(&osFSInfo, FALSE);
+
+ return TRUE;
+}
+
+INT eFuseWriteEeeppromBuf(
+ IN PRTMP_ADAPTER pAd)
+{
+
+ PSTRING src = NULL;
+ INT retval;
+ RTMP_OS_FD srcf;
+ RTMP_OS_FS_INFO osFSInfo;
+
+
+ src=EFUSE_BUFFER_PATH;
+ DBGPRINT(RT_DEBUG_TRACE, ("FileName=%s\n",src));
+
+ RtmpOSFSInfoChange(&osFSInfo, TRUE);
+
+
+
+ if (src && *src)
+ {
+ srcf = RtmpOSFileOpen(src, O_WRONLY|O_CREAT, 0);
+
+ if (IS_FILE_OPEN_ERR(srcf))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("--> Error opening %s\n", src));
+ return FALSE;
+ }
+ else
+ {
+
+ RtmpOSFileWrite(srcf, (PSTRING)pAd->EEPROMImage,MAX_EEPROM_BIN_FILE_SIZE);
+
+ }
+
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("--> Error src or srcf is null\n"));
+ return FALSE;
+
+ }
+
+ retval=RtmpOSFileClose(srcf);
+
+ if (retval)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src));
+ }
+
+ RtmpOSFSInfoChange(&osFSInfo, FALSE);
+ return TRUE;
+}
+
+
+VOID eFuseGetFreeBlockCount(IN PRTMP_ADAPTER pAd,
+ PUINT EfuseFreeBlock)
+{
+
+ USHORT i=0, StartBlock=0, EndBlock=0;
+ USHORT LogicalAddress;
+ USHORT FirstFreeBlock = 0xffff, LastFreeBlock = 0xffff;
+
+ if(!pAd->bUseEfuse)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("eFuseGetFreeBlockCount Only supports efuse Mode\n"));
+ return ;
+ }
+ *EfuseFreeBlock = 0;
+ /* find first free block*/
+ if( (pAd->chipCap.EFUSE_USAGE_MAP_START % 2) != 0)
+ {
+ StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_START-1;
+ }
+ else
+ {
+ StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_START;
+ }
+
+ if( (pAd->chipCap.EFUSE_USAGE_MAP_END % 2) != 0)
+ {
+ EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_END-1;
+ }
+ else
+ {
+ EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_END;
+ }
+
+ for (i = StartBlock; i <= EndBlock; i+=2)
+ {
+ eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
+
+ if( (LogicalAddress & 0xff) == 0)
+ {
+ if(i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1))
+ {
+ FirstFreeBlock = i;
+ break;
+ }
+ }
+
+ if(( (LogicalAddress >> 8) & 0xff) == 0)
+ {
+ if(i != pAd->chipCap.EFUSE_USAGE_MAP_END)
+ {
+ FirstFreeBlock = i+1;
+ break;
+ }
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseGetFreeBlockCount, FirstFreeBlock= 0x%x\n", FirstFreeBlock));
+
+ /*if not find, return free block number = 0*/
+ if(FirstFreeBlock == 0xffff)
+ {
+ *EfuseFreeBlock = 0;
+ return;
+ }
+ for (i = EndBlock; i >= StartBlock; i-=2)
+ {
+ eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress);
+
+ if(( (LogicalAddress >> 8) & 0xff) == 0)
+ {
+ if(i != pAd->chipCap.EFUSE_USAGE_MAP_END)
+ {
+ LastFreeBlock = i+1;
+ break;
+ }
+ }
+
+ if( (LogicalAddress & 0xff) == 0)
+ {
+ if(i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1))
+ {
+ LastFreeBlock = i;
+ break;
+ }
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("eFuseGetFreeBlockCount, LastFreeBlock= 0x%x\n", LastFreeBlock));
+
+ /*if not find last free block, return free block number = 0, this should not happen since we have checked first free block number previously*/
+ if(LastFreeBlock == 0xffff)
+ {
+ *EfuseFreeBlock = 0;
+ return;
+ }
+
+ /* return total free block number, last free block number must >= first free block number*/
+ if(LastFreeBlock < FirstFreeBlock)
+ {
+ *EfuseFreeBlock = 0;
+ }
+ else
+ {
+ *EfuseFreeBlock = LastFreeBlock - FirstFreeBlock + 1;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("eFuseGetFreeBlockCount is %d\n",*EfuseFreeBlock));
+}
+
+
+INT eFuse_init(RTMP_ADAPTER *pAd)
+{
+ UINT EfuseFreeBlock=0;
+
+ /*RT3572 means 3062/3562/3572*/
+ /*3593 means 3593*/
+ DBGPRINT(RT_DEBUG_ERROR, ("NVM is Efuse and its size =%x[%x-%x] \n",pAd->chipCap.EFUSE_USAGE_MAP_SIZE,pAd->chipCap.EFUSE_USAGE_MAP_START,pAd->chipCap.EFUSE_USAGE_MAP_END));
+ eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock);
+ /*If the used block of efuse is less than 5. We assume the default value*/
+ /* of this efuse is empty and change to the buffer mode in odrder to */
+ /*bring up interfaces successfully.*/
+
+
+ if(EfuseFreeBlock > (pAd->chipCap.EFUSE_USAGE_MAP_SIZE-5))
+ {
+ int ret;
+ DBGPRINT(RT_DEBUG_ERROR, ("NVM is Efuse and the information is too less to bring up interface. Force to use EEPROM Buffer Mode\n"));
+ pAd->bFroceEEPROMBuffer = TRUE;
+ ret = eFuseLoadEEPROM(pAd);
+
+ if ( ret == FALSE )
+ {
+ if ( pAd->chipCap.EFUSE_DEFAULT_BIN != NULL )
+ {
+ NdisMoveMemory(pAd->EEPROMImage, pAd->chipCap.EFUSE_DEFAULT_BIN, pAd->chipCap.EFUSE_DEFAULT_BIN_SIZE);
+ }
+ }
+
+#ifdef MT7601
+ if ( IS_MT7601(pAd) )
+ {
+ UINT16 NicConfig, FrequencyOffset;
+ UINT16 EfuseValue;
+
+ eFuseReadRegisters(pAd, EEPROM_FREQ_OFFSET, 2, &FrequencyOffset);
+ eFuseReadRegisters(pAd, EEPROM_NIC1_OFFSET, 2, &NicConfig);
+
+ if ( (NicConfig == 0x0) && ( FrequencyOffset != 0xFFFF ) )
+ {
+ /* Calibration Free IC, but E-Fuse is empty */
+ DBGPRINT(RT_DEBUG_OFF, ("Calibration Free IC, Load calibration data...\n"));
+
+ pAd->EEPROMImage[EEPROM_FREQ_OFFSET] = (UCHAR)(FrequencyOffset & 0xFF);
+
+ eFuseReadRegisters(pAd, EEPROM_TX0_TSSI_SLOPE, 2, &EfuseValue);
+ *(UINT16 *)(&pAd->EEPROMImage[EEPROM_TX0_TSSI_SLOPE]) = EfuseValue;
+ eFuseReadRegisters(pAd, EEPROM_TX0_TSSI_OFFSET_GROUP1, 2, &EfuseValue);
+ *(UINT16 *)(&pAd->EEPROMImage[EEPROM_TX0_TSSI_OFFSET_GROUP1]) = EfuseValue;
+ eFuseReadRegisters(pAd, EEPROM_TX0_TSSI_OFFSET, 2, &EfuseValue);
+ pAd->EEPROMImage[EEPROM_TX0_TSSI_OFFSET] = (UCHAR)(EfuseValue & 0xFF);;
+
+ eFuseReadRegisters(pAd, EEPROM_G_TARGET_POWER, 2, &EfuseValue);
+ pAd->EEPROMImage[EEPROM_G_TARGET_POWER + 1] = (UCHAR)(EfuseValue >> 8);
+
+ pAd->bCalFreeIC = TRUE;
+ }
+ else
+ {
+ pAd->bCalFreeIC = FALSE;
+ }
+ }
+#endif /* MT7601 */
+
+ }
+ else
+ {
+ pAd->bFroceEEPROMBuffer = FALSE;
+ pAd->bCalFreeIC = FALSE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("NVM is Efuse and force to use EEPROM Buffer Mode=%x\n",pAd->bFroceEEPROMBuffer));
+
+ // alan debug
+ //pAd->bFroceEEPROMBuffer = TRUE;
+ //eFuseLoadEEPROM(pAd);
+
+ return 0;
+}
+
+
+INT efuse_probe(RTMP_ADAPTER *pAd)
+{
+ UINT32 eFuseCtrl, ctrl_reg;
+
+
+ if (WaitForAsicReady(pAd) == FALSE)
+ return -1;
+
+ pAd->bUseEfuse=FALSE;
+#ifdef RT65xx
+ // TODO: shiang-6590, find a better naming for EFUSE_CTRL_3290!!
+ if (IS_RT65XX(pAd))
+ ctrl_reg = EFUSE_CTRL_3290;
+ else
+#endif /* RT65xx */
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ ctrl_reg = EFUSE_CTRL_3290;
+ else
+#endif /* MT7601 */
+#ifdef RT3290
+ if (IS_RT3290(pAd))
+ ctrl_reg = EFUSE_CTRL_3290;
+ else
+#endif /* RT3290 */
+ ctrl_reg = EFUSE_CTRL;
+ RTMP_IO_READ32(pAd, ctrl_reg, &eFuseCtrl);
+
+ //pAd->bUseEfuse = ( (eFuseCtrl & 0x80000000) == 0x80000000) ? 1 : 0;
+
+ pAd->bUseEfuse = TRUE;
+
+ return 0;
+}
+
+
+#ifdef RALINK_ATE
+INT Set_LoadEepromBufferFromEfuse_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UINT bEnable = simple_strtol(arg, 0, 10);
+ UINT free_blk = 0;
+
+ if (bEnable < 0)
+ return FALSE;
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Load EEPROM buffer from efuse, and change to BIN buffer mode\n"));
+
+ /* If the number of the used block is less than 5, assume the efuse is not well-calibrated, and force to use buffer mode */
+ eFuseGetFreeBlockCount(pAd, &free_blk);
+ if (free_blk > (pAd->chipCap.EFUSE_USAGE_MAP_SIZE - 5))
+ return FALSE;
+
+ NdisZeroMemory(pAd->EEPROMImage, MAX_EEPROM_BIN_FILE_SIZE);
+ eFuseRead(pAd, 0, (PUSHORT)&pAd->EEPROMImage[0], MAX_EEPROM_BIN_FILE_SIZE);
+
+ /* Change to BIN eeprom buffer mode */
+ pAd->bFroceEEPROMBuffer = TRUE;
+
+ return TRUE;
+ }
+}
+#endif /* RALINK_ATE */
+
+
+#endif /* RTMP_EFUSE_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/ee_prom.c b/cleopatre/devkit/mt7601udrv/common/ee_prom.c
new file mode 100644
index 0000000000..a40a03a1d2
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/ee_prom.c
@@ -0,0 +1,265 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ ee_prom.c
+
+ Abstract:
+ Miniport generic portion header file
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+*/
+
+
+#include "rt_config.h"
+
+
+
+/* IRQL = PASSIVE_LEVEL*/
+static inline VOID RaiseClock(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT32 *x)
+{
+ *x = *x | EESK;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
+ RTMPusecDelay(1); /* Max frequency = 1MHz in Spec. definition */
+}
+
+/* IRQL = PASSIVE_LEVEL*/
+static inline VOID LowerClock(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT32 *x)
+{
+ *x = *x & ~EESK;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
+ RTMPusecDelay(1);
+}
+
+/* IRQL = PASSIVE_LEVEL*/
+static inline USHORT ShiftInBits(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 x,i;
+ USHORT data=0;
+
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+ x &= ~( EEDO | EEDI);
+
+ for(i=0; i<16; i++)
+ {
+ data = data << 1;
+ RaiseClock(pAd, &x);
+
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+ LowerClock(pAd, &x); /*prevent read failed*/
+
+ x &= ~(EEDI);
+ if(x & EEDO)
+ data |= 1;
+ }
+
+ return data;
+}
+
+
+/* IRQL = PASSIVE_LEVEL*/
+static inline VOID ShiftOutBits(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT data,
+ IN USHORT count)
+{
+ UINT32 x,mask;
+
+ mask = 0x01 << (count - 1);
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+ x &= ~(EEDO | EEDI);
+
+ do
+ {
+ x &= ~EEDI;
+ if(data & mask) x |= EEDI;
+
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+ RaiseClock(pAd, &x);
+ LowerClock(pAd, &x);
+
+ mask = mask >> 1;
+ } while(mask);
+
+ x &= ~EEDI;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+}
+
+
+/* IRQL = PASSIVE_LEVEL*/
+static inline VOID EEpromCleanup(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 x;
+
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+ x &= ~(EECS | EEDI);
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+ RaiseClock(pAd, &x);
+ LowerClock(pAd, &x);
+}
+
+
+static inline VOID EWEN(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 x;
+
+ /* reset bits and set EECS*/
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+ x &= ~(EEDI | EEDO | EESK);
+ x |= EECS;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+ /* kick a pulse*/
+ RaiseClock(pAd, &x);
+ LowerClock(pAd, &x);
+
+ /* output the read_opcode and six pulse in that order */
+ ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5);
+ ShiftOutBits(pAd, 0, 6);
+
+ EEpromCleanup(pAd);
+}
+
+
+static inline VOID EWDS(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 x;
+
+ /* reset bits and set EECS*/
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+ x &= ~(EEDI | EEDO | EESK);
+ x |= EECS;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+ /* kick a pulse*/
+ RaiseClock(pAd, &x);
+ LowerClock(pAd, &x);
+
+ /* output the read_opcode and six pulse in that order */
+ ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5);
+ ShiftOutBits(pAd, 0, 6);
+
+ EEpromCleanup(pAd);
+}
+
+
+/* IRQL = PASSIVE_LEVEL*/
+int rtmp_ee_prom_read16(
+ IN RTMP_ADAPTER *pAd,
+ IN USHORT Offset,
+ OUT USHORT *pValue)
+{
+ UINT32 x;
+ USHORT data;
+
+
+
+ Offset /= 2;
+ /* reset bits and set EECS*/
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+ x &= ~(EEDI | EEDO | EESK);
+ x |= EECS;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+ /* patch can not access e-Fuse issue*/
+ if (IS_RT2860(pAd))
+ {
+ /* kick a pulse*/
+ RaiseClock(pAd, &x);
+ LowerClock(pAd, &x);
+ }
+
+ /* output the read_opcode and register number in that order */
+ ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3);
+ ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
+
+ /* Now read the data (16 bits) in from the selected EEPROM word*/
+ data = ShiftInBits(pAd);
+
+ EEpromCleanup(pAd);
+
+
+ *pValue = data;
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+int rtmp_ee_prom_write16(
+ IN RTMP_ADAPTER *pAd,
+ IN USHORT Offset,
+ IN USHORT Data)
+{
+ UINT32 x;
+
+
+
+ Offset /= 2;
+
+ EWEN(pAd);
+
+ /* reset bits and set EECS*/
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+ x &= ~(EEDI | EEDO | EESK);
+ x |= EECS;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+ /* patch can not access e-Fuse issue*/
+ if (IS_RT2860(pAd))
+ {
+ /* kick a pulse*/
+ RaiseClock(pAd, &x);
+ LowerClock(pAd, &x);
+ }
+
+ /* output the read_opcode ,register number and data in that order */
+ ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3);
+ ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
+ ShiftOutBits(pAd, Data, 16); /* 16-bit access*/
+
+ /* read DO status*/
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+ EEpromCleanup(pAd);
+
+ RTMPusecDelay(10000); /*delay for twp(MAX)=10ms*/
+
+ EWDS(pAd);
+
+ EEpromCleanup(pAd);
+
+
+ return NDIS_STATUS_SUCCESS;
+
+}
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/eeprom.c b/cleopatre/devkit/mt7601udrv/common/eeprom.c
new file mode 100644
index 0000000000..500c255644
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/eeprom.c
@@ -0,0 +1,85 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ eeprom.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+*/
+#include "rt_config.h"
+
+
+INT RtmpChipOpsEepromHook(RTMP_ADAPTER *pAd, INT infType)
+{
+ RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
+ UINT32 e2p_csr;
+
+#ifdef RTMP_FLASH_SUPPORT
+ pChipOps->eeinit = rtmp_nv_init;
+ pChipOps->eeread = rtmp_ee_flash_read;
+ pChipOps->eewrite = rtmp_ee_flash_write;
+ return 0;
+#endif /* RTMP_FLASH_SUPPORT */
+
+#ifdef RTMP_EFUSE_SUPPORT
+ efuse_probe(pAd);
+ if(pAd->bUseEfuse)
+ {
+ pChipOps->eeinit = eFuse_init;
+ pChipOps->eeread = rtmp_ee_efuse_read16;
+ pChipOps->eewrite = rtmp_ee_efuse_write16;
+ DBGPRINT(RT_DEBUG_OFF, ("NVM is EFUSE\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("Efuse Size=0x%x [Range:%x-%x] \n",
+ pAd->chipCap.EFUSE_USAGE_MAP_SIZE,
+ pAd->chipCap.EFUSE_USAGE_MAP_START,
+ pAd->chipCap.EFUSE_USAGE_MAP_END));
+
+ return 0 ;
+ }
+ else
+ {
+ pAd->bFroceEEPROMBuffer = FALSE;
+ DBGPRINT(RT_DEBUG_OFF, ("NVM is EEPROM\n"));
+ }
+#endif /* RTMP_EFUSE_SUPPORT */
+
+ switch(infType)
+ {
+
+
+#ifdef RTMP_USB_SUPPORT
+ case RTMP_DEV_INF_USB:
+ pChipOps->eeinit = NULL;
+ pChipOps->eeread = RTUSBReadEEPROM16;
+ pChipOps->eewrite = RTUSBWriteEEPROM16;
+ DBGPRINT(RT_DEBUG_OFF, ("pChipOps->eeread = RTUSBReadEEPROM16\n"));
+ DBGPRINT(RT_DEBUG_OFF, ("pChipOps->eewrite = RTUSBWriteEEPROM16\n"));
+ break;
+#endif /* RTMP_USB_SUPPORT */
+ default:
+ DBGPRINT(RT_DEBUG_ERROR, ("RtmpChipOpsEepromHook() failed!\n"));
+ break;
+ }
+
+ return 0;
+}
+
diff --git a/cleopatre/devkit/mt7601udrv/common/frq_cal.c b/cleopatre/devkit/mt7601udrv/common/frq_cal.c
new file mode 100644
index 0000000000..ac05d39051
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/frq_cal.c
@@ -0,0 +1,28 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ frq_cal.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+*/
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/igmp_snoop.c b/cleopatre/devkit/mt7601udrv/common/igmp_snoop.c
new file mode 100644
index 0000000000..47e458243f
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/igmp_snoop.c
@@ -0,0 +1,1511 @@
+#ifdef IGMP_SNOOP_SUPPORT
+
+#include "rt_config.h"
+#include "ipv6.h"
+#include "igmp_snoop.h"
+
+UINT16 IPv6MulticastFilterExclued[] =
+{
+ IPV6_NEXT_HEADER_ICMPV6, /* ICMPv6. */
+ IPV6_NEXT_HEADER_PIM, /* PIM. */
+};
+#define IPV6_MULTICAST_FILTER_EXCLUED_SIZE \
+ (sizeof(IPv6MulticastFilterExclued) / sizeof(UINT16))
+
+static inline void initFreeEntryList(
+ IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
+ IN PLIST_HEADER pList)
+{
+ int i;
+
+ for (i = 0; i < FREE_MEMBER_POOL_SIZE; i++)
+ insertTailList(pList, (PLIST_ENTRY)&(pMulticastFilterTable->freeMemberPool[i]));
+
+ return;
+}
+
+static inline PMEMBER_ENTRY AllocaGrpMemberEntry(
+ IN PMULTICAST_FILTER_TABLE pMulticastFilterTable)
+{
+ PMEMBER_ENTRY pMemberEntry;
+
+ RTMP_SEM_LOCK(&pMulticastFilterTable->FreeMemberPoolTabLock);
+
+ pMemberEntry = (PMEMBER_ENTRY)removeHeadList(&pMulticastFilterTable->freeEntryList);
+
+ RTMP_SEM_UNLOCK(&pMulticastFilterTable->FreeMemberPoolTabLock);
+
+ return (PMEMBER_ENTRY)pMemberEntry;
+}
+
+static inline VOID FreeGrpMemberEntry(
+ IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
+ IN PMEMBER_ENTRY pEntry)
+{
+ RTMP_SEM_LOCK(&pMulticastFilterTable->FreeMemberPoolTabLock);
+
+ insertTailList(&pMulticastFilterTable->freeEntryList, (PLIST_ENTRY)pEntry);
+
+ RTMP_SEM_UNLOCK(&pMulticastFilterTable->FreeMemberPoolTabLock);
+}
+
+static VOID IGMPTableDisplay(
+ IN PRTMP_ADAPTER pAd);
+
+static BOOLEAN isIgmpMacAddr(
+ IN PUCHAR pMacAddr);
+
+static VOID InsertIgmpMember(
+ IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
+ IN PLIST_HEADER pList,
+ IN PUCHAR pMemberAddr);
+
+static VOID DeleteIgmpMember(
+ IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
+ IN PLIST_HEADER pList,
+ IN PUCHAR pMemberAddr);
+
+static VOID DeleteIgmpMemberList(
+ IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
+ IN PLIST_HEADER pList);
+
+
+/*
+ ==========================================================================
+ Description:
+ This routine init the entire IGMP table.
+ ==========================================================================
+ */
+VOID MulticastFilterTableInit(
+ IN PRTMP_ADAPTER pAd,
+ IN PMULTICAST_FILTER_TABLE *ppMulticastFilterTable)
+{
+ /* Initialize MAC table and allocate spin lock */
+/* *ppMulticastFilterTable = kmalloc(sizeof(MULTICAST_FILTER_TABLE), MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)ppMulticastFilterTable, sizeof(MULTICAST_FILTER_TABLE));
+ if (*ppMulticastFilterTable == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for Multicase filter table, size=%d\n",
+ __FUNCTION__, sizeof(MULTICAST_FILTER_TABLE)));
+ return;
+ }
+
+ NdisZeroMemory(*ppMulticastFilterTable, sizeof(MULTICAST_FILTER_TABLE));
+ NdisAllocateSpinLock(pAd, &((*ppMulticastFilterTable)->MulticastFilterTabLock));
+
+ NdisAllocateSpinLock(pAd, &((*ppMulticastFilterTable)->FreeMemberPoolTabLock));
+ initList(&((*ppMulticastFilterTable)->freeEntryList));
+ initFreeEntryList(*ppMulticastFilterTable, &((*ppMulticastFilterTable)->freeEntryList));
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ This routine reset the entire IGMP table.
+ ==========================================================================
+ */
+VOID MultiCastFilterTableReset(
+ IN PMULTICAST_FILTER_TABLE *ppMulticastFilterTable)
+{
+ if(*ppMulticastFilterTable == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__));
+ return;
+ }
+
+ NdisFreeSpinLock(&((*ppMulticastFilterTable)->FreeMemberPoolTabLock));
+ NdisFreeSpinLock(&((*ppMulticastFilterTable)->MulticastFilterTabLock));
+/* kfree(*ppMulticastFilterTable); */
+ os_free_mem(NULL, *ppMulticastFilterTable);
+ *ppMulticastFilterTable = NULL;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Display all entrys in IGMP table
+ ==========================================================================
+ */
+static VOID IGMPTableDisplay(
+ IN PRTMP_ADAPTER pAd)
+{
+ int i;
+ MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL;
+ PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable;
+
+ if (pMulticastFilterTable == NULL)
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("%s Multicase filter table is not ready.\n", __FUNCTION__));
+ return;
+ }
+
+ /* if FULL, return */
+ if (pMulticastFilterTable->Size == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Table empty.\n"));
+ return;
+ }
+
+ /* allocate one MAC entry */
+ RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock);
+
+ for (i = 0; i< MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++)
+ {
+ /* pick up the first available vacancy */
+ if (pMulticastFilterTable->Content[i].Valid == TRUE)
+ {
+ PMEMBER_ENTRY pMemberEntry = NULL;
+ pEntry = &pMulticastFilterTable->Content[i];
+
+ DBGPRINT(RT_DEBUG_OFF, ("IF(%s) entry #%d, type=%s, GrpId=(%02x:%02x:%02x:%02x:%02x:%02x) memberCnt=%d\n",
+ RTMP_OS_NETDEV_GET_DEVNAME(pEntry->net_dev), i, (pEntry->type==0 ? "static":"dynamic"),
+ PRINT_MAC(pEntry->Addr), IgmpMemberCnt(&pEntry->MemberList)));
+
+ pMemberEntry = (PMEMBER_ENTRY)pEntry->MemberList.pHead;
+ while (pMemberEntry)
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("member mac=(%02x:%02x:%02x:%02x:%02x:%02x)\n",
+ PRINT_MAC(pMemberEntry->Addr)));
+
+ pMemberEntry = pMemberEntry->pNext;
+ }
+ }
+ }
+
+ RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock);
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Add and new entry into MAC table
+ ==========================================================================
+ */
+BOOLEAN MulticastFilterTableInsertEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pGrpId,
+ IN PUCHAR pMemberAddr,
+ IN PNET_DEV dev,
+ IN MulticastFilterEntryType type)
+{
+ UCHAR HashIdx;
+ int i;
+ MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL, *pCurrEntry, *pPrevEntry;
+ PMEMBER_ENTRY pMemberEntry;
+ PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable;
+
+ if (pMulticastFilterTable == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ /* if FULL, return */
+ if (pMulticastFilterTable->Size >= MAX_LEN_OF_MULTICAST_FILTER_TABLE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table full. max-entries = %d\n",
+ __FUNCTION__, MAX_LEN_OF_MULTICAST_FILTER_TABLE));
+ return FALSE;
+ }
+
+ /* check the rule is in table already or not. */
+ if ((pEntry = MulticastFilterTableLookup(pMulticastFilterTable, pGrpId, dev)))
+ {
+ /* doesn't indicate member mac address. */
+ if(pMemberAddr == NULL)
+ {
+ return FALSE;
+ }
+
+ pMemberEntry = (PMEMBER_ENTRY)pEntry->MemberList.pHead;
+
+ while (pMemberEntry)
+ {
+ if (MAC_ADDR_EQUAL(pMemberAddr, pMemberEntry->Addr))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: already in Members list.\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ pMemberEntry = pMemberEntry->pNext;
+ }
+ }
+
+ RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock);
+ do
+ {
+ ULONG Now;
+ /* the multicast entry already exist but doesn't include the member yet. */
+ if (pEntry != NULL && pMemberAddr != NULL)
+ {
+ InsertIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr);
+ break;
+ }
+
+ /* allocate one MAC entry */
+ for (i = 0; i < MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++)
+ {
+ /* pick up the first available vacancy */
+ pEntry = &pMulticastFilterTable->Content[i];
+ NdisGetSystemUpTime(&Now);
+ if ((pEntry->Valid == TRUE) && (pEntry->type == MCAT_FILTER_DYNAMIC)
+ && ((Now - pEntry->lastTime) > IGMPMAC_TB_ENTRY_AGEOUT_TIME))
+ {
+ PMULTICAST_FILTER_TABLE_ENTRY pHashEntry;
+
+ HashIdx = MULTICAST_ADDR_HASH_INDEX(pEntry->Addr);
+ pHashEntry = pMulticastFilterTable->Hash[HashIdx];
+
+ if ((pEntry->net_dev == pHashEntry->net_dev)
+ && MAC_ADDR_EQUAL(pEntry->Addr, pHashEntry->Addr))
+ {
+ pMulticastFilterTable->Hash[HashIdx] = pHashEntry->pNext;
+ pMulticastFilterTable->Size --;
+ DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 1 - Total= %d\n", pMulticastFilterTable->Size));
+ } else
+ {
+ while (pHashEntry->pNext)
+ {
+ pPrevEntry = pHashEntry;
+ pHashEntry = pHashEntry->pNext;
+ if ((pEntry->net_dev == pHashEntry->net_dev)
+ && MAC_ADDR_EQUAL(pEntry->Addr, pHashEntry->Addr))
+ {
+ pPrevEntry->pNext = pHashEntry->pNext;
+ pMulticastFilterTable->Size --;
+ DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size));
+ break;
+ }
+ }
+ }
+ pEntry->Valid = FALSE;
+ DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList);
+ }
+
+ if (pEntry->Valid == FALSE)
+ {
+ NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY));
+ pEntry->Valid = TRUE;
+
+ COPY_MAC_ADDR(pEntry->Addr, pGrpId);
+ pEntry->net_dev = dev;
+ NdisGetSystemUpTime(&Now);
+ pEntry->lastTime = Now;
+ pEntry->type = type;
+ initList(&pEntry->MemberList);
+ if (pMemberAddr != NULL)
+ InsertIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr);
+
+ pMulticastFilterTable->Size ++;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MulticastFilterTableInsertEntry -IF(%s) allocate entry #%d, Total= %d\n", RTMP_OS_NETDEV_GET_DEVNAME(dev), i, pMulticastFilterTable->Size));
+ break;
+ }
+ }
+
+ /* add this MAC entry into HASH table */
+ if (pEntry)
+ {
+ HashIdx = MULTICAST_ADDR_HASH_INDEX(pGrpId);
+ if (pMulticastFilterTable->Hash[HashIdx] == NULL)
+ {
+ pMulticastFilterTable->Hash[HashIdx] = pEntry;
+ } else
+ {
+ pCurrEntry = pMulticastFilterTable->Hash[HashIdx];
+ while (pCurrEntry->pNext != NULL)
+ pCurrEntry = pCurrEntry->pNext;
+ pCurrEntry->pNext = pEntry;
+ }
+ }
+ }while(FALSE);
+
+ RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock);
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Delete a specified client from MAC table
+ ==========================================================================
+ */
+BOOLEAN MulticastFilterTableDeleteEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pGrpId,
+ IN PUCHAR pMemberAddr,
+ IN PNET_DEV dev)
+{
+ USHORT HashIdx;
+ MULTICAST_FILTER_TABLE_ENTRY *pEntry, *pPrevEntry;
+ PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable;
+
+ if (pMulticastFilterTable == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock);
+
+ do
+ {
+ HashIdx = MULTICAST_ADDR_HASH_INDEX(pGrpId);
+ pPrevEntry = pEntry = pMulticastFilterTable->Hash[HashIdx];
+
+ while (pEntry && pEntry->Valid)
+ {
+ if ((pEntry->net_dev == dev)
+ && MAC_ADDR_EQUAL(pEntry->Addr, pGrpId))
+ break;
+ else
+ {
+ pPrevEntry = pEntry;
+ pEntry = pEntry->pNext;
+ }
+ }
+
+ /* check the rule is in table already or not. */
+ if (pEntry && (pMemberAddr != NULL))
+ {
+ /*USHORT Aid = MCAST_WCID; */
+ /*SST Sst = SST_ASSOC; */
+ /*UCHAR PsMode = PWR_ACTIVE, Rate; */
+ /*if(APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate)) */
+ DeleteIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr);
+ if (IgmpMemberCnt(&pEntry->MemberList) > 0)
+ break;
+ }
+
+ if (pEntry)
+ {
+ if (pEntry == pMulticastFilterTable->Hash[HashIdx])
+ {
+ pMulticastFilterTable->Hash[HashIdx] = pEntry->pNext;
+ DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList);
+ NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY));
+ pMulticastFilterTable->Size --;
+ DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 1 - Total= %d\n", pMulticastFilterTable->Size));
+ }
+ else
+ {
+ pPrevEntry->pNext = pEntry->pNext;
+ DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList);
+ NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY));
+ pMulticastFilterTable->Size --;
+ DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size));
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: the Group doesn't exist.\n", __FUNCTION__));
+ }
+ } while(FALSE);
+
+ RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock);
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Look up the MAC address in the IGMP table. Return NULL if not found.
+ Return:
+ pEntry - pointer to the MAC entry; NULL is not found
+ ==========================================================================
+*/
+PMULTICAST_FILTER_TABLE_ENTRY MulticastFilterTableLookup(
+ IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
+ IN PUCHAR pAddr,
+ IN PNET_DEV dev)
+{
+ ULONG HashIdx, Now;
+ PMULTICAST_FILTER_TABLE_ENTRY pEntry = NULL, pPrev = NULL;
+
+ if (pMulticastFilterTable == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s Multicase filter table is not ready.\n", __FUNCTION__));
+ return NULL;
+ }
+
+ RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock);
+
+ HashIdx = MULTICAST_ADDR_HASH_INDEX(pAddr);
+ pEntry = pPrev = pMulticastFilterTable->Hash[HashIdx];
+
+ while (pEntry && pEntry->Valid)
+ {
+ if ((pEntry->net_dev == dev)
+ && MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
+ {
+ NdisGetSystemUpTime(&Now);
+ pEntry->lastTime = Now;
+ break;
+ }
+ else
+ {
+ NdisGetSystemUpTime(&Now);
+ if ((pEntry->Valid == TRUE) && (pEntry->type == MCAT_FILTER_DYNAMIC)
+ && RTMP_TIME_AFTER(Now, pEntry->lastTime+IGMPMAC_TB_ENTRY_AGEOUT_TIME))
+ {
+ /* Remove the aged entry */
+ if (pEntry == pMulticastFilterTable->Hash[HashIdx])
+ {
+ pMulticastFilterTable->Hash[HashIdx] = pEntry->pNext;
+ pPrev = pMulticastFilterTable->Hash[HashIdx];
+ DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList);
+ NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY));
+ pMulticastFilterTable->Size --;
+ pEntry = pPrev;
+ DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size));
+ }
+ else
+ {
+ pPrev->pNext = pEntry->pNext;
+ DeleteIgmpMemberList(pMulticastFilterTable, &pEntry->MemberList);
+ NdisZeroMemory(pEntry, sizeof(MULTICAST_FILTER_TABLE_ENTRY));
+ pMulticastFilterTable->Size --;
+ pEntry = pPrev->pNext;
+ DBGPRINT(RT_DEBUG_TRACE, ("MCastFilterTableDeleteEntry 2 - Total= %d\n", pMulticastFilterTable->Size));
+ }
+ }
+ else
+ {
+ pPrev = pEntry;
+ pEntry = pEntry->pNext;
+ }
+ }
+ }
+
+ RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock);
+
+ return pEntry;
+}
+
+VOID IGMPSnooping(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDstMacAddr,
+ IN PUCHAR pSrcMacAddr,
+ IN PUCHAR pIpHeader,
+ IN PNET_DEV pDev)
+{
+ INT i;
+ INT IpHeaderLen;
+ UCHAR GroupType;
+ UINT16 numOfGroup;
+ UCHAR IgmpVerType;
+ PUCHAR pIgmpHeader;
+ PUCHAR pGroup;
+ UCHAR AuxDataLen;
+ UINT16 numOfSources;
+ PUCHAR pGroupIpAddr;
+ UCHAR GroupMacAddr[6];
+ PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr;
+
+ if(isIgmpPkt(pDstMacAddr, pIpHeader))
+ {
+ IpHeaderLen = (*(pIpHeader + 2) & 0x0f) * 4;
+ pIgmpHeader = pIpHeader + 2 + IpHeaderLen;
+ IgmpVerType = (UCHAR)(*(pIgmpHeader));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("IGMP type=%0x\n", IgmpVerType));
+
+ switch(IgmpVerType)
+ {
+ case IGMP_V1_MEMBERSHIP_REPORT: /* IGMP version 1 membership report. */
+ case IGMP_V2_MEMBERSHIP_REPORT: /* IGMP version 2 membership report. */
+ pGroupIpAddr = (PUCHAR)(pIgmpHeader + 4);
+ ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP);
+ DBGPRINT(RT_DEBUG_TRACE, ("IGMP Group=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5]));
+ MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC);
+ break;
+
+ case IGMP_LEAVE_GROUP: /* IGMP version 1 and version 2 leave group. */
+ pGroupIpAddr = (PUCHAR)(pIgmpHeader + 4);
+ ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP);
+ DBGPRINT(RT_DEBUG_TRACE, ("IGMP Group=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5]));
+ MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev);
+ break;
+
+ case IGMP_V3_MEMBERSHIP_REPORT: /* IGMP version 3 membership report. */
+ numOfGroup = ntohs(*((UINT16 *)(pIgmpHeader + 6)));
+ pGroup = (PUCHAR)(pIgmpHeader + 8);
+ for (i=0; i < numOfGroup; i++)
+ {
+ GroupType = (UCHAR)(*pGroup);
+ AuxDataLen = (UCHAR)(*(pGroup + 1));
+ numOfSources = ntohs(*((UINT16 *)(pGroup + 2)));
+ pGroupIpAddr = (PUCHAR)(pGroup + 4);
+ DBGPRINT(RT_DEBUG_TRACE, ("IGMPv3 Type=%d, ADL=%d, numOfSource=%d\n",
+ GroupType, AuxDataLen, numOfSources));
+ ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP);
+ DBGPRINT(RT_DEBUG_TRACE, ("IGMP Group=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2],
+ GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5]));
+
+ do
+ {
+ if ((GroupType == MODE_IS_EXCLUDE)
+ || (GroupType == CHANGE_TO_EXCLUDE_MODE)
+ || (GroupType == ALLOW_NEW_SOURCES))
+ {
+ MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC);
+ break;
+ }
+
+ if ((GroupType == CHANGE_TO_INCLUDE_MODE)
+ || (GroupType == MODE_IS_INCLUDE)
+ || (GroupType == BLOCK_OLD_SOURCES))
+ {
+ if(numOfSources == 0)
+ MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev);
+ else
+ MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC);
+ break;
+ }
+ } while(FALSE);
+ pGroup += (8 + (numOfSources * 4) + AuxDataLen);
+ }
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("unknow IGMP Type=%d\n", IgmpVerType));
+ break;
+ }
+ }
+
+ return;
+}
+
+
+static BOOLEAN isIgmpMacAddr(
+ IN PUCHAR pMacAddr)
+{
+ if((pMacAddr[0] == 0x01)
+ && (pMacAddr[1] == 0x00)
+ && (pMacAddr[2] == 0x5e))
+ return TRUE;
+ return FALSE;
+}
+
+BOOLEAN isIgmpPkt(
+ IN PUCHAR pDstMacAddr,
+ IN PUCHAR pIpHeader)
+{
+ UINT16 IpProtocol = ntohs(*((UINT16 *)(pIpHeader)));
+ UCHAR IgmpProtocol;
+
+ if(!isIgmpMacAddr(pDstMacAddr))
+ return FALSE;
+
+ if(IpProtocol == ETH_P_IP)
+ {
+ IgmpProtocol = (UCHAR)*(pIpHeader + 11);
+ if(IgmpProtocol == IGMP_PROTOCOL_DESCRIPTOR)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static VOID InsertIgmpMember(
+ IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
+ IN PLIST_HEADER pList,
+ IN PUCHAR pMemberAddr)
+{
+ PMEMBER_ENTRY pMemberEntry;
+
+ if(pList == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__));
+ return;
+ }
+
+ if (pMemberAddr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: invalid member.\n", __FUNCTION__));
+ return;
+ }
+
+ if((pMemberEntry = (PMEMBER_ENTRY)AllocaGrpMemberEntry(pMulticastFilterTable)) != NULL)
+ {
+ NdisZeroMemory(pMemberEntry, sizeof(MEMBER_ENTRY));
+ COPY_MAC_ADDR(pMemberEntry->Addr, pMemberAddr);
+ insertTailList(pList, (PLIST_ENTRY)pMemberEntry);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s Member Mac=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__,
+ pMemberEntry->Addr[0], pMemberEntry->Addr[1], pMemberEntry->Addr[2],
+ pMemberEntry->Addr[3], pMemberEntry->Addr[4], pMemberEntry->Addr[5]));
+ }
+ return;
+}
+
+static VOID DeleteIgmpMember(
+ IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
+ IN PLIST_HEADER pList,
+ IN PUCHAR pMemberAddr)
+{
+ PMEMBER_ENTRY pCurEntry;
+
+ if (pList == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__));
+ return;
+ }
+
+ if (pList->pHead == NULL)
+ {
+ return;
+ }
+
+ if (pMemberAddr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: invalid member.\n", __FUNCTION__));
+ return;
+ }
+
+ pCurEntry = (PMEMBER_ENTRY)pList->pHead;
+ while (pCurEntry)
+ {
+ PMEMBER_ENTRY pCurEntryNext = pCurEntry->pNext;
+ if(MAC_ADDR_EQUAL(pMemberAddr, pCurEntry->Addr))
+ {
+ delEntryList(pList, (PLIST_ENTRY)pCurEntry);
+ FreeGrpMemberEntry(pMulticastFilterTable, pCurEntry);
+ break;
+ }
+ pCurEntry = pCurEntryNext;
+ }
+
+ return;
+}
+
+static VOID DeleteIgmpMemberList(
+ IN PMULTICAST_FILTER_TABLE pMulticastFilterTable,
+ IN PLIST_HEADER pList)
+{
+ PMEMBER_ENTRY pCurEntry, pPrvEntry;
+
+ if (pList == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__));
+ return;
+ }
+
+ if (pList->pHead == NULL)
+ {
+ return;
+ }
+
+ pPrvEntry = pCurEntry = (PMEMBER_ENTRY)pList->pHead;
+ while (pCurEntry)
+ {
+ delEntryList(pList, (PLIST_ENTRY)pCurEntry);
+ pPrvEntry = pCurEntry;
+ pCurEntry = pCurEntry->pNext;
+ FreeGrpMemberEntry(pMulticastFilterTable, pPrvEntry);
+ }
+
+ initList(pList);
+ return;
+}
+
+
+UCHAR IgmpMemberCnt(
+ IN PLIST_HEADER pList)
+{
+ if(pList == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: membert list doesn't exist.\n", __FUNCTION__));
+ return 0;
+ }
+
+ return getListSize(pList);
+}
+
+VOID IgmpGroupDelMembers(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pMemberAddr,
+ IN PNET_DEV pDev)
+{
+ INT i;
+ MULTICAST_FILTER_TABLE_ENTRY *pEntry = NULL;
+ PMULTICAST_FILTER_TABLE pMulticastFilterTable = pAd->pMulticastFilterTable;
+
+ for (i = 0; i < MAX_LEN_OF_MULTICAST_FILTER_TABLE; i++)
+ {
+ /* pick up the first available vacancy */
+ pEntry = &pMulticastFilterTable->Content[i];
+ if (pEntry->Valid == TRUE)
+ {
+ if(pMemberAddr != NULL)
+ {
+ RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock);
+ DeleteIgmpMember(pMulticastFilterTable, &pEntry->MemberList, pMemberAddr);
+ RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock);
+ }
+
+ if((pEntry->type == MCAT_FILTER_DYNAMIC)
+ && (IgmpMemberCnt(&pEntry->MemberList) == 0))
+ MulticastFilterTableDeleteEntry(pAd, pEntry->Addr, pMemberAddr, pDev);
+ }
+ }
+}
+
+INT Set_IgmpSn_Enable_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UINT Enable;
+
+ Enable = (UINT) simple_strtol(arg, 0, 10);
+
+ pAd->ApCfg.IgmpSnoopEnable = (BOOLEAN)(Enable == 0 ? FALSE : TRUE);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: %s\n", __FUNCTION__, Enable == TRUE ? "Enable IGMP Snooping":"Disable IGMP Snooping"));
+
+ return TRUE;
+}
+
+INT Set_IgmpSn_AddEntry_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ INT i;
+ BOOLEAN bGroupId = 1;
+ PSTRING value;
+ PSTRING thisChar;
+ UCHAR IpAddr[4];
+ UCHAR Addr[ETH_LENGTH_OF_ADDRESS];
+ UCHAR GroupId[ETH_LENGTH_OF_ADDRESS];
+ PUCHAR *pAddr = (PUCHAR *)&Addr;
+ PNET_DEV pDev;
+ POS_COOKIE pObj;
+ UCHAR ifIndex;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+ ifIndex = pObj->ioctl_if;
+
+ pDev = (ifIndex == MAIN_MBSSID) ? (pAd->net_dev) : (pAd->ApCfg.MBSSID[ifIndex].MSSIDDev);
+
+ while ((thisChar = strsep((char **)&arg, "-")) != NULL)
+ {
+ /* refuse the Member if it's not a MAC address. */
+ if((bGroupId == 0) && (strlen(thisChar) != 17))
+ continue;
+
+ if(strlen(thisChar) == 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */
+ {
+ for (i=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":"))
+ {
+ if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
+ return FALSE; /*Invalid */
+
+ AtoH(value, &Addr[i++], 1);
+ }
+
+ if(i != 6)
+ return FALSE; /*Invalid */
+ }
+ else
+ {
+ for (i=0, value = rstrtok(thisChar,"."); value; value = rstrtok(NULL,"."))
+ {
+ if((strlen(value) > 0) && (strlen(value) <= 3))
+ {
+ int ii;
+ for(ii=0; ii<strlen(value); ii++)
+ if (!isxdigit(*(value + ii)))
+ return FALSE;
+ }
+ else
+ return FALSE; /*Invalid */
+
+ IpAddr[i] = (UCHAR)simple_strtol(value, NULL, 10);
+ i++;
+ }
+
+ if(i != 4)
+ return FALSE; /*Invalid */
+
+ ConvertMulticastIP2MAC(IpAddr, (PUCHAR *)&pAddr, ETH_P_IP);
+ }
+
+ if(bGroupId == 1)
+ COPY_MAC_ADDR(GroupId, Addr);
+
+ /* Group-Id must be a MCAST address. */
+ if((bGroupId == 1) && IS_MULTICAST_MAC_ADDR(Addr))
+ MulticastFilterTableInsertEntry(pAd, GroupId, NULL, pDev, MCAT_FILTER_STATIC);
+ /* Group-Member must be a UCAST address. */
+ else if ((bGroupId == 0) && !IS_MULTICAST_MAC_ADDR(Addr))
+ MulticastFilterTableInsertEntry(pAd, GroupId, Addr, pDev, MCAT_FILTER_STATIC);
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s (%2X:%2X:%2X:%2X:%2X:%2X) is not a acceptable address.\n",
+ __FUNCTION__, Addr[0], Addr[1], Addr[2], Addr[3], Addr[4], Addr[5]));
+ return FALSE;
+ }
+
+ bGroupId = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s (%2X:%2X:%2X:%2X:%2X:%2X)\n",
+ __FUNCTION__, Addr[0], Addr[1], Addr[2], Addr[3], Addr[4], Addr[5]));
+
+ }
+
+ return TRUE;
+}
+
+INT Set_IgmpSn_DelEntry_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ INT i, memberCnt = 0;
+ BOOLEAN bGroupId = 1;
+ PSTRING value;
+ PSTRING thisChar;
+ UCHAR IpAddr[4];
+ UCHAR Addr[ETH_LENGTH_OF_ADDRESS];
+ UCHAR GroupId[ETH_LENGTH_OF_ADDRESS];
+ PUCHAR *pAddr = (PUCHAR *)&Addr;
+ PNET_DEV pDev;
+ POS_COOKIE pObj;
+ UCHAR ifIndex;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+ ifIndex = pObj->ioctl_if;
+
+ pDev = (ifIndex == MAIN_MBSSID) ? (pAd->net_dev) : (pAd->ApCfg.MBSSID[ifIndex].MSSIDDev);
+
+ while ((thisChar = strsep((char **)&arg, "-")) != NULL)
+ {
+ /* refuse the Member if it's not a MAC address. */
+ if((bGroupId == 0) && (strlen(thisChar) != 17))
+ continue;
+
+ if(strlen(thisChar) == 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */
+ {
+ for (i=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":"))
+ {
+ if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
+ return FALSE; /*Invalid */
+
+ AtoH(value, &Addr[i++], 1);
+ }
+
+ if(i != 6)
+ return FALSE; /*Invalid */
+ }
+ else
+ {
+ for (i=0, value = rstrtok(thisChar,"."); value; value = rstrtok(NULL,"."))
+ {
+ if((strlen(value) > 0) && (strlen(value) <= 3))
+ {
+ int ii;
+ for(ii=0; ii<strlen(value); ii++)
+ if (!isxdigit(*(value + ii)))
+ return FALSE;
+ }
+ else
+ return FALSE; /*Invalid */
+
+ IpAddr[i] = (UCHAR)simple_strtol(value, NULL, 10);
+ i++;
+ }
+
+ if(i != 4)
+ return FALSE; /*Invalid */
+
+ ConvertMulticastIP2MAC(IpAddr, (PUCHAR *)&pAddr, ETH_P_IP);
+ }
+
+ if(bGroupId == 1)
+ COPY_MAC_ADDR(GroupId, Addr);
+ else
+ memberCnt++;
+
+ if (memberCnt > 0 )
+ MulticastFilterTableDeleteEntry(pAd, (PUCHAR)GroupId, Addr, pDev);
+
+ bGroupId = 0;
+ }
+
+ if(memberCnt == 0)
+ MulticastFilterTableDeleteEntry(pAd, (PUCHAR)GroupId, NULL, pDev);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s (%2X:%2X:%2X:%2X:%2X:%2X)\n",
+ __FUNCTION__, Addr[0], Addr[1], Addr[2], Addr[3], Addr[4], Addr[5]));
+
+ return TRUE;
+}
+
+INT Set_IgmpSn_TabDisplay_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ IGMPTableDisplay(pAd);
+ return TRUE;
+}
+
+void rtmp_read_igmp_snoop_from_file(
+ IN PRTMP_ADAPTER pAd,
+ PSTRING tmpbuf,
+ PSTRING buffer)
+{
+ /*IgmpSnEnable */
+ if(RTMPGetKeyParameter("IgmpSnEnable", tmpbuf, 128, buffer, TRUE))
+ {
+ if ((strncmp(tmpbuf, "0", 1) == 0))
+ pAd->ApCfg.IgmpSnoopEnable = FALSE;
+ else if ((strncmp(tmpbuf, "1", 1) == 0))
+ pAd->ApCfg.IgmpSnoopEnable = TRUE;
+ else
+ pAd->ApCfg.IgmpSnoopEnable = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, (" IGMP Snooping Enable=%d\n", pAd->ApCfg.IgmpSnoopEnable));
+ }
+}
+
+NDIS_STATUS IgmpPktInfoQuery(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pSrcBufVA,
+ IN PNDIS_PACKET pPacket,
+ IN UCHAR FromWhichBSSID,
+ OUT INT *pInIgmpGroup,
+ OUT PMULTICAST_FILTER_TABLE_ENTRY *ppGroupEntry)
+{
+ if(IS_MULTICAST_MAC_ADDR(pSrcBufVA))
+ {
+ BOOLEAN IgmpMldPkt = FALSE;
+ PUCHAR pIpHeader = pSrcBufVA + 12;
+
+ if(ntohs(*((UINT16 *)(pIpHeader))) == ETH_P_IPV6)
+ IgmpMldPkt = IPv6MulticastFilterExcluded(pSrcBufVA, pIpHeader);
+ else
+ IgmpMldPkt = isIgmpPkt(pSrcBufVA, pIpHeader);
+
+ if (IgmpMldPkt)
+ {
+ *ppGroupEntry = NULL;
+ *pInIgmpGroup = IGMP_PKT;
+ }
+ else if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pSrcBufVA,
+ get_netdev_from_bssid(pAd, FromWhichBSSID))) == NULL)
+ {
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ return NDIS_STATUS_FAILURE;
+ }
+ else
+ *pInIgmpGroup = IGMP_IN_GROUP;
+ }
+ else if (IS_BROADCAST_MAC_ADDR(pSrcBufVA))
+ {
+ PUCHAR pDstIpAddr = pSrcBufVA + 30; /* point to Destination of Ip address of IP header. */
+ UCHAR GroupMacAddr[6];
+ PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr;
+
+ ConvertMulticastIP2MAC(pDstIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP);
+ if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pGroupMacAddr,
+ get_netdev_from_bssid(pAd, FromWhichBSSID))) != NULL)
+ {
+ *pInIgmpGroup = IGMP_IN_GROUP;
+ }
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+NDIS_STATUS IgmpPktClone(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN INT IgmpPktInGroup,
+ IN PMULTICAST_FILTER_TABLE_ENTRY pGroupEntry,
+ IN UCHAR QueIdx,
+ IN UINT8 UserPriority,
+ IN PNET_DEV pNetDev)
+{
+ PNDIS_PACKET pSkbClone = NULL;
+ PMEMBER_ENTRY pMemberEntry = NULL;
+ MAC_TABLE_ENTRY *pMacEntry = NULL;
+ USHORT Aid;
+ SST Sst = SST_ASSOC;
+ UCHAR PsMode = PWR_ACTIVE;
+ UCHAR Rate;
+ unsigned long IrqFlags;
+ INT MacEntryIdx;
+ BOOLEAN bContinue;
+ PUCHAR pMemberAddr = NULL;
+
+ bContinue = FALSE;
+
+ if ((IgmpPktInGroup == IGMP_IN_GROUP)
+ && (pGroupEntry == NULL))
+ return NDIS_STATUS_FAILURE;
+
+ if (IgmpPktInGroup == IGMP_IN_GROUP)
+ {
+ pMemberEntry = (PMEMBER_ENTRY)pGroupEntry->MemberList.pHead;
+ if (pMemberEntry != NULL)
+ {
+ pMemberAddr = pMemberEntry->Addr;
+ pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate);
+ bContinue = TRUE;
+ }
+ }
+ else if (IgmpPktInGroup == IGMP_PKT)
+ {
+ PUCHAR src_addr = GET_OS_PKT_DATAPTR(pPacket);
+ src_addr += 6;
+
+ for(MacEntryIdx=1; MacEntryIdx<MAX_NUMBER_OF_MAC; MacEntryIdx++)
+ {
+ pMemberAddr = pAd->MacTab.Content[MacEntryIdx].Addr;
+ pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate);
+ if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry)
+ && get_netdev_from_bssid(pAd, pMacEntry->apidx) == pNetDev
+ && (!NdisEqualMemory(src_addr, pMacEntry->Addr, MAC_ADDR_LEN)))
+ {
+ pMemberAddr = pMacEntry->Addr;
+ bContinue = TRUE;
+ break;
+ }
+ }
+ }
+ else
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ /* check all members of the IGMP group. */
+ while(bContinue == TRUE)
+ {
+ if (pMacEntry && (Sst == SST_ASSOC) && (pMacEntry->PortSecured == WPA_802_1X_PORT_SECURED))
+ {
+ OS_PKT_CLONE(pAd, pPacket, pSkbClone, MEM_ALLOC_FLAG);
+ if ((pSkbClone)
+ )
+ {
+ RTMP_SET_PACKET_WCID(pSkbClone, (UCHAR)pMacEntry->Aid);
+ /* Pkt type must set to PKTSRC_NDIS. */
+ /* It cause of the deason that APHardTransmit() */
+ /* doesn't handle PKTSRC_DRIVER pkt type in version 1.3.0.0. */
+ RTMP_SET_PACKET_SOURCE(pSkbClone, PKTSRC_NDIS);
+ }
+ else
+ {
+ if (IgmpPktInGroup == IGMP_IN_GROUP)
+ {
+ pMemberEntry = pMemberEntry->pNext;
+ if (pMemberEntry != NULL)
+ {
+ pMemberAddr = pMemberEntry->Addr;
+ pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate);
+ bContinue = TRUE;
+ }
+ else
+ bContinue = FALSE;
+ }
+ else if (IgmpPktInGroup == IGMP_PKT)
+ {
+ PUCHAR src_addr = GET_OS_PKT_DATAPTR(pPacket);
+ src_addr += 6;
+ for(MacEntryIdx=pMacEntry->Aid + 1; MacEntryIdx<MAX_NUMBER_OF_MAC; MacEntryIdx++)
+ {
+ pMemberAddr = pAd->MacTab.Content[MacEntryIdx].Addr;
+ pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate);
+ if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry)
+ && get_netdev_from_bssid(pAd, pMacEntry->apidx) == pNetDev
+ && (!NdisEqualMemory(src_addr, pMacEntry->Addr, MAC_ADDR_LEN)))
+ {
+ pMemberAddr = pMacEntry->Addr;
+ bContinue = TRUE;
+ break;
+ }
+ }
+ if (MacEntryIdx == MAX_NUMBER_OF_MAC)
+ bContinue = FALSE;
+ }
+ else
+ bContinue = FALSE;
+
+ continue;
+ }
+
+ if (PsMode == PWR_SAVE)
+ {
+ APInsertPsQueue(pAd, pSkbClone, pMacEntry, QueIdx);
+ }
+ else
+ {
+ /* insert the pkt to TxSwQueue. */
+ if (pAd->TxSwQueue[QueIdx].Number >= pAd->TxSwQMaxLen)
+ {
+#ifdef BLOCK_NET_IF
+ StopNetIfQueue(pAd, QueIdx, pSkbClone);
+#endif /* BLOCK_NET_IF */
+ RELEASE_NDIS_PACKET(pAd, pSkbClone, NDIS_STATUS_FAILURE);
+ return NDIS_STATUS_FAILURE;
+ }
+ else
+ {
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+ InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pSkbClone));
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+ }
+ }
+#ifdef DOT11_N_SUPPORT
+ RTMP_BASetup(pAd, pMacEntry, UserPriority);
+#endif /* DOT11_N_SUPPORT */
+ }
+
+ if (IgmpPktInGroup == IGMP_IN_GROUP)
+ {
+ pMemberEntry = pMemberEntry->pNext;
+ if (pMemberEntry != NULL)
+ {
+ pMemberAddr = pMemberEntry->Addr;
+ pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate);
+ bContinue = TRUE;
+ }
+ else
+ bContinue = FALSE;
+ }
+ else if (IgmpPktInGroup == IGMP_PKT)
+ {
+ for(MacEntryIdx=pMacEntry->Aid + 1; MacEntryIdx<MAX_NUMBER_OF_MAC; MacEntryIdx++)
+ {
+ pMemberAddr = pAd->MacTab.Content[MacEntryIdx].Addr;
+ pMacEntry = APSsPsInquiry(pAd, pMemberAddr, &Sst, &Aid, &PsMode, &Rate);
+ if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry)
+ && get_netdev_from_bssid(pAd, pMacEntry->apidx) == pNetDev)
+ {
+ pMemberAddr = pMacEntry->Addr;
+ bContinue = TRUE;
+ break;
+ }
+ }
+ if (MacEntryIdx == MAX_NUMBER_OF_MAC)
+ bContinue = FALSE;
+ }
+ else
+ bContinue = FALSE;
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+static inline BOOLEAN isMldMacAddr(
+ IN PUCHAR pMacAddr)
+{
+ return ((pMacAddr[0] == 0x33) && (pMacAddr[1] == 0x33)) ? TRUE : FALSE;
+}
+
+static inline BOOLEAN IsSupportedMldMsg(
+ IN UINT8 MsgType)
+{
+ BOOLEAN result = FALSE;
+ switch(MsgType)
+ {
+ case MLD_V1_LISTENER_REPORT:
+ case MLD_V1_LISTENER_DONE:
+ case MLD_V2_LISTERNER_REPORT:
+ result = TRUE;
+ break;
+ default:
+ result = FALSE;
+ break;
+ }
+
+ return result;
+}
+
+BOOLEAN isMldPkt(
+ IN PUCHAR pDstMacAddr,
+ IN PUCHAR pIpHeader,
+ OUT UINT8 *pProtoType,
+ OUT PUCHAR *pMldHeader)
+{
+ BOOLEAN result = FALSE;
+ UINT16 IpProtocol = ntohs(*((UINT16 *)(pIpHeader)));
+
+ if(!isMldMacAddr(pDstMacAddr))
+ return FALSE;
+
+ if(IpProtocol != ETH_P_IPV6)
+ return FALSE;
+
+ /* skip protocol (2 Bytes). */
+ pIpHeader += 2;
+ do
+ {
+ PRT_IPV6_HDR pIpv6Hdr = (PRT_IPV6_HDR)(pIpHeader);
+ UINT8 nextProtocol = pIpv6Hdr->nextHdr;
+ UINT32 offset = IPV6_HDR_LEN;
+
+ while(nextProtocol != IPV6_NEXT_HEADER_ICMPV6)
+ {
+ if(IPv6ExtHdrHandle((RT_IPV6_EXT_HDR *)(pIpHeader + offset), &nextProtocol, &offset) == FALSE)
+ break;
+ }
+
+ if(nextProtocol == IPV6_NEXT_HEADER_ICMPV6)
+ {
+ PRT_ICMPV6_HDR pICMPv6Hdr = (PRT_ICMPV6_HDR)(pIpHeader + offset);
+ if (IsSupportedMldMsg(pICMPv6Hdr->type) == TRUE)
+ {
+ if (pProtoType != NULL)
+ *pProtoType = pICMPv6Hdr->type;
+ if (pMldHeader != NULL)
+ *pMldHeader = (PUCHAR)pICMPv6Hdr;
+ result = TRUE;
+ }
+ }
+ }while(FALSE);
+
+ return result;
+}
+
+BOOLEAN IPv6MulticastFilterExcluded(
+ IN PUCHAR pDstMacAddr,
+ IN PUCHAR pIpHeader)
+{
+ BOOLEAN result = FALSE;
+ UINT16 IpProtocol = ntohs(*((UINT16 *)(pIpHeader)));
+ INT idx;
+ UINT8 nextProtocol;
+
+ if(!IS_IPV6_MULTICAST_MAC_ADDR(pDstMacAddr))
+ return FALSE;
+
+ if(IpProtocol != ETH_P_IPV6)
+ return FALSE;
+
+ /* skip protocol (2 Bytes). */
+ pIpHeader += 2;
+ do
+ {
+ PRT_IPV6_HDR pIpv6Hdr = (PRT_IPV6_HDR)(pIpHeader);
+ UINT32 offset = IPV6_HDR_LEN;
+
+ nextProtocol = pIpv6Hdr->nextHdr;
+ while(nextProtocol == IPV6_NEXT_HEADER_HOP_BY_HOP)
+ {
+ if(IPv6ExtHdrHandle((RT_IPV6_EXT_HDR *)(pIpHeader + offset), &nextProtocol, &offset) == FALSE)
+ break;
+ }
+ } while(FALSE);
+
+ for (idx = 0; idx < IPV6_MULTICAST_FILTER_EXCLUED_SIZE; idx++)
+ {
+ if (nextProtocol == IPv6MulticastFilterExclued[idx])
+ {
+ result = TRUE;
+ break;
+ }
+ }
+
+ return result;
+}
+
+/* MLD v1 messages have the following format:
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Maximum Response Delay | Reserved |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | |
+ + Multicast Address +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/* Version 3 Membership Report Message
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type = 143 | Reserved | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved | Number of Group Records (M) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . .
+ . Multicast Address Record [1] .
+ . .
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . .
+ . Multicast Address Record [2] .
+ . .
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | . |
+ . . .
+ | . |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . .
+ . Multicast Address Record [M] .
+ . .
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ where each Group Record has the following internal format:
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Record Type | Aux Data Len | Number of Sources (N) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ * *
+ | |
+ * Multicast Address *
+ | |
+ * *
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ * *
+ | |
+ * Source Address [1] *
+ | |
+ * *
+ | |
+ +- -+
+ | |
+ * *
+ | |
+ * Source Address [2] *
+ | |
+ * *
+ | |
+ +- -+
+ . . .
+ . . .
+ . . .
+ +- -+
+ | |
+ * *
+ | |
+ * Source Address [N] *
+ | |
+ * *
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . .
+ . Auxiliary Data .
+ . .
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+VOID MLDSnooping(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDstMacAddr,
+ IN PUCHAR pSrcMacAddr,
+ IN PUCHAR pIpHeader,
+ IN PNET_DEV pDev)
+{
+ INT i;
+ UCHAR GroupType;
+ UINT16 numOfGroup;
+ PUCHAR pGroup;
+ UCHAR AuxDataLen;
+ UINT16 numOfSources;
+ PUCHAR pGroupIpAddr;
+ UCHAR GroupMacAddr[6];
+ PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr;
+
+ UINT8 MldType;
+ PUCHAR pMldHeader;
+
+ if(isMldPkt(pDstMacAddr, pIpHeader, &MldType, &pMldHeader) == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MLD type=%0x\n", MldType));
+
+ switch(MldType)
+ {
+ case MLD_V1_LISTENER_REPORT:
+ /* skip Type(1 Byte), code(1 Byte), checksum(2 Bytes), Maximum Rsp Delay(2 Bytes), Reserve(2 Bytes). */
+ pGroupIpAddr = (PUCHAR)(pMldHeader + 8);
+ ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IPV6);
+ DBGPRINT(RT_DEBUG_TRACE, ("Group Id=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5]));
+ MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC);
+ break;
+
+ case MLD_V1_LISTENER_DONE:
+ /* skip Type(1 Byte), code(1 Byte), checksum(2 Bytes), Maximum Rsp Delay(2 Bytes), Reserve(2 Bytes). */
+ pGroupIpAddr = (PUCHAR)(pMldHeader + 8);
+ ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IPV6);
+ DBGPRINT(RT_DEBUG_TRACE, ("Group Id=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2], GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5]));
+ MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev);
+ break;
+
+ case MLD_V2_LISTERNER_REPORT: /* IGMP version 3 membership report. */
+ numOfGroup = ntohs(*((UINT16 *)(pMldHeader + 6)));
+ pGroup = (PUCHAR)(pMldHeader + 8);
+ for (i=0; i < numOfGroup; i++)
+ {
+ GroupType = (UCHAR)(*pGroup);
+ AuxDataLen = (UCHAR)(*(pGroup + 1));
+ numOfSources = ntohs(*((UINT16 *)(pGroup + 2)));
+ pGroupIpAddr = (PUCHAR)(pGroup + 4);
+ DBGPRINT(RT_DEBUG_TRACE, ("MLDv2 Type=%d, ADL=%d, numOfSource=%d\n",
+ GroupType, AuxDataLen, numOfSources));
+ ConvertMulticastIP2MAC(pGroupIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IPV6);
+ DBGPRINT(RT_DEBUG_TRACE, ("MLD Group=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ GroupMacAddr[0], GroupMacAddr[1], GroupMacAddr[2],
+ GroupMacAddr[3], GroupMacAddr[4], GroupMacAddr[5]));
+
+ do
+ {
+ if ((GroupType == MODE_IS_EXCLUDE)
+ || (GroupType == CHANGE_TO_EXCLUDE_MODE)
+ || (GroupType == ALLOW_NEW_SOURCES))
+ {
+ MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC);
+ break;
+ }
+
+ if ((GroupType == CHANGE_TO_INCLUDE_MODE)
+ || (GroupType == MODE_IS_INCLUDE)
+ || (GroupType == BLOCK_OLD_SOURCES))
+ {
+ if(numOfSources == 0)
+ MulticastFilterTableDeleteEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev);
+ else
+ MulticastFilterTableInsertEntry(pAd, GroupMacAddr, pSrcMacAddr, pDev, MCAT_FILTER_DYNAMIC);
+ break;
+ }
+ } while(FALSE);
+ /* skip 4 Bytes (Record Type, Aux Data Len, Number of Sources) + a IPv6 address. */
+ pGroup += (4 + IPV6_ADDR_LEN + (numOfSources * 16) + AuxDataLen);
+ }
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("unknow MLD Type=%d\n", MldType));
+ break;
+ }
+ }
+
+ return;
+}
+
+
+#endif /* IGMP_SNOOP_SUPPORT */
diff --git a/cleopatre/devkit/mt7601udrv/common/image.bin b/cleopatre/devkit/mt7601udrv/common/image.bin
new file mode 100644
index 0000000000..f357c59ab4
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/image.bin
Binary files differ
diff --git a/cleopatre/devkit/mt7601udrv/common/misc.c b/cleopatre/devkit/mt7601udrv/common/misc.c
new file mode 100644
index 0000000000..72ca956049
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/misc.c
@@ -0,0 +1,35 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2009, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ misc.c
+
+ Abstract:
+
+ Handling Misc Problem
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Sean Wang 2009-08-12 Create
+ John Li 2009-11-30 Modified
+*/
+
+#include "rt_config.h"
+#include "misc.h"
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/mlme.c b/cleopatre/devkit/mt7601udrv/common/mlme.c
new file mode 100644
index 0000000000..e43726b26e
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/mlme.c
@@ -0,0 +1,4000 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ mlme.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John Chang 2004-08-25 Modify from RT2500 code base
+ John Chang 2004-09-06 modified for RT2600
+*/
+
+#include "rt_config.h"
+#include <stdarg.h>
+
+
+UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
+UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
+UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
+UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
+UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72};
+UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
+UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
+UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
+UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
+
+UCHAR OfdmRateToRxwiMCS[12] = {
+ 0, 0, 0, 0,
+ 0, 1, 2, 3, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */
+ 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */
+};
+
+UCHAR RxwiMCSToOfdmRate[12] = {
+ RATE_6, RATE_9, RATE_12, RATE_18,
+ RATE_24, RATE_36, RATE_48, RATE_54, /* OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3 */
+ 4, 5, 6, 7, /* OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7 */
+};
+
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+UINT32 CW_MAX_IN_BITS;
+#endif /* CONFIG_APSTA_MIXED_SUPPORT */
+
+
+
+
+extern UCHAR OfdmRateToRxwiMCS[];
+/* since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.*/
+/* otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate*/
+ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
+ 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
+ 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
+
+UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/* e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than*/
+/* this value, then it's quaranteed capable of operating in 36 mbps TX rate in*/
+/* clean environment.*/
+/* TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100*/
+CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
+
+UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
+USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
+
+UCHAR SsidIe = IE_SSID;
+UCHAR SupRateIe = IE_SUPP_RATES;
+UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
+#ifdef DOT11_N_SUPPORT
+UCHAR HtCapIe = IE_HT_CAP;
+UCHAR AddHtInfoIe = IE_ADD_HT;
+UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
+UCHAR BssCoexistIe = IE_2040_BSS_COEXIST;
+UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
+#endif /* DOT11_N_SUPPORT */
+UCHAR ExtCapIe = IE_EXT_CAPABILITY;
+UCHAR ErpIe = IE_ERP;
+UCHAR DsIe = IE_DS_PARM;
+UCHAR TimIe = IE_TIM;
+UCHAR WpaIe = IE_WPA;
+UCHAR Wpa2Ie = IE_WPA2;
+UCHAR IbssIe = IE_IBSS_PARM;
+UCHAR WapiIe = IE_WAPI;
+
+extern UCHAR WPA_OUI[];
+
+UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
+
+UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+
+
+UCHAR dot11_max_sup_rate(INT SupRateLen, UCHAR *SupRate, INT ExtRateLen, UCHAR *ExtRate)
+{
+ INT idx;
+ UCHAR MaxSupportedRateIn500Kbps = 0;
+
+ /* supported rates array may not be sorted. sort it and find the maximum rate */
+ for (idx = 0; idx < SupRateLen; idx++) {
+ if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f))
+ MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f;
+ }
+
+ if (ExtRateLen > 0 && ExtRate != NULL)
+ {
+ for (idx = 0; idx < ExtRateLen; idx++) {
+ if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f))
+ MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f;
+ }
+ }
+
+ return MaxSupportedRateIn500Kbps;
+}
+
+
+UCHAR dot11_2_ra_rate(UCHAR MaxSupportedRateIn500Kbps)
+{
+ UCHAR MaxSupportedRate;
+
+ 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;
+ }
+
+ return MaxSupportedRate;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ initialize the MLME task and its data structure (queue, spinlock,
+ timer, state machines).
+
+ IRQL = PASSIVE_LEVEL
+
+ Return:
+ always return NDIS_STATUS_SUCCESS
+
+ ==========================================================================
+*/
+NDIS_STATUS MlmeInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
+
+ do
+ {
+ Status = MlmeQueueInit(pAd, &pAd->Mlme.Queue);
+ if(Status != NDIS_STATUS_SUCCESS)
+ break;
+
+ pAd->Mlme.bRunning = FALSE;
+ NdisAllocateSpinLock(pAd, &pAd->Mlme.TaskLock);
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* init AP state machines*/
+ APAssocStateMachineInit(pAd, &pAd->Mlme.ApAssocMachine, pAd->Mlme.ApAssocFunc);
+ APAuthStateMachineInit(pAd, &pAd->Mlme.ApAuthMachine, pAd->Mlme.ApAuthFunc);
+ APSyncStateMachineInit(pAd, &pAd->Mlme.ApSyncMachine, pAd->Mlme.ApSyncFunc);
+
+#ifdef APCLI_SUPPORT
+ /* init apcli state machines*/
+ ASSERT(APCLI_AUTH_FUNC_SIZE == APCLI_MAX_AUTH_MSG * APCLI_MAX_AUTH_STATE);
+ ApCliAuthStateMachineInit(pAd, &pAd->Mlme.ApCliAuthMachine, pAd->Mlme.ApCliAuthFunc);
+
+ ASSERT(APCLI_ASSOC_FUNC_SIZE == APCLI_MAX_ASSOC_MSG * APCLI_MAX_ASSOC_STATE);
+ ApCliAssocStateMachineInit(pAd, &pAd->Mlme.ApCliAssocMachine, pAd->Mlme.ApCliAssocFunc);
+
+ ASSERT(APCLI_SYNC_FUNC_SIZE == APCLI_MAX_SYNC_MSG * APCLI_MAX_SYNC_STATE);
+ ApCliSyncStateMachineInit(pAd, &pAd->Mlme.ApCliSyncMachine, pAd->Mlme.ApCliSyncFunc);
+
+ ASSERT(APCLI_CTRL_FUNC_SIZE == APCLI_MAX_CTRL_MSG * APCLI_MAX_CTRL_STATE);
+ ApCliCtrlStateMachineInit(pAd, &pAd->Mlme.ApCliCtrlMachine, pAd->Mlme.ApCliCtrlFunc);
+
+#endif /* APCLI_SUPPORT */
+ }
+
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef WSC_INCLUDED
+ /* Init Wsc state machine */
+ ASSERT(WSC_FUNC_SIZE == MAX_WSC_MSG * MAX_WSC_STATE);
+ WscStateMachineInit(pAd, &pAd->Mlme.WscMachine, pAd->Mlme.WscFunc);
+#endif /* WSC_INCLUDED */
+
+ WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine, pAd->Mlme.WpaFunc);
+
+
+ ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
+
+ /* Init mlme periodic timer*/
+ RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
+
+#ifdef CONFIG_MULTI_CHANNEL
+ pAd->Mlme.StaStayTick = 0;
+ pAd->Mlme.P2pStayTick = 0;
+#endif /* CONFIG_MULTI_CHANNEL */
+
+ /* Set mlme periodic timer*/
+ RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
+
+ /* software-based RX Antenna diversity*/
+ RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* Init APSD periodic timer*/
+ RTMPInitTimer(pAd, &pAd->Mlme.APSDPeriodicTimer, GET_TIMER_FUNCTION(APSDPeriodicExec), pAd, TRUE);
+ RTMPSetTimer(&pAd->Mlme.APSDPeriodicTimer, 50);
+
+ /* Init APQuickResponseForRateUp timer.*/
+ RTMPInitTimer(pAd, &pAd->ApCfg.ApQuickResponeForRateUpTimer, GET_TIMER_FUNCTION(APQuickResponeForRateUpExec), pAd, FALSE);
+ pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = FALSE;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ } while (FALSE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
+
+ return Status;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ main loop of the MLME
+ Pre:
+ Mlme has to be initialized, and there are something inside the queue
+ Note:
+ This function is invoked from MPSetInformation and MPReceive;
+ This task guarantee only one MlmeHandler will run.
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeHandler(RTMP_ADAPTER *pAd)
+{
+ MLME_QUEUE_ELEM *Elem = NULL;
+#ifdef APCLI_SUPPORT
+ SHORT apcliIfIndex;
+#endif /* APCLI_SUPPORT */
+
+ /* Only accept MLME and Frame from peer side, no other (control/data) frame should*/
+ /* get into this state machine*/
+
+ NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
+ if(pAd->Mlme.bRunning)
+ {
+ NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+ return;
+ }
+ else
+ {
+ pAd->Mlme.bRunning = TRUE;
+ }
+ NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+
+ while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
+ {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_SUSPEND))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
+ break;
+ }
+
+#ifdef RALINK_ATE
+ if(ATE_ON(pAd))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n"));
+ break;
+ }
+#endif /* RALINK_ATE */
+
+ /*From message type, determine which state machine I should drive*/
+ if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
+ {
+#ifdef RTMP_MAC_USB
+ if (Elem->MsgType == MT2_RESET_CONF)
+ {
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
+ MlmeRestartStateMachine(pAd);
+ Elem->Occupied = FALSE;
+ Elem->MsgLen = 0;
+ continue;
+ }
+#endif /* RTMP_MAC_USB */
+
+ /* if dequeue success*/
+ switch (Elem->Machine)
+ {
+ /* STA state machines*/
+
+ case ACTION_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine,
+ Elem, pAd->Mlme.ActMachine.CurrState);
+ break;
+
+#ifdef CONFIG_AP_SUPPORT
+ /* AP state amchines*/
+
+ case AP_ASSOC_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.ApAssocMachine,
+ Elem, pAd->Mlme.ApAssocMachine.CurrState);
+ break;
+
+ case AP_AUTH_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.ApAuthMachine,
+ Elem, pAd->Mlme.ApAuthMachine.CurrState);
+ break;
+
+ case AP_SYNC_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.ApSyncMachine,
+ Elem, pAd->Mlme.ApSyncMachine.CurrState);
+ break;
+
+#ifdef APCLI_SUPPORT
+ case APCLI_AUTH_STATE_MACHINE:
+ apcliIfIndex = Elem->Priv;
+ if(isValidApCliIf(apcliIfIndex))
+ StateMachinePerformAction(pAd, &pAd->Mlme.ApCliAuthMachine, Elem,
+ (pAd->ApCfg.ApCliTab[apcliIfIndex].AuthCurrState));
+ break;
+
+ case APCLI_ASSOC_STATE_MACHINE:
+ apcliIfIndex = Elem->Priv;
+ if(isValidApCliIf(apcliIfIndex))
+ StateMachinePerformAction(pAd, &pAd->Mlme.ApCliAssocMachine, Elem,
+ (pAd->ApCfg.ApCliTab[apcliIfIndex].AssocCurrState));
+ break;
+
+ case APCLI_SYNC_STATE_MACHINE:
+ apcliIfIndex = Elem->Priv;
+ if(isValidApCliIf(apcliIfIndex))
+ StateMachinePerformAction(pAd, &pAd->Mlme.ApCliSyncMachine, Elem,
+ (pAd->ApCfg.ApCliTab[apcliIfIndex].SyncCurrState));
+ break;
+
+ case APCLI_CTRL_STATE_MACHINE:
+ apcliIfIndex = Elem->Priv;
+ if(isValidApCliIf(apcliIfIndex))
+ StateMachinePerformAction(pAd, &pAd->Mlme.ApCliCtrlMachine, Elem,
+ (pAd->ApCfg.ApCliTab[apcliIfIndex].CtrlCurrState));
+ break;
+#endif /* APCLI_SUPPORT */
+
+#endif /* CONFIG_AP_SUPPORT */
+ case WPA_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.WpaMachine, Elem, pAd->Mlme.WpaMachine.CurrState);
+ break;
+#ifdef WSC_INCLUDED
+ case WSC_STATE_MACHINE:
+ if (pAd->pWscElme)
+ {
+ RTMP_SEM_LOCK(&pAd->WscElmeLock);
+ NdisMoveMemory(pAd->pWscElme, Elem, sizeof(MLME_QUEUE_ELEM));
+ RTMP_SEM_UNLOCK(&pAd->WscElmeLock);
+/*#ifdef KTHREAD_SUPPORT*/
+/* WAKE_UP(&(pAd->wscTask));*/
+/*#else*/
+/* RTMP_SEM_EVENT_UP(&(pAd->wscTask.taskSema));*/
+/*#endif*/
+ RtmpOsTaskWakeUp(&(pAd->wscTask));
+ }
+ break;
+#endif /* WSC_INCLUDED */
+
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
+ break;
+ } /* end of switch*/
+
+ /* free MLME element*/
+ Elem->Occupied = FALSE;
+ Elem->MsgLen = 0;
+
+ }
+ else {
+ DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
+ }
+ }
+
+ NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
+ pAd->Mlme.bRunning = FALSE;
+ NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Destructor of MLME (Destroy queue, state machine, spin lock and timer)
+ Parameters:
+ Adapter - NIC Adapter pointer
+ Post:
+ The MLME task will no longer work properly
+
+ IRQL = PASSIVE_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeHalt(
+ IN PRTMP_ADAPTER pAd)
+{
+ BOOLEAN Cancelled;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
+
+ if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ {
+ /* disable BEACON generation and other BEACON related hardware timers*/
+ AsicDisableSync(pAd);
+ }
+
+ RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
+
+
+ RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ RTMPCancelTimer(&pAd->Mlme.APSDPeriodicTimer, &Cancelled);
+
+ if (pAd->ApCfg.ApQuickResponeForRateUpTimerRunning == TRUE)
+ RTMPCancelTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, &Cancelled);
+
+#ifdef APCLI_SUPPORT
+ RTMPCancelTimer(&pAd->ApCliMlmeAux.ProbeTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->ApCliMlmeAux.ApCliAssocTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->ApCliMlmeAux.ApCliAuthTimer, &Cancelled);
+
+#ifdef WSC_AP_SUPPORT
+ if (pAd->ApCfg.ApCliTab[BSS0].WscControl.WscProfileRetryTimerRunning)
+ {
+ pAd->ApCfg.ApCliTab[BSS0].WscControl.WscProfileRetryTimerRunning = FALSE;
+ RTMPCancelTimer(&pAd->ApCfg.ApCliTab[BSS0].WscControl.WscProfileRetryTimer, &Cancelled);
+ }
+#endif /* WSC_AP_SUPPORT */
+#endif /* APCLI_SUPPORT */
+ RTMPCancelTimer(&pAd->MlmeAux.APScanTimer, &Cancelled);
+ }
+
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+ if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ {
+ RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
+
+#ifdef LED_CONTROL_SUPPORT
+ /* Set LED*/
+ RTMPSetLED(pAd, LED_HALT);
+ RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, firmware is not done it.*/
+#ifdef RTMP_MAC_USB
+ {
+ LED_CFG_STRUC LedCfg;
+ RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
+ LedCfg.field.LedPolar = 0;
+ LedCfg.field.RLedMode = 0;
+ LedCfg.field.GLedMode = 0;
+ LedCfg.field.YLedMode = 0;
+ RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
+ }
+#endif /* RTMP_MAC_USB */
+#endif /* LED_CONTROL_SUPPORT */
+
+#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT)
+ if (pAd->WOW_Cfg.bEnable == FALSE)
+#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */
+ if (pChipOps->AsicHaltAction)
+ pChipOps->AsicHaltAction(pAd);
+ }
+
+ RTMPusecDelay(5000); /* 5 msec to gurantee Ant Diversity timer canceled*/
+
+ MlmeQueueDestroy(&pAd->Mlme.Queue);
+ NdisFreeSpinLock(&pAd->Mlme.TaskLock);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
+}
+
+VOID MlmeResetRalinkCounters(
+ IN PRTMP_ADAPTER pAd)
+{
+ pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
+
+#ifdef RALINK_ATE
+ if (!ATE_ON(pAd))
+#endif /* RALINK_ATE */
+ /* for performace enchanement */
+ NdisZeroMemory(&pAd->RalinkCounters,
+ (UINT32)&pAd->RalinkCounters.OneSecEnd -
+ (UINT32)&pAd->RalinkCounters.OneSecStart);
+
+ return;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ This routine is executed periodically to -
+ 1. Decide if it's a right time to turn on PwrMgmt bit of all
+ outgoiing frames
+ 2. Calculate ChannelQuality based on statistics of the last
+ period, so that TX rate won't toggling very frequently between a
+ successful TX and a failed TX.
+ 3. If the calculated ChannelQuality indicated current connection not
+ healthy, then a ROAMing attempt is tried here.
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+#define ADHOC_BEACON_LOST_TIME (8*OS_HZ) /* 8 sec*/
+VOID MlmePeriodicExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ ULONG TxTotalCnt;
+ PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
+
+#ifdef MICROWAVE_OVEN_SUPPORT
+ /* update False CCA count to an array */
+ NICUpdateRxStatusCnt1(pAd, pAd->Mlme.PeriodicRound%10);
+#endif /* MICROWAVE_OVEN_SUPPORT */
+
+ /* No More 0x84 MCU CMD from v.30 FW*/
+
+#ifdef MICROWAVE_OVEN_SUPPORT
+ //printk("MO_Cfg.bEnable=%d \n", pAd->CommonCfg.MO_Cfg.bEnable);
+ if (pAd->CommonCfg.MO_Cfg.bEnable)
+ {
+ UINT8 stage = pAd->Mlme.PeriodicRound%10;
+
+ if (stage == MO_MEAS_PERIOD)
+ {
+ ASIC_MEASURE_FALSE_CCA(pAd);
+ pAd->CommonCfg.MO_Cfg.nPeriod_Cnt = 0;
+ }
+ else if (stage == MO_IDLE_PERIOD)
+ {
+ UINT16 Idx;
+
+ for (Idx = MO_MEAS_PERIOD + 1; Idx < MO_IDLE_PERIOD + 1; Idx++)
+ pAd->CommonCfg.MO_Cfg.nFalseCCACnt += pAd->RalinkCounters.FalseCCACnt_100MS[Idx];
+
+ //printk("%s: fales cca1 %d\n", __FUNCTION__, pAd->CommonCfg.MO_Cfg.nFalseCCACnt);
+ if (pAd->CommonCfg.MO_Cfg.nFalseCCACnt > pAd->CommonCfg.MO_Cfg.nFalseCCATh)
+ ASIC_MITIGATE_MICROWAVE(pAd);
+
+ }
+ }
+#endif /* MICROWAVE_OVEN_SUPPORT */
+
+#ifdef INF_AMAZON_SE
+#ifdef RTMP_MAC_USB
+ SoftwareFlowControl(pAd);
+#endif /* RTMP_MAC_USB */
+#endif /* INF_AMAZON_SE */
+
+
+ /* Do nothing if the driver is starting halt state.*/
+ /* This might happen when timer already been fired before cancel timer with mlmehalt*/
+ if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
+ fRTMP_ADAPTER_RADIO_OFF |
+ fRTMP_ADAPTER_RADIO_MEASUREMENT |
+ fRTMP_ADAPTER_RESET_IN_PROGRESS |
+ fRTMP_ADAPTER_NIC_NOT_EXIST))))
+ return;
+
+
+ pAd->bUpdateBcnCntDone = FALSE;
+
+/* RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);*/
+ pAd->Mlme.PeriodicRound ++;
+ pAd->Mlme.GPIORound++;
+
+#ifdef RTMP_MAC_USB
+ /* execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.*/
+ NICUpdateFifoStaCounters(pAd);
+#ifdef CONFIG_AP_SUPPORT
+#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT
+ if (pAd->CommonCfg.CarrierDetect.Enable)
+ CarrierDetectionPeriodicStateCtrl(pAd);
+#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* RTMP_MAC_USB */
+
+#ifdef CONFIG_MULTI_CHANNEL
+ /*
+ Use StayTicks to call MlmeDynamicTxRateSwitching
+ */
+ if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
+ )
+ && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
+ {
+
+ if (INFRA_ON(pAd)
+ && ((pAd->MultiChannelFlowCtl & EDCA_AC0_DEQUEUE_DISABLE) == 0))
+ {
+ pAd->Mlme.StaStayTick++;
+ }
+
+ if (P2P_CLI_ON(pAd)
+ && ((pAd->MultiChannelFlowCtl & HCCA_DEQUEUE_DISABLE) == 0))
+ {
+ pAd->Mlme.P2pStayTick++;
+ }
+
+ if ((pAd->P2pCfg.bStartP2pConnect == FALSE)
+#ifdef CONFIG_MULTI_CHANNEL
+ && (pAd->Multi_Channel_Enable == TRUE)
+#endif /* CONFIG_MULTI_CHANNEL */
+)
+ MlmeDynamicTxRateSwitching(pAd);
+ }
+#endif /* CONFIG_MULTI_CHANNEL */
+
+
+ /* by default, execute every 500ms */
+ if ((pAd->ra_interval) &&
+ ((pAd->Mlme.PeriodicRound % (pAd->ra_interval / 100)) == 0) &&
+ RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/
+ )
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ APMlmeDynamicTxRateSwitching(pAd);
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+#ifdef DFS_SUPPORT
+#ifdef CONFIG_AP_SUPPORT
+#ifdef RTMP_MAC_USB
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if ((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == TRUE))
+ NewUsbTimerCB_Radar(pAd);
+ }
+#endif /* RTMP_MAC_USB */
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* DFS_SUPPORT */
+
+
+
+
+ /* Normal 1 second Mlme PeriodicExec.*/
+ if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
+ {
+ pAd->Mlme.OneSecPeriodicRound ++;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ dynamic_tune_be_tx_op(pAd, 50); /* change form 100 to 50 for WMM WiFi test @20070504*/
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /*ORIBATimerTimeout(pAd);*/
+ NdisGetSystemUpTime(&pAd->Mlme.Now32);
+
+ /* add the most up-to-date h/w raw counters into software variable, so that*/
+ /* the dynamic tuning mechanism below are based on most up-to-date information*/
+ /* Hint: throughput impact is very serious in the function */
+ NICUpdateRawCounters(pAd);
+
+#ifdef RTMP_MAC_USB
+#ifndef INF_AMAZON_SE
+#ifndef CONFIG_MULTI_CHANNEL
+ RTUSBWatchDog(pAd);
+#endif /* !CONFIG_MULTI_CHANNEL */
+#endif /* INF_AMAZON_SE */
+#endif /* RTMP_MAC_USB */
+
+#ifdef DOT11_N_SUPPORT
+ /* Need statistics after read counter. So put after NICUpdateRawCounters*/
+ ORIBATimerTimeout(pAd);
+#endif /* DOT11_N_SUPPORT */
+
+ /*
+ if (pAd->RalinkCounters.MgmtRingFullCount >= 2)
+ RTMP_SET_FLAG(pAd, fRTMP_HW_ERR);
+ else
+ pAd->RalinkCounters.MgmtRingFullCount = 0;
+ */
+
+ /* The time period for checking antenna is according to traffic*/
+ {
+ if (pAd->Mlme.bEnableAutoAntennaCheck)
+ {
+ TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
+ pAd->RalinkCounters.OneSecTxRetryOkCount +
+ pAd->RalinkCounters.OneSecTxFailCount;
+
+ /* dynamic adjust antenna evaluation period according to the traffic*/
+ if (TxTotalCnt > 50)
+ {
+ if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
+ AsicEvaluateRxAnt(pAd);
+ }
+ else
+ {
+ if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
+ AsicEvaluateRxAnt(pAd);
+ }
+ }
+ }
+
+#ifdef VIDEO_TURBINE_SUPPORT
+ /*
+ VideoTurbineUpdate(pAd);
+ VideoTurbineDynamicTune(pAd);
+ */
+#endif /* VIDEO_TURBINE_SUPPORT */
+
+#ifdef VCORECAL_SUPPORT
+ {
+ if ((pAd->Mlme.OneSecPeriodicRound % 10) == 0)
+ AsicVCORecalibration(pAd);
+ }
+#endif /* VCORECAL_SUPPORT */
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ APMlmePeriodicExec(pAd);
+
+ if ((pAd->RalinkCounters.OneSecBeaconSentCnt == 0)
+ && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+ && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ && ((pAd->CommonCfg.bIEEE80211H != 1)
+ || (pAd->Dot11_H.RDMode != RD_SILENCE_MODE))
+#ifdef WDS_SUPPORT
+ && (pAd->WdsTab.Mode != WDS_BRIDGE_MODE)
+#endif /* WDS_SUPPORT */
+#ifdef CARRIER_DETECTION_SUPPORT
+ && (isCarrierDetectExist(pAd) == FALSE)
+#endif /* CARRIER_DETECTION_SUPPORT */
+ )
+ pAd->macwd ++;
+ else
+ pAd->macwd = 0;
+
+ if (pAd->macwd > 1)
+ {
+ int count = 0;
+ BOOLEAN MAC_ready = FALSE;
+ UINT32 MacCsr12 = 0;
+
+ /* Disable MAC*/
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
+
+ /* polling MAC status*/
+ while (count < 10)
+ {
+ RTMPusecDelay(1000); /* 1 ms*/
+ RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacCsr12);
+
+ /* if MAC is idle*/
+ if ((MacCsr12 & 0x03) == 0)
+ {
+ MAC_ready = TRUE;
+ break;
+ }
+ count ++;
+ }
+
+ if (MAC_ready)
+ {
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
+ RTMPusecDelay(1);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("Warning, MAC isn't ready \n"));
+ }
+
+ {
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
+ }
+
+ DBGPRINT(RT_DEBUG_WARN, ("MAC specific condition \n"));
+
+#ifdef AP_QLOAD_SUPPORT
+ Show_QoSLoad_Proc(pAd, NULL);
+#endif /* AP_QLOAD_SUPPORT */
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+ MlmeResetRalinkCounters(pAd);
+
+
+ RTMP_MLME_HANDLER(pAd);
+ }
+
+#ifdef WSC_INCLUDED
+ WSC_HDR_BTN_MR_HANDLE(pAd);
+#endif /* WSC_INCLUDED */
+
+
+
+ pAd->bUpdateBcnCntDone = FALSE;
+}
+
+
+/*
+ ==========================================================================
+ Validate SSID for connection try and rescan purpose
+ Valid SSID will have visible chars only.
+ The valid length is from 0 to 32.
+ IRQL = DISPATCH_LEVEL
+ ==========================================================================
+ */
+BOOLEAN MlmeValidateSSID(
+ IN PUCHAR pSsid,
+ IN UCHAR SsidLen)
+{
+ int index;
+
+ if (SsidLen > MAX_LEN_OF_SSID)
+ return (FALSE);
+
+ /* Check each character value*/
+ for (index = 0; index < SsidLen; index++)
+ {
+ if (pSsid[index] < 0x20)
+ return (FALSE);
+ }
+
+ /* All checked*/
+ return (TRUE);
+}
+
+
+
+/*
+ ==========================================================================
+ Description:
+ This routine calculates TxPER, RxPER of the past N-sec period. And
+ according to the calculation result, ChannelQuality is calculated here
+ to decide if current AP is still doing the job.
+
+ If ChannelQuality is not good, a ROAMing attempt may be tried later.
+ Output:
+ StaCfg.ChannelQuality - 0..100
+
+ IRQL = DISPATCH_LEVEL
+
+ NOTE: This routine decide channle quality based on RX CRC error ratio.
+ Caller should make sure a function call to NICUpdateRawCounters(pAd)
+ is performed right before this routine, so that this routine can decide
+ channel quality based on the most up-to-date information
+ ==========================================================================
+ */
+VOID MlmeCalculateChannelQuality(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pMacEntry,
+ IN ULONG Now32)
+{
+ ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
+ ULONG RxCnt, RxPER;
+ UCHAR NorRssi;
+ CHAR MaxRssi;
+ RSSI_SAMPLE *pRssiSample = NULL;
+ UINT32 OneSecTxNoRetryOkCount = 0;
+ UINT32 OneSecTxRetryOkCount = 0;
+ UINT32 OneSecTxFailCount = 0;
+ UINT32 OneSecRxOkCnt = 0;
+ UINT32 OneSecRxFcsErrCnt = 0;
+ ULONG ChannelQuality = 0; /* 0..100, Channel Quality Indication for Roaming*/
+
+
+
+ if (pMacEntry != NULL)
+ {
+ pRssiSample = &pMacEntry->RssiSample;
+ OneSecTxNoRetryOkCount = pMacEntry->OneSecTxNoRetryOkCount;
+ OneSecTxRetryOkCount = pMacEntry->OneSecTxRetryOkCount;
+ OneSecTxFailCount = pMacEntry->OneSecTxFailCount;
+ OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
+ OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
+ }
+ else
+ {
+ pRssiSample = &pAd->MacTab.Content[0].RssiSample;
+ OneSecTxNoRetryOkCount = pAd->RalinkCounters.OneSecTxNoRetryOkCount;
+ OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount;
+ OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount;
+ OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
+ OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
+ }
+
+ if (pRssiSample == NULL)
+ return;
+ MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0,
+ pRssiSample->LastRssi1,
+ pRssiSample->LastRssi2);
+
+
+ /*
+ calculate TX packet error ratio and TX retry ratio - if too few TX samples,
+ skip TX related statistics
+ */
+ TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount;
+ TxCnt = TxOkCnt + OneSecTxFailCount;
+ if (TxCnt < 5)
+ {
+ TxPER = 0;
+ TxPRR = 0;
+ }
+ else
+ {
+ TxPER = (OneSecTxFailCount * 100) / TxCnt;
+ TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt;
+ }
+
+
+ /* calculate RX PER - don't take RxPER into consideration if too few sample*/
+ RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt;
+ if (RxCnt < 5)
+ RxPER = 0;
+ else
+ RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt;
+
+
+ /* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER*/
+ {
+ /* Normalize Rssi*/
+ if (MaxRssi > -40)
+ NorRssi = 100;
+ else if (MaxRssi < -90)
+ NorRssi = 0;
+ else
+ NorRssi = (MaxRssi + 90) * 2;
+
+ /* ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)*/
+ ChannelQuality = (RSSI_WEIGHTING * NorRssi +
+ TX_WEIGHTING * (100 - TxPRR) +
+ RX_WEIGHTING* (100 - RxPER)) / 100;
+ }
+
+
+#ifdef CONFIG_AP_SUPPORT
+ if (pAd->OpMode == OPMODE_AP)
+ {
+ if (pMacEntry != NULL)
+ pMacEntry->ChannelQuality = (ChannelQuality > 100) ? 100 : ChannelQuality;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+}
+
+
+/* IRQL = DISPATCH_LEVEL*/
+VOID MlmeSetTxPreamble(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT TxPreamble)
+{
+ AUTO_RSP_CFG_STRUC csr4;
+
+
+ /* Always use Long preamble before verifiation short preamble functionality works well.*/
+ /* Todo: remove the following line if short preamble functionality works*/
+
+ /*TxPreamble = Rt802_11PreambleLong;*/
+
+ RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
+ if (TxPreamble == Rt802_11PreambleLong)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+ csr4.field.AutoResponderPreamble = 0;
+ }
+ else
+ {
+ /* NOTE: 1Mbps should always use long preamble*/
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+ csr4.field.AutoResponderPreamble = 1;
+ }
+
+ RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Update basic rate bitmap
+ ==========================================================================
+ */
+
+VOID UpdateBasicRateBitmap(
+ IN PRTMP_ADAPTER pAdapter)
+{
+ INT i, j;
+ /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
+ UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
+ UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
+ UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
+ ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
+
+ /* if A mode, always use fix BasicRateBitMap */
+ /*if (pAdapter->CommonCfg.Channel == WMODE_A)*/
+ if (pAdapter->CommonCfg.Channel > 14)
+ {
+ if (pAdapter->CommonCfg.BasicRateBitmap & 0xF)
+ {
+ /* no 11b rate in 5G band */
+ pAdapter->CommonCfg.BasicRateBitmapOld = \
+ pAdapter->CommonCfg.BasicRateBitmap;
+ pAdapter->CommonCfg.BasicRateBitmap &= (~0xF); /* no 11b */
+ }
+
+ /* force to 6,12,24M in a-band */
+ pAdapter->CommonCfg.BasicRateBitmap |= 0x150; /* 6, 12, 24M */
+ }
+ else
+ {
+ /* no need to modify in 2.4G (bg mixed) */
+ pAdapter->CommonCfg.BasicRateBitmap = \
+ pAdapter->CommonCfg.BasicRateBitmapOld;
+ }
+
+ if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
+ {
+ /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
+ return;
+ }
+
+ for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
+ {
+ sup_p[i] &= 0x7f;
+ ext_p[i] &= 0x7f;
+ }
+
+ for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
+ {
+ if (bitmap & (1 << i))
+ {
+ for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
+ {
+ if (sup_p[j] == rate[i])
+ sup_p[j] |= 0x80;
+ }
+
+ for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
+ {
+ if (ext_p[j] == rate[i])
+ ext_p[j] |= 0x80;
+ }
+ }
+ }
+}
+
+/*
+ bLinkUp is to identify the inital link speed.
+ TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
+*/
+VOID MlmeUpdateTxRates(
+ IN RTMP_ADAPTER *pAd,
+ IN BOOLEAN bLinkUp,
+ IN UCHAR apidx)
+{
+ int i, num;
+ UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
+ UCHAR MinSupport = RATE_54;
+ ULONG BasicRateBitmap = 0;
+ UCHAR CurrBasicRate = RATE_1;
+ UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
+ HTTRANSMIT_SETTING *pHtPhy = NULL, *pMaxHtPhy = NULL, *pMinHtPhy = NULL;
+ BOOLEAN *auto_rate_cur_p;
+ UCHAR HtMcs = MCS_AUTO;
+
+ /* find max desired rate*/
+ UpdateBasicRateBitmap(pAd);
+
+ num = 0;
+ auto_rate_cur_p = NULL;
+ for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
+ {
+ switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
+ {
+ case 2: Rate = RATE_1; num++; break;
+ case 4: Rate = RATE_2; num++; break;
+ case 11: Rate = RATE_5_5; num++; break;
+ case 22: Rate = RATE_11; num++; break;
+ case 12: Rate = RATE_6; num++; break;
+ case 18: Rate = RATE_9; num++; break;
+ case 24: Rate = RATE_12; num++; break;
+ case 36: Rate = RATE_18; num++; break;
+ case 48: Rate = RATE_24; num++; break;
+ case 72: Rate = RATE_36; num++; break;
+ case 96: Rate = RATE_48; num++; break;
+ case 108: Rate = RATE_54; num++; break;
+ /*default: Rate = RATE_1; break;*/
+ }
+ if (MaxDesire < Rate) MaxDesire = Rate;
+ }
+
+/*===========================================================================*/
+/*===========================================================================*/
+ do
+ {
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ if (apidx >= MIN_NET_DEVICE_FOR_APCLI)
+ {
+ UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI;
+
+ if (idx < MAX_APCLI_NUM)
+ {
+ pHtPhy = &pAd->ApCfg.ApCliTab[idx].HTPhyMode;
+ pMaxHtPhy = &pAd->ApCfg.ApCliTab[idx].MaxHTPhyMode;
+ pMinHtPhy = &pAd->ApCfg.ApCliTab[idx].MinHTPhyMode;
+
+ auto_rate_cur_p = &pAd->ApCfg.ApCliTab[idx].bAutoTxRateSwitch;
+ HtMcs = pAd->ApCfg.ApCliTab[idx].DesiredTransmitSetting.field.MCS;
+ break;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid idx(%d)\n", __FUNCTION__, idx));
+ return;
+ }
+ }
+#endif /* APCLI_SUPPORT */
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef WDS_SUPPORT
+ if (apidx >= MIN_NET_DEVICE_FOR_WDS)
+ {
+ UCHAR idx = apidx - MIN_NET_DEVICE_FOR_WDS;
+
+ if (idx < MAX_WDS_ENTRY)
+ {
+ pHtPhy = &pAd->WdsTab.WdsEntry[idx].HTPhyMode;
+ pMaxHtPhy = &pAd->WdsTab.WdsEntry[idx].MaxHTPhyMode;
+ pMinHtPhy = &pAd->WdsTab.WdsEntry[idx].MinHTPhyMode;
+
+ auto_rate_cur_p = &pAd->WdsTab.WdsEntry[idx].bAutoTxRateSwitch;
+ HtMcs = pAd->WdsTab.WdsEntry[idx].DesiredTransmitSetting.field.MCS;
+ break;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx));
+ return;
+ }
+ }
+#endif /* WDS_SUPPORT */
+
+ if ((apidx < pAd->ApCfg.BssidNum) &&
+ (apidx < MAX_MBSSID_NUM(pAd)) &&
+ (apidx < HW_BEACON_MAX_NUM))
+ {
+ pHtPhy = &pAd->ApCfg.MBSSID[apidx].HTPhyMode;
+ pMaxHtPhy = &pAd->ApCfg.MBSSID[apidx].MaxHTPhyMode;
+ pMinHtPhy = &pAd->ApCfg.MBSSID[apidx].MinHTPhyMode;
+
+ auto_rate_cur_p = &pAd->ApCfg.MBSSID[apidx].bAutoTxRateSwitch;
+ HtMcs = pAd->ApCfg.MBSSID[apidx].DesiredTransmitSetting.field.MCS;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx));
+ }
+ break;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ } while(FALSE);
+
+ pAd->CommonCfg.MaxDesiredRate = MaxDesire;
+
+ if (pMinHtPhy == NULL)
+ return;
+ pMinHtPhy->word = 0;
+ pMaxHtPhy->word = 0;
+ pHtPhy->word = 0;
+
+ /*
+ Auto rate switching is enabled only if more than one DESIRED RATES are
+ specified; otherwise disabled
+ */
+ if (num <= 1)
+ *auto_rate_cur_p = FALSE;
+ else
+ *auto_rate_cur_p = TRUE;
+
+ if (HtMcs != MCS_AUTO)
+ *auto_rate_cur_p = FALSE;
+ else
+ *auto_rate_cur_p = TRUE;
+
+ {
+ pSupRate = &pAd->CommonCfg.SupRate[0];
+ pExtRate = &pAd->CommonCfg.ExtRate[0];
+ SupRateLen = pAd->CommonCfg.SupRateLen;
+ ExtRateLen = pAd->CommonCfg.ExtRateLen;
+ }
+
+ /* find max supported rate*/
+ for (i=0; i<SupRateLen; i++)
+ {
+ switch (pSupRate[i] & 0x7f)
+ {
+ case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 0; break;
+ case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 1; break;
+ case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 2; break;
+ case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 3; break;
+ case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 1 << 4; break;
+ case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 5; break;
+ case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 1 << 6; break;
+ case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 7; break;
+ case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 1 << 8; break;
+ case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 9; break;
+ case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 10; break;
+ case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 1 << 11; break;
+ default: Rate = RATE_1; break;
+ }
+
+ if (MaxSupport < Rate)
+ MaxSupport = Rate;
+
+ if (MinSupport > Rate)
+ MinSupport = Rate;
+ }
+
+ for (i=0; i<ExtRateLen; i++)
+ {
+ switch (pExtRate[i] & 0x7f)
+ {
+ case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 0; break;
+ case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 1; break;
+ case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 2; break;
+ case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 3; break;
+ case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 1 << 4; break;
+ case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 5; break;
+ case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 1 << 6; break;
+ case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 7; break;
+ case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 1 << 8; break;
+ case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 9; break;
+ case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 10; break;
+ case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 1 << 11; break;
+ default: Rate = RATE_1;
+ break;
+ }
+ if (MaxSupport < Rate)
+ MaxSupport = Rate;
+
+ if (MinSupport > Rate)
+ MinSupport = Rate;
+ }
+
+ RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
+
+ for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
+ {
+ if (BasicRateBitmap & (0x01 << i))
+ CurrBasicRate = (UCHAR)i;
+ pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s():[MaxSupport = %d] = MaxDesire %d Mbps\n",
+ __FUNCTION__, RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
+ /* max tx rate = min {max desire rate, max supported rate}*/
+ if (MaxSupport < MaxDesire)
+ pAd->CommonCfg.MaxTxRate = MaxSupport;
+ else
+ pAd->CommonCfg.MaxTxRate = MaxDesire;
+
+ pAd->CommonCfg.MinTxRate = MinSupport;
+ /*
+ 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
+ ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
+ on average RSSI
+ 1. RSSI >= -70db, start at 54 Mbps (short distance)
+ 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
+ 3. -75 > RSSI, start at 11 Mbps (long distance)
+ */
+ if (*auto_rate_cur_p)
+ {
+ short dbm = 0;
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ dbm =0;
+#endif /* CONFIG_AP_SUPPORT */
+ if (bLinkUp == TRUE)
+ pAd->CommonCfg.TxRate = RATE_24;
+ else
+ pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
+
+ if (dbm < -75)
+ pAd->CommonCfg.TxRate = RATE_11;
+ else if (dbm < -70)
+ pAd->CommonCfg.TxRate = RATE_24;
+
+ /* should never exceed MaxTxRate (consider 11B-only mode)*/
+ if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
+ pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
+
+ pAd->CommonCfg.TxRateIndex = 0;
+
+ }
+ else
+ {
+ pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
+
+ /* Choose the Desire Tx MCS in CCK/OFDM mode */
+ if (num > RATE_6)
+ {
+ if (HtMcs <= MCS_7)
+ MaxDesire = RxwiMCSToOfdmRate[HtMcs];
+ else
+ MaxDesire = MinSupport;
+ }
+ else
+ {
+ if (HtMcs <= MCS_3)
+ MaxDesire = HtMcs;
+ else
+ MaxDesire = MinSupport;
+ }
+
+ pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
+ pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
+ pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
+ pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
+
+ }
+
+ if (pAd->CommonCfg.TxRate <= RATE_11)
+ {
+ pMaxHtPhy->field.MODE = MODE_CCK;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ pMaxHtPhy->field.MCS = MaxDesire;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ else
+ {
+ pMaxHtPhy->field.MODE = MODE_OFDM;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[MaxDesire];
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+
+ pHtPhy->word = (pMaxHtPhy->word);
+ if (bLinkUp && (pAd->OpMode == OPMODE_STA))
+ {
+ pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
+ pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
+ pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
+ }
+ else
+ {
+ if (WMODE_CAP(pAd->CommonCfg.PhyMode, WMODE_B) &&
+ pAd->CommonCfg.Channel <= 14)
+ {
+ pAd->CommonCfg.MlmeRate = RATE_1;
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
+ pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
+ pAd->CommonCfg.RtsRate = RATE_11;
+ }
+ else
+ {
+ pAd->CommonCfg.MlmeRate = RATE_6;
+ pAd->CommonCfg.RtsRate = RATE_6;
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+ pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+ }
+
+ /* Keep Basic Mlme Rate.*/
+ pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
+ if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
+ pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
+ else
+ pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
+ pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef MCAST_RATE_SPECIFIC
+ {
+ /* set default value if MCastPhyMode is not initialized */
+ HTTRANSMIT_SETTING tPhyMode;
+
+ memset(&tPhyMode, 0, sizeof(HTTRANSMIT_SETTING));
+ if (memcmp(&pAd->CommonCfg.MCastPhyMode, &tPhyMode, sizeof(HTTRANSMIT_SETTING)) == 0)
+ {
+ memmove(&pAd->CommonCfg.MCastPhyMode, &pAd->MacTab.Content[MCAST_WCID].HTPhyMode,
+ sizeof(HTTRANSMIT_SETTING));
+ }
+ }
+#endif /* MCAST_RATE_SPECIFIC */
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, (" %s(): (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
+ __FUNCTION__, RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport],
+ RateIdToMbps[pAd->CommonCfg.MaxTxRate],
+ RateIdToMbps[pAd->CommonCfg.MinTxRate],
+ /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
+ DBGPRINT(RT_DEBUG_TRACE, (" %s(): (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
+ __FUNCTION__, RateIdToMbps[pAd->CommonCfg.TxRate],
+ RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
+ __FUNCTION__, pAd->CommonCfg.MlmeTransmit.word,
+ pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word,
+ pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word,
+ pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word ));
+}
+
+#ifdef DOT11_N_SUPPORT
+/*
+ ==========================================================================
+ Description:
+ This function update HT Rate setting.
+ Input Wcid value is valid for 2 case :
+ 1. it's used for Station in infra mode that copy AP rate to Mactable.
+ 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeUpdateHtTxRates(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR apidx)
+{
+ UCHAR StbcMcs;
+ RT_HT_CAPABILITY *pRtHtCap = NULL;
+ RT_PHY_INFO *pActiveHtPhy = NULL;
+ ULONG BasicMCS;
+ RT_PHY_INFO *pDesireHtPhy = NULL;
+ PHTTRANSMIT_SETTING pHtPhy = NULL;
+ PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
+ PHTTRANSMIT_SETTING pMinHtPhy = NULL;
+ BOOLEAN *auto_rate_cur_p;
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s()===> \n", __FUNCTION__));
+
+ auto_rate_cur_p = NULL;
+
+ do
+ {
+#ifdef CONFIG_AP_SUPPORT
+
+#ifdef APCLI_SUPPORT
+ if (apidx >= MIN_NET_DEVICE_FOR_APCLI)
+ {
+ UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI;
+
+ if (idx < MAX_APCLI_NUM)
+ {
+ pDesireHtPhy = &pAd->ApCfg.ApCliTab[idx].DesiredHtPhyInfo;
+ pActiveHtPhy = &pAd->ApCfg.ApCliTab[idx].DesiredHtPhyInfo;
+ pHtPhy = &pAd->ApCfg.ApCliTab[idx].HTPhyMode;
+ pMaxHtPhy = &pAd->ApCfg.ApCliTab[idx].MaxHTPhyMode;
+ pMinHtPhy = &pAd->ApCfg.ApCliTab[idx].MinHTPhyMode;
+
+ auto_rate_cur_p = &pAd->ApCfg.ApCliTab[idx].bAutoTxRateSwitch;
+ break;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid idx(%d)\n", __FUNCTION__, idx));
+ return;
+ }
+ }
+#endif /* APCLI_SUPPORT */
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef WDS_SUPPORT
+ if (apidx >= MIN_NET_DEVICE_FOR_WDS)
+ {
+ UCHAR idx = apidx - MIN_NET_DEVICE_FOR_WDS;
+
+ if (idx < MAX_WDS_ENTRY)
+ {
+ pDesireHtPhy = &pAd->WdsTab.WdsEntry[idx].DesiredHtPhyInfo;
+ pActiveHtPhy = &pAd->WdsTab.WdsEntry[idx].DesiredHtPhyInfo;
+ pHtPhy = &pAd->WdsTab.WdsEntry[idx].HTPhyMode;
+ pMaxHtPhy = &pAd->WdsTab.WdsEntry[idx].MaxHTPhyMode;
+ pMinHtPhy = &pAd->WdsTab.WdsEntry[idx].MinHTPhyMode;
+
+ auto_rate_cur_p = &pAd->WdsTab.WdsEntry[idx].bAutoTxRateSwitch;
+ break;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx));
+ return;
+ }
+ }
+#endif /* WDS_SUPPORT */
+
+ if ((apidx < pAd->ApCfg.BssidNum) && (apidx < HW_BEACON_MAX_NUM))
+ {
+ pDesireHtPhy = &pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo;
+ pActiveHtPhy = &pAd->ApCfg.MBSSID[apidx].DesiredHtPhyInfo;
+ pHtPhy = &pAd->ApCfg.MBSSID[apidx].HTPhyMode;
+ pMaxHtPhy = &pAd->ApCfg.MBSSID[apidx].MaxHTPhyMode;
+ pMinHtPhy = &pAd->ApCfg.MBSSID[apidx].MinHTPhyMode;
+
+ auto_rate_cur_p = &pAd->ApCfg.MBSSID[apidx].bAutoTxRateSwitch;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx));
+ }
+ break;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ } while (FALSE);
+
+ {
+ if ((!pDesireHtPhy) || pDesireHtPhy->bHtEnable == FALSE)
+ return;
+
+ pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
+ StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
+ BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
+ if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pAd->Antenna.field.TxPath >= 2))
+ pMaxHtPhy->field.STBC = STBC_USE;
+ else
+ pMaxHtPhy->field.STBC = STBC_NONE;
+ }
+
+ /* Decide MAX ht rate.*/
+ if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
+ pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
+ else
+ pMaxHtPhy->field.MODE = MODE_HTMIX;
+
+ if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
+ pMaxHtPhy->field.BW = BW_40;
+ else
+ pMaxHtPhy->field.BW = BW_20;
+
+ if (pMaxHtPhy->field.BW == BW_20)
+ pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
+ else
+ pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
+
+ if (pDesireHtPhy->MCSSet[4] != 0)
+ {
+ pMaxHtPhy->field.MCS = 32;
+ }
+
+ pMaxHtPhy->field.MCS = get_ht_max_mcs(pAd, &pDesireHtPhy->MCSSet[0],
+ &pActiveHtPhy->MCSSet[0]);
+
+ /* Copy MIN ht rate. rt2860???*/
+ pMinHtPhy->field.BW = BW_20;
+ pMinHtPhy->field.MCS = 0;
+ pMinHtPhy->field.STBC = 0;
+ pMinHtPhy->field.ShortGI = 0;
+ /*If STA assigns fixed rate. update to fixed here.*/
+
+
+ /* Decide ht rate*/
+ pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
+ pHtPhy->field.BW = pMaxHtPhy->field.BW;
+ pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
+ pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
+ pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
+
+ /* use default now. rt2860*/
+ if (pDesireHtPhy->MCSSet[0] != 0xff)
+ *auto_rate_cur_p = FALSE;
+ else
+ *auto_rate_cur_p = TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE, (" %s():<---.AMsduSize = %d \n", __FUNCTION__, pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
+ DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
+ pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
+ DBGPRINT(RT_DEBUG_TRACE,("%s():<=== \n", __FUNCTION__));
+}
+
+
+VOID BATableInit(
+ IN PRTMP_ADAPTER pAd,
+ IN BA_TABLE *Tab)
+{
+ int i;
+
+ Tab->numAsOriginator = 0;
+ Tab->numAsRecipient = 0;
+ Tab->numDoneOriginator = 0;
+ NdisAllocateSpinLock(pAd, &pAd->BATabLock);
+ for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
+ {
+ Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
+ NdisAllocateSpinLock(pAd, &(Tab->BARecEntry[i].RxReRingLock));
+ }
+ for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
+ {
+ Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
+ }
+}
+
+VOID BATableExit(
+ IN RTMP_ADAPTER *pAd)
+{
+ int i;
+
+ for(i=0; i<MAX_LEN_OF_BA_REC_TABLE; i++)
+ {
+ NdisFreeSpinLock(&pAd->BATable.BARecEntry[i].RxReRingLock);
+ }
+ NdisFreeSpinLock(&pAd->BATabLock);
+}
+#endif /* DOT11_N_SUPPORT */
+
+/* IRQL = DISPATCH_LEVEL*/
+VOID MlmeRadioOff(
+ IN PRTMP_ADAPTER pAd)
+{
+ RTMP_MLME_RADIO_OFF(pAd);
+}
+
+/* IRQL = DISPATCH_LEVEL*/
+VOID MlmeRadioOn(
+ IN PRTMP_ADAPTER pAd)
+{
+ RTMP_MLME_RADIO_ON(pAd);
+}
+
+/*
+===========================================================================================
+ bss_table.c
+===========================================================================================
+*/
+
+
+/*! \brief initialize BSS table
+ * \param p_tab pointer to the table
+ * \return none
+ * \pre
+ * \post
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ */
+VOID BssTableInit(BSS_TABLE *Tab)
+{
+ int i;
+
+ Tab->BssNr = 0;
+ Tab->BssOverlapNr = 0;
+
+ for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
+ {
+ UCHAR *pOldAddr = Tab->BssEntry[i].pVarIeFromProbRsp;
+
+ NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
+
+ Tab->BssEntry[i].Rssi = -127; /* initial the rssi as a minimum value */
+ if (pOldAddr)
+ {
+ RTMPZeroMemory(pOldAddr, MAX_VIE_LEN);
+ Tab->BssEntry[i].pVarIeFromProbRsp = pOldAddr;
+ }
+ }
+}
+
+
+/*! \brief search the BSS table by SSID
+ * \param p_tab pointer to the bss table
+ * \param ssid SSID string
+ * \return index of the table, BSS_NOT_FOUND if not in the table
+ * \pre
+ * \post
+ * \note search by sequential search
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+ULONG BssTableSearch(
+ IN BSS_TABLE *Tab,
+ IN PUCHAR pBssid,
+ IN UCHAR Channel)
+{
+ UCHAR i;
+
+ for (i = 0; i < Tab->BssNr; i++)
+ {
+
+ /*
+ Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
+ We should distinguish this case.
+ */
+ if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
+ ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
+ MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
+ {
+ return i;
+ }
+ }
+ return (ULONG)BSS_NOT_FOUND;
+}
+
+ULONG BssSsidTableSearch(
+ IN BSS_TABLE *Tab,
+ IN PUCHAR pBssid,
+ IN PUCHAR pSsid,
+ IN UCHAR SsidLen,
+ IN UCHAR Channel)
+{
+ UCHAR i;
+
+ for (i = 0; i < Tab->BssNr; i++)
+ {
+
+ /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.*/
+ /* We should distinguish this case.*/
+ /* */
+ if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
+ ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
+ MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
+ SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
+ {
+ return i;
+ }
+ }
+ return (ULONG)BSS_NOT_FOUND;
+}
+
+ULONG BssTableSearchWithSSID(
+ IN BSS_TABLE *Tab,
+ IN PUCHAR Bssid,
+ IN PUCHAR pSsid,
+ IN UCHAR SsidLen,
+ IN UCHAR Channel)
+{
+ UCHAR i;
+
+ for (i = 0; i < Tab->BssNr; i++)
+ {
+ if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
+ ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
+ MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
+ (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
+ (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
+ (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
+ {
+ return i;
+ }
+ }
+ return (ULONG)BSS_NOT_FOUND;
+}
+
+
+ULONG BssSsidTableSearchBySSID(
+ IN BSS_TABLE *Tab,
+ IN PUCHAR pSsid,
+ IN UCHAR SsidLen)
+{
+ UCHAR i;
+
+ for (i = 0; i < Tab->BssNr; i++)
+ {
+ if (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
+ {
+ return i;
+ }
+ }
+ return (ULONG)BSS_NOT_FOUND;
+}
+
+
+/* IRQL = DISPATCH_LEVEL*/
+VOID BssTableDeleteEntry(
+ IN OUT BSS_TABLE *Tab,
+ IN PUCHAR pBssid,
+ IN UCHAR Channel)
+{
+ UCHAR i, j;
+
+ for (i = 0; i < Tab->BssNr; i++)
+ {
+ if ((Tab->BssEntry[i].Channel == Channel) &&
+ (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
+ {
+ UCHAR *pOldAddr = NULL;
+
+ for (j = i; j < Tab->BssNr - 1; j++)
+ {
+ pOldAddr = Tab->BssEntry[j].pVarIeFromProbRsp;
+ NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
+ if (pOldAddr)
+ {
+ RTMPZeroMemory(pOldAddr, MAX_VIE_LEN);
+ NdisMoveMemory(pOldAddr,
+ Tab->BssEntry[j + 1].pVarIeFromProbRsp,
+ Tab->BssEntry[j + 1].VarIeFromProbeRspLen);
+ Tab->BssEntry[j].pVarIeFromProbRsp = pOldAddr;
+ }
+ }
+
+ pOldAddr = Tab->BssEntry[Tab->BssNr - 1].pVarIeFromProbRsp;
+ NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
+ if (pOldAddr)
+ {
+ RTMPZeroMemory(pOldAddr, MAX_VIE_LEN);
+ Tab->BssEntry[Tab->BssNr - 1].pVarIeFromProbRsp = pOldAddr;
+ }
+
+ Tab->BssNr -= 1;
+ return;
+ }
+ }
+}
+
+
+/*! \brief
+ * \param
+ * \return
+ * \pre
+ * \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+VOID BssEntrySet(
+ IN PRTMP_ADAPTER pAd,
+ OUT BSS_ENTRY *pBss,
+ IN BCN_IE_LIST *ie_list,
+ IN CHAR Rssi,
+ IN USHORT LengthVIE,
+ IN PNDIS_802_11_VARIABLE_IEs pVIE)
+{
+ COPY_MAC_ADDR(pBss->Bssid, ie_list->Bssid);
+ /* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID*/
+ pBss->Hidden = 1;
+ if (ie_list->SsidLen > 0)
+ {
+ /* For hidden SSID AP, it might send beacon with SSID len equal to 0*/
+ /* Or send beacon /probe response with SSID len matching real SSID length,*/
+ /* but SSID is all zero. such as "00-00-00-00" with length 4.*/
+ /* We have to prevent this case overwrite correct table*/
+ if (NdisEqualMemory(ie_list->Ssid, ZeroSsid, ie_list->SsidLen) == 0)
+ {
+ NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
+ NdisMoveMemory(pBss->Ssid, ie_list->Ssid, ie_list->SsidLen);
+ pBss->SsidLen = ie_list->SsidLen;
+ pBss->Hidden = 0;
+ }
+ }
+ else
+ {
+ /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
+ if (NdisEqualMemory(pBss->Ssid, ZeroSsid, pBss->SsidLen))
+ {
+ NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
+ pBss->SsidLen = 0;
+ }
+ }
+
+ pBss->BssType = ie_list->BssType;
+ pBss->BeaconPeriod = ie_list->BeaconPeriod;
+ if (ie_list->BssType == BSS_INFRA)
+ {
+ if (ie_list->CfParm.bValid)
+ {
+ pBss->CfpCount = ie_list->CfParm.CfpCount;
+ pBss->CfpPeriod = ie_list->CfParm.CfpPeriod;
+ pBss->CfpMaxDuration = ie_list->CfParm.CfpMaxDuration;
+ pBss->CfpDurRemaining = ie_list->CfParm.CfpDurRemaining;
+ }
+ }
+ else
+ {
+ pBss->AtimWin = ie_list->AtimWin;
+ }
+
+ NdisGetSystemUpTime(&pBss->LastBeaconRxTime);
+ pBss->CapabilityInfo = ie_list->CapabilityInfo;
+ /* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES*/
+ /* Combine with AuthMode, they will decide the connection methods.*/
+ pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
+ ASSERT(ie_list->SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
+ if (ie_list->SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
+ NdisMoveMemory(pBss->SupRate, ie_list->SupRate, ie_list->SupRateLen);
+ else
+ NdisMoveMemory(pBss->SupRate, ie_list->SupRate, MAX_LEN_OF_SUPPORTED_RATES);
+ pBss->SupRateLen = ie_list->SupRateLen;
+ ASSERT(ie_list->ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
+ if (ie_list->ExtRateLen > MAX_LEN_OF_SUPPORTED_RATES)
+ ie_list->ExtRateLen = MAX_LEN_OF_SUPPORTED_RATES;
+ NdisMoveMemory(pBss->ExtRate, ie_list->ExtRate, ie_list->ExtRateLen);
+ pBss->NewExtChanOffset = ie_list->NewExtChannelOffset;
+ pBss->ExtRateLen = ie_list->ExtRateLen;
+ pBss->Channel = ie_list->Channel;
+ pBss->CentralChannel = ie_list->Channel;
+ pBss->Rssi = Rssi;
+ /* Update CkipFlag. if not exists, the value is 0x0*/
+ pBss->CkipFlag = ie_list->CkipFlag;
+
+ /* New for microsoft Fixed IEs*/
+ NdisMoveMemory(pBss->FixIEs.Timestamp, &ie_list->TimeStamp, 8);
+ pBss->FixIEs.BeaconInterval = ie_list->BeaconPeriod;
+ pBss->FixIEs.Capabilities = ie_list->CapabilityInfo;
+
+ /* New for microsoft Variable IEs*/
+ if (LengthVIE != 0)
+ {
+ pBss->VarIELen = LengthVIE;
+ NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
+ }
+ else
+ {
+ pBss->VarIELen = 0;
+ }
+
+ pBss->AddHtInfoLen = 0;
+ pBss->HtCapabilityLen = 0;
+#ifdef DOT11_N_SUPPORT
+ if (ie_list->HtCapabilityLen> 0)
+ {
+ pBss->HtCapabilityLen = ie_list->HtCapabilityLen;
+ NdisMoveMemory(&pBss->HtCapability, &ie_list->HtCapability, ie_list->HtCapabilityLen);
+ if (ie_list->AddHtInfoLen > 0)
+ {
+ pBss->AddHtInfoLen = ie_list->AddHtInfoLen;
+ NdisMoveMemory(&pBss->AddHtInfo, &ie_list->AddHtInfo, ie_list->AddHtInfoLen);
+
+ pBss->CentralChannel = get_cent_ch_by_htinfo(pAd, &ie_list->AddHtInfo,
+ &ie_list->HtCapability);
+ }
+
+#ifdef DOT11_VHT_AC
+ if (ie_list->vht_cap_len) {
+ NdisMoveMemory(&pBss->vht_cap_ie, &ie_list->vht_cap_ie, ie_list->vht_cap_len);
+ pBss->vht_cap_len = ie_list->vht_cap_len;
+ }
+
+ if (ie_list->vht_op_len) {
+ VHT_OP_IE *vht_op;
+
+ NdisMoveMemory(&pBss->vht_op_ie, &ie_list->vht_op_ie, ie_list->vht_op_len);
+ pBss->vht_op_len = ie_list->vht_op_len;
+ vht_op = &ie_list->vht_op_ie;
+ if ((vht_op->vht_op_info.ch_width > 0) &&
+ (ie_list->AddHtInfo.AddHtInfo.ExtChanOffset != EXTCHA_NONE) &&
+ (ie_list->HtCapability.HtCapInfo.ChannelWidth == BW_40) &&
+ (pBss->CentralChannel != ie_list->AddHtInfo.ControlChan))
+ {
+ UCHAR cent_ch;
+
+ cent_ch = vht_cent_ch_freq(pAd, ie_list->AddHtInfo.ControlChan);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():VHT cent_ch=%d, vht_op_info->center_freq_1=%d, Bss->CentralChannel=%d, change from CentralChannel to cent_ch!\n",
+ __FUNCTION__, cent_ch, vht_op->vht_op_info.center_freq_1, pBss->CentralChannel));
+ pBss->CentralChannel = vht_op->vht_op_info.center_freq_1;
+ }
+ }
+#endif /* DOT11_VHT_AC */
+ }
+#endif /* DOT11_N_SUPPORT */
+
+ BssCipherParse(pBss);
+
+ /* new for QOS*/
+ if (ie_list->EdcaParm.bValid)
+ NdisMoveMemory(&pBss->EdcaParm, &ie_list->EdcaParm, sizeof(EDCA_PARM));
+ else
+ pBss->EdcaParm.bValid = FALSE;
+ if (ie_list->QosCapability.bValid)
+ NdisMoveMemory(&pBss->QosCapability, &ie_list->QosCapability, sizeof(QOS_CAPABILITY_PARM));
+ else
+ pBss->QosCapability.bValid = FALSE;
+ if (ie_list->QbssLoad.bValid)
+ NdisMoveMemory(&pBss->QbssLoad, &ie_list->QbssLoad, sizeof(QBSS_LOAD_PARM));
+ else
+ pBss->QbssLoad.bValid = FALSE;
+
+ {
+ PEID_STRUCT pEid;
+ USHORT Length = 0;
+
+#ifdef WSC_INCLUDED
+ pBss->WpsAP = 0x00;
+ pBss->WscDPIDFromWpsAP = 0xFFFF;
+#endif /* WSC_INCLUDED */
+
+ pEid = (PEID_STRUCT) pVIE;
+ while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
+ {
+#define WPS_AP 0x01
+ switch(pEid->Eid)
+ {
+ case IE_WPA:
+ if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4)
+ )
+ {
+#ifdef WSC_INCLUDED
+ pBss->WpsAP |= WPS_AP;
+ WscCheckWpsIeFromWpsAP(pAd,
+ pEid,
+ &pBss->WscDPIDFromWpsAP);
+#endif /* WSC_INCLUDED */
+ break;
+ }
+ break;
+
+ }
+ Length = Length + 2 + (USHORT)pEid->Len; /* Eid[1] + Len[1]+ content[Len]*/
+ pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+ }
+ }
+}
+
+
+
+/*!
+ * \brief insert an entry into the bss table
+ * \param p_tab The BSS table
+ * \param Bssid BSSID
+ * \param ssid SSID
+ * \param ssid_len Length of SSID
+ * \param bss_type
+ * \param beacon_period
+ * \param timestamp
+ * \param p_cf
+ * \param atim_win
+ * \param cap
+ * \param rates
+ * \param rates_len
+ * \param channel_idx
+ * \return none
+ * \pre
+ * \post
+ * \note If SSID is identical, the old entry will be replaced by the new one
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+ULONG BssTableSetEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT BSS_TABLE *Tab,
+ IN BCN_IE_LIST *ie_list,
+ IN CHAR Rssi,
+ IN USHORT LengthVIE,
+ IN PNDIS_802_11_VARIABLE_IEs pVIE)
+{
+ ULONG Idx;
+
+
+ Idx = BssTableSearch(Tab, ie_list->Bssid, ie_list->Channel);
+ if (Idx == BSS_NOT_FOUND)
+ {
+ if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
+ {
+ /*
+ It may happen when BSS Table was full.
+ The desired AP will not be added into BSS Table
+ In this case, if we found the desired AP then overwrite BSS Table.
+ */
+ if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) ||
+ !OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED))
+ {
+ if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, ie_list->Bssid) ||
+ SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, ie_list->Ssid, ie_list->SsidLen)
+#ifdef APCLI_SUPPORT
+ || MAC_ADDR_EQUAL(pAd->ApCliMlmeAux.Bssid, ie_list->Bssid)
+ || SSID_EQUAL(pAd->ApCliMlmeAux.Ssid, pAd->ApCliMlmeAux.SsidLen, ie_list->Ssid, ie_list->SsidLen)
+#endif /* APCLI_SUPPORT */
+ )
+ {
+ Idx = Tab->BssOverlapNr;
+ BssEntrySet(pAd, &Tab->BssEntry[Idx], ie_list, Rssi, LengthVIE, pVIE);
+ Tab->BssOverlapNr += 1;
+ Tab->BssOverlapNr = Tab->BssOverlapNr % MAX_LEN_OF_BSS_TABLE;
+ }
+ return Idx;
+ }
+ else
+ {
+ return BSS_NOT_FOUND;
+ }
+ }
+ Idx = Tab->BssNr;
+ BssEntrySet(pAd, &Tab->BssEntry[Idx], ie_list, Rssi, LengthVIE, pVIE);
+ Tab->BssNr++;
+ }
+ else
+ {
+ BssEntrySet(pAd, &Tab->BssEntry[Idx], ie_list, Rssi, LengthVIE, pVIE);
+ }
+
+ return Idx;
+}
+
+
+
+
+VOID BssCipherParse(
+ IN OUT PBSS_ENTRY pBss)
+{
+ PEID_STRUCT pEid;
+ PUCHAR pTmp;
+ PRSN_IE_HEADER_STRUCT pRsnHeader;
+ PCIPHER_SUITE_STRUCT pCipher;
+ PAKM_SUITE_STRUCT pAKM;
+ USHORT Count;
+ INT Length;
+ NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
+
+
+ /* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.*/
+
+ if (pBss->Privacy)
+ {
+ pBss->WepStatus = Ndis802_11WEPEnabled;
+ }
+ else
+ {
+ pBss->WepStatus = Ndis802_11WEPDisabled;
+ }
+ /* Set default to disable & open authentication before parsing variable IE*/
+ pBss->AuthMode = Ndis802_11AuthModeOpen;
+ pBss->AuthModeAux = Ndis802_11AuthModeOpen;
+
+ /* Init WPA setting*/
+ pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
+ pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
+ pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
+ pBss->WPA.RsnCapability = 0;
+ pBss->WPA.bMixMode = FALSE;
+
+ /* Init WPA2 setting*/
+ pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
+ pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
+ pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
+ pBss->WPA2.RsnCapability = 0;
+ pBss->WPA2.bMixMode = FALSE;
+
+#ifdef WAPI_SUPPORT
+ /* Init WAPI setting*/
+ pBss->WAPI.PairCipher = Ndis802_11WEPDisabled;
+ pBss->WAPI.PairCipherAux = Ndis802_11WEPDisabled;
+ pBss->WAPI.GroupCipher = Ndis802_11WEPDisabled;
+ pBss->WAPI.RsnCapability = 0;
+ pBss->WAPI.bMixMode = FALSE;
+#endif /* WAPI_SUPPORT */
+
+ Length = (INT) pBss->VarIELen;
+
+ while (Length > 0)
+ {
+ /* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently*/
+ pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
+ pEid = (PEID_STRUCT) pTmp;
+ switch (pEid->Eid)
+ {
+ case IE_WPA:
+ if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
+ {
+ pBss->bSES = TRUE;
+ break;
+ }
+ else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
+ {
+ /* if unsupported vendor specific IE*/
+ break;
+ }
+ /*
+ Skip OUI, version, and multicast suite
+ This part should be improved in the future when AP supported multiple cipher suite.
+ For now, it's OK since almost all APs have fixed cipher suite supported.
+ */
+ /* pTmp = (PUCHAR) pEid->Octet;*/
+ pTmp += 11;
+
+ /*
+ Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
+ Value Meaning
+ 0 None
+ 1 WEP-40
+ 2 Tkip
+ 3 WRAP
+ 4 AES
+ 5 WEP-104
+ */
+ /* Parse group cipher*/
+ switch (*pTmp)
+ {
+ case 1:
+ pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
+ break;
+ case 5:
+ pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
+ break;
+ case 2:
+ pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
+ break;
+ case 4:
+ pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
+ break;
+ default:
+ break;
+ }
+ /* number of unicast suite*/
+ pTmp += 1;
+
+ /* skip all unicast cipher suites*/
+ /*Count = *(PUSHORT) pTmp; */
+ Count = (pTmp[1]<<8) + pTmp[0];
+ pTmp += sizeof(USHORT);
+
+ /* Parsing all unicast cipher suite*/
+ while (Count > 0)
+ {
+ /* Skip OUI*/
+ pTmp += 3;
+ TmpCipher = Ndis802_11WEPDisabled;
+ switch (*pTmp)
+ {
+ case 1:
+ case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway*/
+ TmpCipher = Ndis802_11Encryption1Enabled;
+ break;
+ case 2:
+ TmpCipher = Ndis802_11Encryption2Enabled;
+ break;
+ case 4:
+ TmpCipher = Ndis802_11Encryption3Enabled;
+ break;
+ default:
+ break;
+ }
+ if (TmpCipher > pBss->WPA.PairCipher)
+ {
+ /* Move the lower cipher suite to PairCipherAux*/
+ pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
+ pBss->WPA.PairCipher = TmpCipher;
+ }
+ else
+ {
+ pBss->WPA.PairCipherAux = TmpCipher;
+ }
+ pTmp++;
+ Count--;
+ }
+
+ /* 4. get AKM suite counts*/
+ /*Count = *(PUSHORT) pTmp;*/
+ Count = (pTmp[1]<<8) + pTmp[0];
+ pTmp += sizeof(USHORT);
+ pTmp += 3;
+
+ switch (*pTmp)
+ {
+ case 1:
+ /* Set AP support WPA-enterprise mode*/
+ if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+ pBss->AuthMode = Ndis802_11AuthModeWPA;
+ else
+ pBss->AuthModeAux = Ndis802_11AuthModeWPA;
+ break;
+ case 2:
+ /* Set AP support WPA-PSK mode*/
+ if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+ pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
+ else
+ pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
+ break;
+ default:
+ break;
+ }
+ pTmp += 1;
+
+ /* Fixed for WPA-None*/
+ if (pBss->BssType == BSS_ADHOC)
+ {
+ pBss->AuthMode = Ndis802_11AuthModeWPANone;
+ pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
+ pBss->WepStatus = pBss->WPA.GroupCipher;
+ /* Patched bugs for old driver*/
+ if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
+ pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
+ }
+ else
+ pBss->WepStatus = pBss->WPA.PairCipher;
+
+ /* Check the Pair & Group, if different, turn on mixed mode flag*/
+ if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
+ pBss->WPA.bMixMode = TRUE;
+
+ break;
+
+ case IE_RSN:
+ pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
+
+ /* 0. Version must be 1*/
+ if (le2cpu16(pRsnHeader->Version) != 1)
+ break;
+ pTmp += sizeof(RSN_IE_HEADER_STRUCT);
+
+ /* 1. Check group cipher*/
+ pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
+ if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
+ break;
+
+ /* Parse group cipher*/
+ switch (pCipher->Type)
+ {
+ case 1:
+ pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
+ break;
+ case 5:
+ pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
+ break;
+ case 2:
+ pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
+ break;
+ case 4:
+ pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
+ break;
+ default:
+ break;
+ }
+ /* set to correct offset for next parsing*/
+ pTmp += sizeof(CIPHER_SUITE_STRUCT);
+
+ /* 2. Get pairwise cipher counts*/
+ /*Count = *(PUSHORT) pTmp;*/
+ Count = (pTmp[1]<<8) + pTmp[0];
+ pTmp += sizeof(USHORT);
+
+ /* 3. Get pairwise cipher*/
+ /* Parsing all unicast cipher suite*/
+ while (Count > 0)
+ {
+ /* Skip OUI*/
+ pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
+ TmpCipher = Ndis802_11WEPDisabled;
+ switch (pCipher->Type)
+ {
+ case 1:
+ case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway*/
+ TmpCipher = Ndis802_11Encryption1Enabled;
+ break;
+ case 2:
+ TmpCipher = Ndis802_11Encryption2Enabled;
+ break;
+ case 4:
+ TmpCipher = Ndis802_11Encryption3Enabled;
+ break;
+ default:
+ break;
+ }
+ if (TmpCipher > pBss->WPA2.PairCipher)
+ {
+ /* Move the lower cipher suite to PairCipherAux*/
+ pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
+ pBss->WPA2.PairCipher = TmpCipher;
+ }
+ else
+ {
+ pBss->WPA2.PairCipherAux = TmpCipher;
+ }
+ pTmp += sizeof(CIPHER_SUITE_STRUCT);
+ Count--;
+ }
+
+ /* 4. get AKM suite counts*/
+ /*Count = *(PUSHORT) pTmp;*/
+ Count = (pTmp[1]<<8) + pTmp[0];
+ pTmp += sizeof(USHORT);
+
+ /* 5. Get AKM ciphers*/
+ /* Parsing all AKM ciphers*/
+ while (Count > 0)
+ {
+ pAKM = (PAKM_SUITE_STRUCT) pTmp;
+ if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
+ break;
+
+ switch (pAKM->Type)
+ {
+ case 0:
+ if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+ pBss->AuthMode = Ndis802_11AuthModeWPANone;
+ else
+ pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
+ break;
+ case 1:
+ /* Set AP support WPA-enterprise mode*/
+ if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+ pBss->AuthMode = Ndis802_11AuthModeWPA2;
+ else
+ pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
+ break;
+ case 2:
+ /* Set AP support WPA-PSK mode*/
+ if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+ pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
+ else
+ pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
+
+
+ break;
+ default:
+ if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+ pBss->AuthMode = Ndis802_11AuthModeMax;
+ else
+ pBss->AuthModeAux = Ndis802_11AuthModeMax;
+ break;
+ }
+ pTmp += sizeof(AKM_SUITE_STRUCT);
+ Count--;
+ }
+
+ /* Fixed for WPA-None*/
+ if (pBss->BssType == BSS_ADHOC)
+ {
+ pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
+ pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
+ pBss->WepStatus = pBss->WPA.GroupCipher;
+ /* Patched bugs for old driver*/
+ if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
+ pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
+ }
+ pBss->WepStatus = pBss->WPA2.PairCipher;
+
+ /* 6. Get RSN capability*/
+ /*pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;*/
+ pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
+ pTmp += sizeof(USHORT);
+
+ /* Check the Pair & Group, if different, turn on mixed mode flag*/
+ if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
+ pBss->WPA2.bMixMode = TRUE;
+
+ break;
+#ifdef WAPI_SUPPORT
+ case IE_WAPI:
+ pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
+
+ /* 0. The version number must be 1*/
+ if (le2cpu16(pRsnHeader->Version) != 1)
+ break;
+ pTmp += sizeof(RSN_IE_HEADER_STRUCT);
+
+ /* 1. Get AKM suite counts*/
+ NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
+ Count = cpu2le16(Count);
+ pTmp += sizeof(USHORT);
+
+ /* 2. Get AKM ciphers*/
+ pAKM = (PAKM_SUITE_STRUCT) pTmp;
+ if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3))
+ break;
+
+ switch (pAKM->Type)
+ {
+ case 1:
+ /* Support WAI certificate authentication*/
+ pBss->AuthMode = Ndis802_11AuthModeWAICERT;
+ break;
+ case 2:
+ /* Support WAI PSK*/
+ pBss->AuthMode = Ndis802_11AuthModeWAIPSK;
+ break;
+ default:
+ break;
+ }
+ pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
+
+ /* 3. Get pairwise cipher counts*/
+ NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
+ Count = cpu2le16(Count);
+ pTmp += sizeof(USHORT);
+
+ /* 4. Get pairwise cipher*/
+ /* Parsing all unicast cipher suite*/
+ while (Count > 0)
+ {
+ if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3))
+ break;
+
+ /* Skip OUI*/
+ pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
+ TmpCipher = Ndis802_11WEPDisabled;
+ switch (pCipher->Type)
+ {
+ case 1:
+ TmpCipher = Ndis802_11EncryptionSMS4Enabled;
+ break;
+ default:
+ break;
+ }
+
+ if (TmpCipher > pBss->WAPI.PairCipher)
+ {
+ /* Move the lower cipher suite to PairCipherAux*/
+ pBss->WAPI.PairCipherAux = pBss->WAPI.PairCipher;
+ pBss->WAPI.PairCipher = TmpCipher;
+ }
+ else
+ {
+ pBss->WAPI.PairCipherAux = TmpCipher;
+ }
+ pTmp += sizeof(CIPHER_SUITE_STRUCT);
+ Count--;
+ }
+
+ /* 5. Check group cipher*/
+ if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3))
+ break;
+
+ pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
+ /* Parse group cipher*/
+ switch (pCipher->Type)
+ {
+ case 1:
+ pBss->WAPI.GroupCipher = Ndis802_11EncryptionSMS4Enabled;
+ break;
+ default:
+ break;
+ }
+ /* set to correct offset for next parsing*/
+ pTmp += sizeof(CIPHER_SUITE_STRUCT);
+
+ /* update the encryption type*/
+ pBss->WepStatus = pBss->WAPI.PairCipher;
+
+ /* update the WAPI capability*/
+ pBss->WAPI.RsnCapability = (pTmp[1]<<8) + pTmp[0];
+ pTmp += sizeof(USHORT);
+
+ break;
+#endif /* WAPI_SUPPORT */
+ default:
+ break;
+ }
+ Length -= (pEid->Len + 2);
+ }
+}
+
+/* ===========================================================================================*/
+/* mac_table.c*/
+/* ===========================================================================================*/
+
+/*! \brief generates a random mac address value for IBSS BSSID
+ * \param Addr the bssid location
+ * \return none
+ * \pre
+ * \post
+ */
+VOID MacAddrRandomBssid(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pAddr)
+{
+ INT i;
+
+ for (i = 0; i < MAC_ADDR_LEN; i++)
+ {
+ pAddr[i] = RandomByte(pAd);
+ }
+
+ pAddr[0] = (pAddr[0] & 0xfe) | 0x02; /* the first 2 bits must be 01xxxxxxxx*/
+}
+
+/*! \brief init the management mac frame header
+ * \param p_hdr mac header
+ * \param subtype subtype of the frame
+ * \param p_ds destination address, don't care if it is a broadcast address
+ * \return none
+ * \pre the station has the following information in the pAd->StaCfg
+ * - bssid
+ * - station address
+ * \post
+ * \note this function initializes the following field
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ */
+VOID MgtMacHeaderInit(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PHEADER_802_11 pHdr80211,
+ IN UCHAR SubType,
+ IN UCHAR ToDs,
+ IN PUCHAR pDA,
+ IN PUCHAR pBssid)
+{
+ NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
+
+ pHdr80211->FC.Type = BTYPE_MGMT;
+ pHdr80211->FC.SubType = SubType;
+/* if (SubType == SUBTYPE_ACK) sample, no use, it will conflict with ACTION frame sub type*/
+/* pHdr80211->FC.Type = BTYPE_CNTL;*/
+ pHdr80211->FC.ToDs = ToDs;
+ COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ COPY_MAC_ADDR(pHdr80211->Addr2, pBssid);
+#endif /* CONFIG_AP_SUPPORT */
+ COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
+}
+
+/* ===========================================================================================*/
+/* mem_mgmt.c*/
+/* ===========================================================================================*/
+
+/*!***************************************************************************
+ * This routine build an outgoing frame, and fill all information specified
+ * in argument list to the frame body. The actual frame size is the summation
+ * of all arguments.
+ * input params:
+ * Buffer - pointer to a pre-allocated memory segment
+ * args - a list of <int arg_size, arg> pairs.
+ * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
+ * function will FAIL!!!
+ * return:
+ * Size of the buffer
+ * usage:
+ * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ****************************************************************************/
+ULONG MakeOutgoingFrame(
+ OUT UCHAR *Buffer,
+ OUT ULONG *FrameLen, ...)
+{
+ UCHAR *p;
+ int leng;
+ ULONG TotLeng;
+ va_list Args;
+
+ /* calculates the total length*/
+ TotLeng = 0;
+ va_start(Args, FrameLen);
+ do
+ {
+ leng = va_arg(Args, int);
+ if (leng == END_OF_ARGS)
+ {
+ break;
+ }
+ p = va_arg(Args, PVOID);
+ NdisMoveMemory(&Buffer[TotLeng], p, leng);
+ TotLeng = TotLeng + leng;
+ } while(TRUE);
+
+ va_end(Args); /* clean up */
+ *FrameLen = TotLeng;
+ return TotLeng;
+}
+
+/* ===========================================================================================*/
+/* mlme_queue.c*/
+/* ===========================================================================================*/
+
+/*! \brief Initialize The MLME Queue, used by MLME Functions
+ * \param *Queue The MLME Queue
+ * \return Always Return NDIS_STATE_SUCCESS in this implementation
+ * \pre
+ * \post
+ * \note Because this is done only once (at the init stage), no need to be locked
+
+ IRQL = PASSIVE_LEVEL
+
+ */
+NDIS_STATUS MlmeQueueInit(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE *Queue)
+{
+ INT i;
+
+ NdisAllocateSpinLock(pAd, &Queue->Lock);
+
+ Queue->Num = 0;
+ Queue->Head = 0;
+ Queue->Tail = 0;
+
+ for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
+ {
+ Queue->Entry[i].Occupied = FALSE;
+ Queue->Entry[i].MsgLen = 0;
+ NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
+ * \param *Queue The MLME Queue
+ * \param Machine The State Machine Id
+ * \param MsgType The Message Type
+ * \param MsgLen The Message length
+ * \param *Msg The message pointer
+ * \return TRUE if enqueue is successful, FALSE if the queue is full
+ * \pre
+ * \post
+ * \note The message has to be initialized
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeEnqueue(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Machine,
+ IN ULONG MsgType,
+ IN ULONG MsgLen,
+ IN VOID *Msg,
+ IN ULONG Priv)
+{
+ INT Tail;
+ MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
+
+ /* Do nothing if the driver is starting halt state.*/
+ /* This might happen when timer already been fired before cancel timer with mlmehalt*/
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return FALSE;
+
+ /* First check the size, it MUST not exceed the mlme queue size*/
+ if (MsgLen > MGMT_DMA_BUFFER_SIZE)
+ {
+ DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
+ return FALSE;
+ }
+
+ if (MlmeQueueFull(Queue, 1))
+ {
+ return FALSE;
+ }
+
+ NdisAcquireSpinLock(&(Queue->Lock));
+ Tail = Queue->Tail;
+ Queue->Tail++;
+ Queue->Num++;
+ if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
+ {
+ Queue->Tail = 0;
+ }
+
+ Queue->Entry[Tail].Wcid = RESERVED_WCID;
+ Queue->Entry[Tail].Occupied = TRUE;
+ Queue->Entry[Tail].Machine = Machine;
+ Queue->Entry[Tail].MsgType = MsgType;
+ Queue->Entry[Tail].MsgLen = MsgLen;
+ Queue->Entry[Tail].Priv = Priv;
+
+ if (Msg != NULL)
+ {
+ NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
+ }
+
+ NdisReleaseSpinLock(&(Queue->Lock));
+ return TRUE;
+}
+
+/*! \brief This function is used when Recv gets a MLME message
+ * \param *Queue The MLME Queue
+ * \param TimeStampHigh The upper 32 bit of timestamp
+ * \param TimeStampLow The lower 32 bit of timestamp
+ * \param Rssi The receiving RSSI strength
+ * \param MsgLen The length of the message
+ * \param *Msg The message pointer
+ * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
+ * \pre
+ * \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeEnqueueForRecv(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Wcid,
+ IN ULONG TimeStampHigh,
+ IN ULONG TimeStampLow,
+ IN UCHAR Rssi0,
+ IN UCHAR Rssi1,
+ IN UCHAR Rssi2,
+ IN UCHAR AntSel,
+ IN ULONG MsgLen,
+ IN VOID *Msg,
+ IN UCHAR Signal,
+ IN UCHAR OpMode)
+{
+ INT Tail, Machine = 0xff;
+ PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+ INT MsgType = 0x0;
+ MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
+
+#ifdef RALINK_ATE
+ /* Nothing to do in ATE mode */
+ if(ATE_ON(pAd))
+ return FALSE;
+#endif /* RALINK_ATE */
+
+ /* Do nothing if the driver is starting halt state.*/
+ /* This might happen when timer already been fired before cancel timer with mlmehalt*/
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ {
+ DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
+ return FALSE;
+ }
+
+ /* First check the size, it MUST not exceed the mlme queue size*/
+ if (MsgLen > MGMT_DMA_BUFFER_SIZE)
+ {
+ DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
+ return FALSE;
+ }
+
+ if (MlmeQueueFull(Queue, 0))
+ {
+ return FALSE;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ /* Beacon must be handled by ap-sync state machine.*/
+ /* Probe-rsp must be handled by apcli-sync state machine.*/
+ /* Those packets don't need to check its MAC address.*/
+ do
+ {
+ /*
+ 1. When P2P GO On and receive Probe Response, preCheckMsgTypeSubset function will
+ enquene Probe response to APCli sync state machine
+ Solution: when GO On skip preCheckMsgTypeSubset redirect to APMsgTypeSubst
+ 2. When P2P Cli On and receive Probe Response, preCheckMsgTypeSubset function will
+ enquene Probe response to APCli sync state machine
+ Solution: handle MsgType == APCLI_MT2_PEER_PROBE_RSP on ApCli Sync state machine
+ when ApCli on idle state.
+ */
+
+ if (!MAC_ADDR_EQUAL(pFrame->Hdr.Addr1, pAd->CurrentAddress) &&
+ preCheckMsgTypeSubset(pAd, pFrame, &Machine, &MsgType))
+ break;
+
+ if (!MAC_ADDR_EQUAL(pFrame->Hdr.Addr1, pAd->CurrentAddress) &&
+ !MAC_ADDR_EQUAL(pAd->ApCliMlmeAux.Bssid, ZERO_MAC_ADDR)
+ && MAC_ADDR_EQUAL(pAd->ApCliMlmeAux.Bssid, pFrame->Hdr.Addr2))
+ {
+ if (ApCliMsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
+ break;
+ }
+ else
+ {
+ if (APMsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
+ break;
+ }
+
+ DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d, STA-%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pFrame->Hdr.FC.SubType, PRINT_MAC(pFrame->Hdr.Addr2)));
+ return FALSE;
+
+ } while (FALSE);
+#else
+ if (!APMsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
+ {
+ DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
+ return FALSE;
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* OK, we got all the informations, it is time to put things into queue*/
+
+ NdisAcquireSpinLock(&(Queue->Lock));
+ Tail = Queue->Tail;
+ Queue->Tail++;
+ Queue->Num++;
+ if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
+ {
+ Queue->Tail = 0;
+ }
+ Queue->Entry[Tail].Occupied = TRUE;
+ Queue->Entry[Tail].Machine = Machine;
+ Queue->Entry[Tail].MsgType = MsgType;
+ Queue->Entry[Tail].MsgLen = MsgLen;
+ Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
+ Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
+ Queue->Entry[Tail].Rssi0 = Rssi0;
+ Queue->Entry[Tail].Rssi1 = Rssi1;
+ Queue->Entry[Tail].Rssi2 = Rssi2;
+ Queue->Entry[Tail].AntSel = AntSel;
+ Queue->Entry[Tail].Signal = Signal;
+ Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
+ Queue->Entry[Tail].OpMode = (ULONG)OpMode;
+ Queue->Entry[Tail].Priv = 0;
+
+ Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
+
+ if (Msg != NULL)
+ {
+ NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
+ }
+
+ NdisReleaseSpinLock(&(Queue->Lock));
+ RTMP_MLME_HANDLER(pAd);
+
+ return TRUE;
+}
+
+#ifdef WSC_INCLUDED
+/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
+ * \param *Queue The MLME Queue
+ * \param TimeStampLow The lower 32 bit of timestamp, here we used for eventID.
+ * \param Machine The State Machine Id
+ * \param MsgType The Message Type
+ * \param MsgLen The Message length
+ * \param *Msg The message pointer
+ * \return TRUE if enqueue is successful, FALSE if the queue is full
+ * \pre
+ * \post
+ * \note The message has to be initialized
+ */
+BOOLEAN MlmeEnqueueForWsc(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG eventID,
+ IN LONG senderID,
+ IN ULONG Machine,
+ IN ULONG MsgType,
+ IN ULONG MsgLen,
+ IN VOID *Msg)
+{
+ INT Tail;
+ /*ULONG IrqFlags;*/
+ MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> MlmeEnqueueForWsc\n"));
+ /* Do nothing if the driver is starting halt state.*/
+ /* This might happen when timer already been fired before cancel timer with mlmehalt*/
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
+ return FALSE;
+
+ /* First check the size, it MUST not exceed the mlme queue size*/
+ if (MsgLen > MGMT_DMA_BUFFER_SIZE)
+ {
+ DBGPRINT_ERR(("MlmeEnqueueForWsc: msg too large, size = %ld \n", MsgLen));
+ return FALSE;
+ }
+
+ if (MlmeQueueFull(Queue, 1))
+ {
+
+ return FALSE;
+ }
+
+ /* OK, we got all the informations, it is time to put things into queue*/
+ NdisAcquireSpinLock(&(Queue->Lock));
+ Tail = Queue->Tail;
+ Queue->Tail++;
+ Queue->Num++;
+ if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
+ {
+ Queue->Tail = 0;
+ }
+
+ Queue->Entry[Tail].Occupied = TRUE;
+ Queue->Entry[Tail].Machine = Machine;
+ Queue->Entry[Tail].MsgType = MsgType;
+ Queue->Entry[Tail].MsgLen = MsgLen;
+ Queue->Entry[Tail].TimeStamp.u.LowPart = eventID;
+ Queue->Entry[Tail].TimeStamp.u.HighPart = senderID;
+ if (Msg != NULL)
+ NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
+
+ NdisReleaseSpinLock(&(Queue->Lock));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- MlmeEnqueueForWsc\n"));
+
+ return TRUE;
+}
+#endif /* WSC_INCLUDED */
+
+/*! \brief Dequeue a message from the MLME Queue
+ * \param *Queue The MLME Queue
+ * \param *Elem The message dequeued from MLME Queue
+ * \return TRUE if the Elem contains something, FALSE otherwise
+ * \pre
+ * \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeDequeue(
+ IN MLME_QUEUE *Queue,
+ OUT MLME_QUEUE_ELEM **Elem)
+{
+ NdisAcquireSpinLock(&(Queue->Lock));
+ *Elem = &(Queue->Entry[Queue->Head]);
+ Queue->Num--;
+ Queue->Head++;
+ if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
+ {
+ Queue->Head = 0;
+ }
+ NdisReleaseSpinLock(&(Queue->Lock));
+ return TRUE;
+}
+
+/* IRQL = DISPATCH_LEVEL*/
+VOID MlmeRestartStateMachine(
+ IN PRTMP_ADAPTER pAd)
+{
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
+
+
+
+ /* Change back to original channel in case of doing scan*/
+ {
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+ }
+
+ /* Resume MSDU which is turned off durning scan*/
+ RTMPResumeMsduTransmission(pAd);
+
+
+}
+
+/*! \brief test if the MLME Queue is empty
+ * \param *Queue The MLME Queue
+ * \return TRUE if the Queue is empty, FALSE otherwise
+ * \pre
+ * \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeQueueEmpty(
+ IN MLME_QUEUE *Queue)
+{
+ BOOLEAN Ans;
+
+ NdisAcquireSpinLock(&(Queue->Lock));
+ Ans = (Queue->Num == 0);
+ NdisReleaseSpinLock(&(Queue->Lock));
+
+ return Ans;
+}
+
+/*! \brief test if the MLME Queue is full
+ * \param *Queue The MLME Queue
+ * \return TRUE if the Queue is empty, FALSE otherwise
+ * \pre
+ * \post
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeQueueFull(
+ IN MLME_QUEUE *Queue,
+ IN UCHAR SendId)
+{
+ BOOLEAN Ans;
+
+ NdisAcquireSpinLock(&(Queue->Lock));
+ if (SendId == 0)
+ Ans = ((Queue->Num >= (MAX_LEN_OF_MLME_QUEUE / 2)) || Queue->Entry[Queue->Tail].Occupied);
+ else
+ Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE);
+ NdisReleaseSpinLock(&(Queue->Lock));
+
+ return Ans;
+}
+
+/*! \brief The destructor of MLME Queue
+ * \param
+ * \return
+ * \pre
+ * \post
+ * \note Clear Mlme Queue, Set Queue->Num to Zero.
+
+ IRQL = PASSIVE_LEVEL
+
+ */
+VOID MlmeQueueDestroy(
+ IN MLME_QUEUE *pQueue)
+{
+ NdisAcquireSpinLock(&(pQueue->Lock));
+ pQueue->Num = 0;
+ pQueue->Head = 0;
+ pQueue->Tail = 0;
+ NdisReleaseSpinLock(&(pQueue->Lock));
+ NdisFreeSpinLock(&(pQueue->Lock));
+}
+
+
+/*! \brief To substitute the message type if the message is coming from external
+ * \param pFrame The frame received
+ * \param *Machine The state machine
+ * \param *MsgType the message type for the state machine
+ * \return TRUE if the substitution is successful, FALSE otherwise
+ * \pre
+ * \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+
+/* ===========================================================================================*/
+/* state_machine.c*/
+/* ===========================================================================================*/
+
+/*! \brief Initialize the state machine.
+ * \param *S pointer to the state machine
+ * \param Trans State machine transition function
+ * \param StNr number of states
+ * \param MsgNr number of messages
+ * \param DefFunc default function, when there is invalid state/message combination
+ * \param InitState initial state of the state machine
+ * \param Base StateMachine base, internal use only
+ * \pre p_sm should be a legal pointer
+ * \post
+
+ IRQL = PASSIVE_LEVEL
+
+ */
+VOID StateMachineInit(
+ IN STATE_MACHINE *S,
+ IN STATE_MACHINE_FUNC Trans[],
+ IN ULONG StNr,
+ IN ULONG MsgNr,
+ IN STATE_MACHINE_FUNC DefFunc,
+ IN ULONG InitState,
+ IN ULONG Base)
+{
+ ULONG i, j;
+
+ /* set number of states and messages*/
+ S->NrState = StNr;
+ S->NrMsg = MsgNr;
+ S->Base = Base;
+
+ S->TransFunc = Trans;
+
+ /* init all state transition to default function*/
+ for (i = 0; i < StNr; i++)
+ {
+ for (j = 0; j < MsgNr; j++)
+ {
+ S->TransFunc[i * MsgNr + j] = DefFunc;
+ }
+ }
+
+ /* set the starting state*/
+ S->CurrState = InitState;
+}
+
+/*! \brief This function fills in the function pointer into the cell in the state machine
+ * \param *S pointer to the state machine
+ * \param St state
+ * \param Msg incoming message
+ * \param f the function to be executed when (state, message) combination occurs at the state machine
+ * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state
+ * \post
+
+ IRQL = PASSIVE_LEVEL
+
+ */
+VOID StateMachineSetAction(
+ IN STATE_MACHINE *S,
+ IN ULONG St,
+ IN ULONG Msg,
+ IN STATE_MACHINE_FUNC Func)
+{
+ ULONG MsgIdx;
+
+ MsgIdx = Msg - S->Base;
+
+ if (St < S->NrState && MsgIdx < S->NrMsg)
+ {
+ /* boundary checking before setting the action*/
+ S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
+ }
+}
+
+/*! \brief This function does the state transition
+ * \param *Adapter the NIC adapter pointer
+ * \param *S the state machine
+ * \param *Elem the message to be executed
+ * \return None
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+VOID StateMachinePerformAction(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ IN MLME_QUEUE_ELEM *Elem,
+ IN ULONG CurrState)
+{
+
+ if (S->TransFunc[(CurrState) * S->NrMsg + Elem->MsgType - S->Base])
+ (*(S->TransFunc[(CurrState) * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
+}
+
+/*
+ ==========================================================================
+ Description:
+ The drop function, when machine executes this, the message is simply
+ ignored. This function does nothing, the message is freed in
+ StateMachinePerformAction()
+ ==========================================================================
+ */
+VOID Drop(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+/*
+ ==========================================================================
+ Description:
+ ==========================================================================
+ */
+UCHAR RandomByte(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG i;
+ UCHAR R, Result;
+
+ R = 0;
+
+ if (pAd->Mlme.ShiftReg == 0)
+ NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
+
+ for (i = 0; i < 8; i++)
+ {
+ if (pAd->Mlme.ShiftReg & 0x00000001)
+ {
+ pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
+ Result = 1;
+ }
+ else
+ {
+ pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
+ Result = 0;
+ }
+ R = (R << 1) | Result;
+ }
+
+ return R;
+}
+
+
+UCHAR RandomByte2(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 a,b;
+ UCHAR value, seed = 0;
+
+ /*MAC statistic related*/
+ RTMP_IO_READ32(pAd, RX_STA_CNT1, &a);
+ a &= 0x0000ffff;
+ RTMP_IO_READ32(pAd, RX_STA_CNT0, &b);
+ b &= 0x0000ffff;
+ value = (a<<16)|b;
+
+ /*get seed by RSSI or SNR related info */
+ seed = rtmp_bbp_get_random_seed(pAd);
+
+ return value ^ seed ^ RandomByte(pAd);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Verify the support rate for different PHY type
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ ========================================================================
+*/
+VOID RTMPCheckRates(
+ IN PRTMP_ADAPTER pAd,
+ INOUT UCHAR SupRate[],
+ INOUT UCHAR *SupRateLen)
+{
+ UCHAR RateIdx, i, j;
+ UCHAR NewRate[12], NewRateLen;
+
+ NewRateLen = 0;
+
+ if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B))
+ RateIdx = 4;
+ else
+ RateIdx = 12;
+
+ /* Check for support rates exclude basic rate bit */
+ for (i = 0; i < *SupRateLen; i++)
+ for (j = 0; j < RateIdx; j++)
+ if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
+ NewRate[NewRateLen++] = SupRate[i];
+
+ *SupRateLen = NewRateLen;
+ NdisMoveMemory(SupRate, NewRate, NewRateLen);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Verify the support rate for different PHY type
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ ========================================================================
+*/
+VOID RTMPUpdateMlmeRate(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR MinimumRate;
+ UCHAR ProperMlmeRate; /*= RATE_54;*/
+ UCHAR i, j, RateIdx = 12; /*1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54*/
+ BOOLEAN bMatch = FALSE;
+
+
+ switch (pAd->CommonCfg.PhyMode)
+ {
+ case (WMODE_B):
+ ProperMlmeRate = RATE_11;
+ MinimumRate = RATE_1;
+ break;
+ case (WMODE_B | WMODE_G):
+#ifdef DOT11_N_SUPPORT
+ case (WMODE_B | WMODE_G | WMODE_GN | WMODE_A |WMODE_AN):
+ case (WMODE_B | WMODE_G | WMODE_GN):
+#endif /* DOT11_N_SUPPORT */
+ if ((pAd->MlmeAux.SupRateLen == 4) &&
+ (pAd->MlmeAux.ExtRateLen == 0))
+ /* B only AP*/
+ ProperMlmeRate = RATE_11;
+ else
+ ProperMlmeRate = RATE_24;
+
+ if (pAd->MlmeAux.Channel <= 14)
+ MinimumRate = RATE_1;
+ else
+ MinimumRate = RATE_6;
+ break;
+ case (WMODE_A):
+#ifdef DOT11_N_SUPPORT
+ case (WMODE_GN): /* rt2860 need to check mlmerate for 802.11n*/
+ case (WMODE_G | WMODE_GN):
+ case (WMODE_A | WMODE_G | WMODE_GN | WMODE_AN):
+ case (WMODE_A |WMODE_AN):
+ case (WMODE_AN):
+#endif /* DOT11_N_SUPPORT */
+ ProperMlmeRate = RATE_24;
+ MinimumRate = RATE_6;
+ break;
+ case (WMODE_A |WMODE_B | WMODE_G):
+ ProperMlmeRate = RATE_24;
+ if (pAd->MlmeAux.Channel <= 14)
+ MinimumRate = RATE_1;
+ else
+ MinimumRate = RATE_6;
+ break;
+ default:
+ ProperMlmeRate = RATE_1;
+ MinimumRate = RATE_1;
+ break;
+ }
+
+
+#ifdef DOT11_VHT_AC
+ if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B))
+ {
+ ProperMlmeRate = RATE_11;
+ MinimumRate = RATE_1;
+ }
+ else
+ {
+ if (WMODE_CAP(pAd->CommonCfg.PhyMode, WMODE_B))
+ {
+ if ((pAd->MlmeAux.SupRateLen == 4) && (pAd->MlmeAux.ExtRateLen == 0))
+ ProperMlmeRate = RATE_11; /* B only AP */
+ else
+ ProperMlmeRate = RATE_24;
+
+ if (pAd->MlmeAux.Channel <= 14)
+ MinimumRate = RATE_1;
+ else
+ MinimumRate = RATE_6;
+ }
+ else
+ {
+ ProperMlmeRate = RATE_24;
+ MinimumRate = RATE_6;
+ }
+ }
+#endif /* DOT11_VHT_AC */
+
+ for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
+ {
+ for (j = 0; j < RateIdx; j++)
+ {
+ if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
+ {
+ if (j == ProperMlmeRate)
+ {
+ bMatch = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (bMatch)
+ break;
+ }
+
+ if (bMatch == FALSE)
+ {
+ for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
+ {
+ for (j = 0; j < RateIdx; j++)
+ {
+ if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
+ {
+ if (j == ProperMlmeRate)
+ {
+ bMatch = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (bMatch)
+ break;
+ }
+ }
+
+ if (bMatch == FALSE)
+ {
+ ProperMlmeRate = MinimumRate;
+ }
+
+ pAd->CommonCfg.MlmeRate = MinimumRate;
+ pAd->CommonCfg.RtsRate = ProperMlmeRate;
+ if (pAd->CommonCfg.MlmeRate >= RATE_6)
+ {
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+ pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+ pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
+ pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+ }
+ else
+ {
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
+ pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
+ pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
+ pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
+}
+
+
+CHAR RTMPAvgRssi(
+ IN PRTMP_ADAPTER pAd,
+ IN RSSI_SAMPLE *pRssi)
+{
+ CHAR Rssi;
+
+ if(pAd->Antenna.field.RxPath == 3)
+ {
+ Rssi = (pRssi->AvgRssi0 + pRssi->AvgRssi1 + pRssi->AvgRssi2)/3;
+ }
+ else if(pAd->Antenna.field.RxPath == 2)
+ {
+ Rssi = (pRssi->AvgRssi0 + pRssi->AvgRssi1)>>1;
+ }
+ else
+ {
+ Rssi = pRssi->AvgRssi0;
+ }
+
+ return Rssi;
+}
+
+
+CHAR RTMPMaxRssi(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR Rssi0,
+ IN CHAR Rssi1,
+ IN CHAR Rssi2)
+{
+ CHAR larger = -127;
+
+ if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
+ {
+ larger = Rssi0;
+ }
+
+ if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
+ {
+ larger = max(Rssi0, Rssi1);
+ }
+
+ if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
+ {
+ larger = max(larger, Rssi2);
+ }
+
+ if (larger == -127)
+ larger = 0;
+
+ return larger;
+}
+
+
+CHAR RTMPMinSnr(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR Snr0,
+ IN CHAR Snr1)
+{
+ CHAR smaller = Snr0;
+
+ if (pAd->Antenna.field.RxPath == 1)
+ {
+ smaller = Snr0;
+ }
+
+ if ((pAd->Antenna.field.RxPath >= 2) && (Snr1 != 0))
+ {
+ smaller = min(Snr0, Snr1);
+ }
+
+ return smaller;
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Periodic evaluate antenna link status
+
+ Arguments:
+ pAd - Adapter pointer
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID AsicEvaluateRxAnt(
+ IN PRTMP_ADAPTER pAd)
+{
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ return;
+#endif /* RALINK_ATE */
+
+#ifdef RTMP_MAC_USB
+#endif /* RTMP_MAC_USB */
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
+ fRTMP_ADAPTER_HALT_IN_PROGRESS |
+ fRTMP_ADAPTER_RADIO_OFF |
+ fRTMP_ADAPTER_NIC_NOT_EXIST |
+ fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
+ || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
+ )
+ return;
+
+#ifdef RT3290
+ if (IS_RT3290(pAd) && (pAd->RalinkCounters.OneSecTransmittedByteCount >= 500))
+ return;
+#endif /* RT3290 */
+
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+/* if (pAd->CommonCfg.bRxAntDiversity == ANT_DIVERSITY_DISABLE)*/
+ /* for SmartBit 64-byte stream test */
+ if (pAd->MacTab.Size > 0)
+ APAsicEvaluateRxAnt(pAd);
+ return;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+}
+
+
+/*
+ ========================================================================
+ Routine Description:
+ After evaluation, check antenna link status
+
+ Arguments:
+ pAd - Adapter pointer
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID AsicRxAntEvalTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ return;
+#endif /* RALINK_ATE */
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
+ fRTMP_ADAPTER_HALT_IN_PROGRESS |
+ fRTMP_ADAPTER_RADIO_OFF |
+ fRTMP_ADAPTER_NIC_NOT_EXIST)
+ || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
+ )
+ return;
+
+ {
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+/* if (pAd->CommonCfg.bRxAntDiversity == ANT_DIVERSITY_DISABLE)*/
+ APAsicRxAntEvalTimeout(pAd);
+ return;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+}
+
+
+VOID APSDPeriodicExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+ if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
+ !OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED))
+ return;
+
+ pAd->CommonCfg.TriggerTimerCount++;
+
+/* Driver should not send trigger frame, it should be send by application layer*/
+/*
+ if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
+ && (pAd->CommonCfg.bNeedSendTriggerFrame ||
+ (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
+ RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
+ pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
+ pAd->CommonCfg.TriggerTimerCount = 0;
+ pAd->CommonCfg.bInServicePeriod = TRUE;
+ }*/
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Set/reset MAC registers according to bPiggyBack parameter
+
+ Arguments:
+ pAd - Adapter pointer
+ bPiggyBack - Enable / Disable Piggy-Back
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID RTMPSetPiggyBack(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bPiggyBack)
+{
+ TX_LINK_CFG_STRUC TxLinkCfg;
+
+ RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
+
+ TxLinkCfg.field.TxCFAckEn = bPiggyBack;
+ RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ check if this entry need to switch rate automatically
+
+ Arguments:
+ pAd
+ pEntry
+
+ Return Value:
+ TURE
+ FALSE
+
+ ========================================================================
+*/
+BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry)
+{
+ BOOLEAN result = TRUE;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ if (pEntry)
+ {
+ if (IS_ENTRY_CLIENT(pEntry))
+ result = pAd->ApCfg.MBSSID[pEntry->apidx].bAutoTxRateSwitch;
+#ifdef WDS_SUPPORT
+ else if (IS_ENTRY_WDS(pEntry))
+ result = pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].bAutoTxRateSwitch;
+#endif /* WDS_SUPPORT */
+#ifdef APCLI_SUPPORT
+ else if (IS_ENTRY_APCLI(pEntry))
+ result = pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].bAutoTxRateSwitch;
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+
+ return result;
+}
+
+
+BOOLEAN RTMPAutoRateSwitchCheck(
+ IN PRTMP_ADAPTER pAd)
+{
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ INT apidx = 0;
+
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ if (pAd->ApCfg.MBSSID[apidx].bAutoTxRateSwitch)
+ return TRUE;
+ }
+#ifdef WDS_SUPPORT
+ for (apidx = 0; apidx < MAX_WDS_ENTRY; apidx++)
+ {
+ if (pAd->WdsTab.WdsEntry[apidx].bAutoTxRateSwitch)
+ return TRUE;
+ }
+#endif /* WDS_SUPPORT */
+#ifdef APCLI_SUPPORT
+ for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++)
+ {
+ if (pAd->ApCfg.ApCliTab[apidx].bAutoTxRateSwitch)
+ return TRUE;
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ return FALSE;
+}
+
+
+/*
+ ========================================================================
+ Routine Description:
+ check if this entry need to fix tx legacy rate
+
+ Arguments:
+ pAd
+ pEntry
+
+ Return Value:
+ TURE
+ FALSE
+
+ ========================================================================
+*/
+UCHAR RTMPStaFixedTxMode(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry)
+{
+ UCHAR tx_mode = FIXED_TXMODE_HT;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ if (pEntry)
+ {
+ if (IS_ENTRY_CLIENT(pEntry))
+ tx_mode = (UCHAR)pAd->ApCfg.MBSSID[pEntry->apidx].DesiredTransmitSetting.field.FixedTxMode;
+#ifdef WDS_SUPPORT
+ else if (IS_ENTRY_WDS(pEntry))
+ tx_mode = (UCHAR)pAd->WdsTab.WdsEntry[pEntry->MatchWDSTabIdx].DesiredTransmitSetting.field.FixedTxMode;
+#endif /* WDS_SUPPORT */
+#ifdef APCLI_SUPPORT
+ else if (IS_ENTRY_APCLI(pEntry))
+ tx_mode = (UCHAR)pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx].DesiredTransmitSetting.field.FixedTxMode;
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ return tx_mode;
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
+
+ Arguments:
+ pAd
+ pEntry
+
+ Return Value:
+ TURE
+ FALSE
+
+ ========================================================================
+*/
+VOID RTMPUpdateLegacyTxSetting(
+ UCHAR fixed_tx_mode,
+ PMAC_TABLE_ENTRY pEntry)
+{
+ HTTRANSMIT_SETTING TransmitSetting;
+
+ if (fixed_tx_mode == FIXED_TXMODE_HT)
+ return;
+
+ TransmitSetting.word = 0;
+
+ TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
+ TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
+
+ if (fixed_tx_mode == FIXED_TXMODE_CCK)
+ {
+ TransmitSetting.field.MODE = MODE_CCK;
+ /* CCK mode allow MCS 0~3*/
+ if (TransmitSetting.field.MCS > MCS_3)
+ TransmitSetting.field.MCS = MCS_3;
+ }
+ else
+ {
+ TransmitSetting.field.MODE = MODE_OFDM;
+ /* OFDM mode allow MCS 0~7*/
+ if (TransmitSetting.field.MCS > MCS_7)
+ TransmitSetting.field.MCS = MCS_7;
+ }
+
+ if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
+ {
+ pEntry->HTPhyMode.word = TransmitSetting.word;
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
+ pEntry->Aid, get_phymode_str(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : the fixed TxMode is invalid \n", __FUNCTION__));
+ }
+}
+
+
+
+VOID RTMPSetAGCInitValue(RTMP_ADAPTER *pAd, UCHAR BandWidth)
+{
+ if (pAd->chipOps.ChipAGCInit != NULL)
+ pAd->chipOps.ChipAGCInit(pAd, BandWidth);
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Check if the channel has the property.
+
+Arguments:
+ pAd - WLAN control block pointer
+ ChanNum - channel number
+ Property - channel property, CHANNEL_PASSIVE_SCAN, etc.
+
+Return Value:
+ TRUE - YES
+ FALSE - NO
+
+Note:
+========================================================================
+*/
+BOOLEAN CHAN_PropertyCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT32 ChanNum,
+ IN UCHAR Property)
+{
+ UINT32 IdChan;
+
+
+ /* look for all registered channels */
+ for(IdChan=0; IdChan<pAd->ChannelListNum; IdChan++)
+ {
+ if (pAd->ChannelList[IdChan].Channel == ChanNum)
+ {
+ if ((pAd->ChannelList[IdChan].Flags & Property) == Property)
+ return TRUE;
+
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/multi_channel.c b/cleopatre/devkit/mt7601udrv/common/multi_channel.c
new file mode 100644
index 0000000000..2474e80885
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/multi_channel.c
@@ -0,0 +1,1012 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ****************************************************************************
+
+ Module Name:
+ multi_channel.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ --------- ---------- ----------------------------------------------
+ */
+
+
+#include "rt_config.h"
+
+#ifdef CONFIG_MULTI_CHANNEL
+
+UINT32 SwitchTime1, SwitchTime2, SwitchTime3, SwitchTime4, SwitchTime5, SwitchTime6, SwitchTime7, SwitchTime8;
+UINT32 TempTimeLo, TempTimeHi;
+
+extern INT Set_P2pCli_Enable_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg);
+
+extern INT Set_P2p_OpMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg);
+
+VOID RtmpPrepareHwNullFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN BOOLEAN bQosNull,
+ IN BOOLEAN bEOSP,
+ IN UCHAR OldUP,
+ IN UCHAR OpMode,
+ IN UCHAR PwrMgmt,
+ IN BOOLEAN bWaitACK,
+ IN CHAR Index)
+{
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+ TXWI_STRUC *pTxWI;
+ TXINFO_STRUC *pTxInfo;
+ PUCHAR pNullFrame;
+ PHEADER_802_11 pNullFr;
+ UINT32 frameLen;
+ UINT32 totalLen;
+ UCHAR *ptr;
+ UINT i;
+ UINT32 longValue;
+ UCHAR MlmeRate;
+
+#ifdef RT_BIG_ENDIAN
+ NDIS_STATUS NState;
+ PUCHAR pNullFrBuf;
+#endif /* RT_BIG_ENDIAN */
+
+
+ NdisZeroMemory(pAd->NullFrBuf, sizeof(pAd->NullFrBuf));
+ pTxWI = (TXWI_STRUC *)&pAd->NullFrBuf[0];
+ pNullFrame = &pAd->NullFrBuf[TXWISize];
+
+ pNullFr = (PHEADER_802_11) pNullFrame;
+ frameLen = sizeof(HEADER_802_11);
+
+ pNullFr->FC.Type = BTYPE_DATA;
+ pNullFr->FC.SubType = SUBTYPE_NULL_FUNC;
+ pNullFr->FC.ToDs = 1;
+ pNullFr->FC.FrDs = 0;
+
+ COPY_MAC_ADDR(pNullFr->Addr1, pEntry->Addr);
+ {
+ COPY_MAC_ADDR(pNullFr->Addr2, pAd->CurrentAddress);
+ COPY_MAC_ADDR(pNullFr->Addr3, pAd->CommonCfg.Bssid);
+ }
+
+ pNullFr->FC.PwrMgmt = PwrMgmt;
+
+ pNullFr->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, pAd->CommonCfg.TxRate, 14);
+
+ /* sequence is increased in MlmeHardTx */
+ pNullFr->Sequence = pAd->Sequence;
+ pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */
+
+ if (bQosNull)
+ {
+ UCHAR *qos_p = ((UCHAR *)pNullFr) + frameLen;
+
+ pNullFr->FC.SubType = SUBTYPE_QOS_NULL;
+
+ /* copy QOS control bytes */
+ qos_p[0] = ((bEOSP) ? (1 << 4) : 0) | OldUP;
+ qos_p[1] = 0;
+ frameLen += 2;
+ } /* End of if */
+
+ RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, 0, pEntry->Aid, frameLen,
+ 0, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit);
+
+ dumpTxWI(pAd, pTxWI);
+
+ if (bWaitACK)
+ pTxWI->TxWITXRPT = 1;
+
+ hex_dump("RtmpPrepareHwNullFrame", pAd->NullFrBuf, TXWISize + frameLen);
+
+ totalLen = TXWISize + frameLen;
+ pAd->NullFrLen = totalLen;
+ ptr = pAd->NullFrBuf;
+
+#ifdef RT_BIG_ENDIAN
+ NState = os_alloc_mem(pAd, (PUCHAR *) &pNullFrBuf, 100);
+ if ( NState == NDIS_STATUS_FAILURE )
+ return;
+
+ NdisZeroMemory(pNullFrame, 100);
+ NdisMoveMemory(pNullFrBuf, pAd->NullFrBuf, totalLen);
+ RTMPWIEndianChange(pAd, pNullFrBuf, TYPE_TXWI);
+ RTMPFrameEndianChange(pAd, (PUCHAR)pNullFrBuf + TXWISize, DIR_WRITE, FALSE);
+
+ ptr = pNullFrBuf;
+#endif /* RT_BIG_ENDIAN */
+
+
+ for (i= 0; i< totalLen; i+=4)
+ {
+ longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24);
+ //hex_dump("null frame before",&longValue, 4);
+
+ if (Index == 0)
+ RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[0] + i, longValue);
+ else if (Index == 1)
+ RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[1] + i, longValue);
+
+ //RTMP_IO_WRITE32(pAd, 0xB700 + i, longValue);
+ //RTMP_IO_WRITE32(pAd, 0xB780 + i, longValue);
+
+ ptr += 4;
+ }
+
+
+
+}
+
+
+VOID RTMPHwSendNullFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR TxRate,
+ IN BOOLEAN bQosNull,
+ IN USHORT PwrMgmt,
+ IN CHAR Index)
+{
+
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+ NDIS_STATUS NState;
+ PHEADER_802_11 pNullFr;
+ UCHAR *ptr;
+ UINT32 longValue;
+#ifdef RT_BIG_ENDIAN
+ PUCHAR pNullFrame;
+#endif /* RT_BIG_ENDIAN */
+ UINT32 Data=0;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s - Send NULL Frame @%d Mbps...%d \n", __FUNCTION__, RateIdToMbps[pAd->CommonCfg.TxRate],PwrMgmt));
+
+ pNullFr = (PHEADER_802_11)((&pAd->NullFrBuf[0]) +TXWISize);
+
+ pNullFr->FC.PwrMgmt = PwrMgmt;
+
+ pNullFr->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
+
+ /* sequence is increased in MlmeHardTx */
+ pNullFr->Sequence = pAd->Sequence;
+ pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */
+
+ //hex_dump("RtmpPrepareHwNullFrame", pAd->NullFrBuf, pAd->NullFrLen);
+
+ if (Index == 0)
+ {
+ ptr = pAd->NullFrBuf + TXWISize;
+
+#ifdef RT_BIG_ENDIAN
+ longValue = (*ptr << 8) + *(ptr + 1) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24);
+#else
+ longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24);
+#endif /* RT_BIG_ENDIAN */
+ RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[0] + TXWISize, longValue);
+
+ ptr = pAd->NullFrBuf + TXWISize + 20; // update Sequence
+ longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24);
+ RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[0] + TXWISize + 20, longValue);
+
+ RTMP_IO_READ32(pAd, PBF_CFG, &Data);
+ Data &= 0xffffff1f; /* Null 2 frame buffer select bit[5:7]=0 */
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Data);
+ }
+ else if (Index == 1)
+ {
+ ptr = pAd->NullFrBuf + TXWISize;
+#ifdef RT_BIG_ENDIAN
+ longValue = (*ptr << 8) + *(ptr + 1) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24);
+#else
+ longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24);
+#endif /* RT_BIG_ENDIAN */
+ RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[1] + TXWISize, longValue);
+
+ ptr = pAd->NullFrBuf + TXWISize + 20; // update Sequence
+ longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24);
+ RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[1] + TXWISize + 20, longValue);
+
+ RTMP_IO_READ32(pAd, PBF_CFG, &Data);
+ Data &= 0xffffff1f; /* Null 2 frame buffer select bit[5:7]=1 */
+ Data |= 0x20; /* Null 2 frame buffer select bit[5:7]=1 */
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Data);
+ }
+
+ RTMP_IO_WRITE32(pAd, PBF_CTRL, 0x04);
+
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Send out a NULL frame to a specified STA at a higher TX rate. The
+ purpose is to ensure the designated client is okay to received at this
+ rate.
+ ==========================================================================
+ */
+VOID RtmpEnqueueLastNullFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UCHAR TxRate,
+ IN UCHAR PID,
+ IN UCHAR apidx,
+ IN BOOLEAN bQosNull,
+ IN BOOLEAN bEOSP,
+ IN UCHAR OldUP,
+ IN UCHAR PwrMgmt,
+ IN UCHAR OpMode)
+{
+ UCHAR NullFrame[48];
+ ULONG Length;
+ PHEADER_802_11 pHeader_802_11;
+ MAC_TABLE_ENTRY *pEntry = NULL;
+ PAPCLI_STRUCT pApCliEntry = NULL;
+
+ pEntry = MacTableLookup(pAd, pAddr);
+
+ if (pEntry == NULL)
+ {
+ return;
+ }
+
+ NdisZeroMemory(NullFrame, 48);
+ Length = sizeof(HEADER_802_11);
+
+ pHeader_802_11 = (PHEADER_802_11) NullFrame;
+
+ pHeader_802_11->FC.Type = BTYPE_DATA;
+ pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
+ pHeader_802_11->FC.ToDs = 1;
+
+ COPY_MAC_ADDR(pHeader_802_11->Addr1, pEntry->Addr);
+ {
+ COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
+ COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
+ }
+
+ pHeader_802_11->FC.PwrMgmt = PwrMgmt;
+
+ pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
+
+ /* sequence is increased in MlmeHardTx */
+ pHeader_802_11->Sequence = pAd->Sequence;
+ pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */
+
+ /* Prepare QosNull function frame */
+ if (bQosNull)
+ {
+ pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
+
+ /* copy QOS control bytes */
+ NullFrame[Length] = 0;
+ NullFrame[Length+1] = 0;
+ Length += 2;/* if pad with 2 bytes for alignment, APSD will fail */
+ }
+}
+
+
+
+
+VOID MCC_ChangeAction(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext;
+ RtmpOsTaskWakeUp(&(pAd->MultiChannelTask));
+}
+
+VOID ConcurrentP2PConnectTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ int i;
+ RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext;
+ PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg;
+
+ pAd->Mlme.ConcurrentP2PConnectTimerRunning = FALSE;
+ pAd->P2pCfg.bStartP2pConnect = FALSE;
+
+ if (pAd->P2pCfg.bStartP2pConnect)
+ {
+ P2pStopConnectThis(pAd);
+ pAd->StaCfg.bAutoReconnect = TRUE;
+ pP2PCtrl->bSentProbeRSP = FALSE;
+ P2pStopScan(pAd);
+
+ P2pGroupTabInit(pAd);
+ pP2PCtrl->GoFormCurrentState = P2P_GO_FORM_IDLE;
+
+ /* Restore P2P WSC Mode / Config Method */
+ pP2PCtrl->WscMode = WSC_PIN_MODE; /* PIN */
+ pP2PCtrl->ConfigMethod = 0x188;
+ pP2PCtrl->Dpid = DEV_PASS_ID_NOSPEC;
+
+ if (P2P_CLI_ON(pAd))
+ {
+
+ Set_P2pCli_Enable_Proc(pAd, "0");
+
+ }
+
+ Set_P2p_OpMode_Proc(pAd, "0");
+ pAd->ApCfg.ApCliTab[0].WscControl.WscConfStatus = WSC_SCSTATE_UNCONFIGURED;
+ pAd->ApCfg.MBSSID[0].WscControl.WscConfStatus = WSC_SCSTATE_UNCONFIGURED;
+ OS_WAIT(200);
+
+ if (INFRA_ON(pAd))
+ MultiChannelSwitchToRa(pAd);
+
+ }
+}
+
+
+
+static VOID MACBuffer_Change(
+ RTMP_ADAPTER *pAd,
+ BOOLEAN hcca_to_edca,
+ BOOLEAN edca_to_hcca)
+{
+ MAC_TABLE_ENTRY *pEntry = NULL;
+ PAPCLI_STRUCT pApCliEntry = NULL;
+ UINT i = 0;
+ UINT32 MacValue, Data, Data2;
+ INT ret;
+ UINT32 MTxCycle;
+ UINT32 TimeStamp;
+ BOOLEAN bBlockIn2Out=FALSE;
+ pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0];
+ INT ext_ch;
+
+// RTMP_SEM_EVENT_WAIT(&pAd->reg_atomic2, ret);
+ if (edca_to_hcca)
+ RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev);
+ if (hcca_to_edca)
+ RTMP_OS_NETDEV_STOP_QUEUE(pApCliEntry->dev);
+// RTMP_SEM_EVENT_UP(&pAd->reg_atomic2);
+
+
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET);
+
+ /* Disable EDCA or HCCA dequeue */
+ if (edca_to_hcca)
+ {
+ pAd->MultiChannelFlowCtl |= EDCA_AC0_DEQUEUE_DISABLE;// 1
+ }
+ if(hcca_to_edca)
+ {
+ pAd->MultiChannelFlowCtl |= HCCA_DEQUEUE_DISABLE;//16
+ }
+
+
+ RTMP_IO_READ32(pAd, WMM_CTRL, &Data);
+
+ if(edca_to_hcca)
+ Data |= 0x80000000;/* bit 31 set to 1 */ /* WMM Channel switch to EDCA2 */
+ if(hcca_to_edca)
+ Data &= 0x7fffffff;/* bit 31 set to 0 */ /* WMM Channel switch to EDCA1 */
+
+
+ RTMP_IO_WRITE32(pAd, WMM_CTRL, Data);
+
+ /* Polling EDCA or EDCA2 Out-Q until empty */
+
+ for (MTxCycle = 0;; MTxCycle++)
+ {
+ if (!bBlockIn2Out)
+ {
+ RTMP_IO_READ32(pAd, 0x438, &Data);
+ if ((edca_to_hcca) && (((Data >> 16) & 0xff) == 0))
+ {
+ /* Disable EDCA1 In-Q to Out-Q */
+ RTMP_IO_READ32(pAd, PBF_CFG, &Data);
+ Data &= 0xffffEfff;/* bit 12 set to 0 */ //zero modify 20120807
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Data);
+ bBlockIn2Out=TRUE;
+ }
+ else if ((hcca_to_edca) && (((Data >> 24) & 0xff) == 0))
+ {
+ /* Disable HCCA/EDCA2 In-Q to Out-Q */
+ RTMP_IO_READ32(pAd, PBF_CFG, &Data);
+ Data &= 0xffffDfff;/* set bit 13 set to 0 */ //zero modify 20120807
+ //Data |= ((1 << 10) | (1 << 11));
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Data);
+ bBlockIn2Out=TRUE;
+ }
+ else
+ RTMPusecDelay(50);
+ }
+ else
+ {
+ RTMP_IO_READ32(pAd, TXQ_STA, &Data);
+ if ((edca_to_hcca) && (((Data >> 19) & 0x1f) == 0))
+ break;
+ else if ((hcca_to_edca) && (((Data >> 27) & 0x1f) == 0))
+ break;
+ else
+ RTMPusecDelay(50);
+ }
+
+ }
+
+ if (MTxCycle >= 2000)
+ {
+ if(edca_to_hcca)
+ DBGPRINT(RT_DEBUG_ERROR, ("Polling EDCA Out-Q max(%x)\n", Data));
+ if(hcca_to_edca)
+ DBGPRINT(RT_DEBUG_ERROR, ("Polling HCCA Out-Q max\n"));
+
+ }
+
+ if(edca_to_hcca)
+ RTMPHwSendNullFrame(pAd,
+ pAd->CommonCfg.TxRate,
+ (pAd->CommonCfg.bWmmCapable & pAd->CommonCfg.APEdcaParm.bValid),
+ PWR_SAVE, 0);
+
+ if(hcca_to_edca)
+ RTMPHwSendNullFrame(pAd,
+ pAd->CommonCfg.TxRate,
+ (pAd->CommonCfg.bWmmCapable & pAd->CommonCfg.APEdcaParm.bValid),
+ PWR_SAVE, 1);
+
+
+ RtmpOsMsDelay(20);
+ /* Disable all Tx Out-Q */
+ RTMP_IO_READ32(pAd, PBF_CFG, &Data);
+ Data &= 0xfffffff3;/* bit 3 and bit 2 set to 0 */ //zero modify 20120807
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Data);
+
+
+
+ if(hcca_to_edca)
+ {
+ if (pAd->StaCfg.BW == BW_40)
+ {
+ if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
+ ext_ch = EXTCHA_ABOVE;
+
+ else
+ ext_ch = EXTCHA_BELOW;
+ }
+ else
+ {
+ ext_ch = EXTCHA_NONE;
+ }
+
+ AsicSetChannel(pAd, pAd->CommonCfg.CentralChannel, pAd->StaCfg.BW, ext_ch, FALSE);
+
+ }
+
+ if(edca_to_hcca)
+ {
+ if (pAd->P2pCfg.BW == BW_40)
+ {
+ if (pAd->ApCliMlmeAux.CentralChannel > pAd->ApCliMlmeAux.Channel)
+ ext_ch = EXTCHA_ABOVE;
+ else
+ ext_ch = EXTCHA_BELOW;
+
+ }
+ else
+ {
+ ext_ch = EXTCHA_NONE;
+ }
+
+ AsicSetChannel(pAd, pAd->ApCliMlmeAux.CentralChannel, pAd->P2pCfg.BW, ext_ch, FALSE);
+
+ }
+
+
+
+ if(edca_to_hcca)
+ RTMPHwSendNullFrame(pAd,
+ pAd->CommonCfg.TxRate,
+ (pAd->CommonCfg.bWmmCapable & pAd->CommonCfg.APEdcaParm.bValid),
+ PWR_ACTIVE, 1);
+
+ if(hcca_to_edca)
+ RTMPHwSendNullFrame(pAd,
+ pAd->CommonCfg.TxRate,
+ (pAd->CommonCfg.bWmmCapable & pAd->CommonCfg.APEdcaParm.bValid),
+ PWR_ACTIVE, 0);
+
+ RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &SwitchTime7);
+
+ /* Enable EDCA or EDCA2 Tx In-Q and Out-Q */
+ RTMP_IO_READ32(pAd, PBF_CFG, &Data);
+ if(edca_to_hcca)
+ Data |= ((1 << 3) | (1 << 13));/* bit 3 and bit 13 set to 1 */
+
+ if(hcca_to_edca)
+ Data |= ((1 << 2) | (1 << 12));/* bit 2 and bit 12 set to 1 */
+
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Data);
+ RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &SwitchTime8);
+
+ if ((i == 10) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Multi Channel Switch Retry count exhausted\n"));
+ }
+
+ /* Enable EDCA or EDCA2 dequeue */
+ if(hcca_to_edca)
+ pAd->MultiChannelFlowCtl &= ~EDCA_AC0_DEQUEUE_DISABLE; // 0
+
+ if(edca_to_hcca)
+ pAd->MultiChannelFlowCtl &= ~HCCA_DEQUEUE_DISABLE; // 0
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET);
+
+// RTMP_SEM_EVENT_WAIT(&pAd->reg_atomic2, ret);
+
+ if(hcca_to_edca)
+ RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev);
+
+ if(edca_to_hcca)
+ RTMP_OS_NETDEV_WAKE_QUEUE(pApCliEntry->dev);
+
+// RTMP_SEM_EVENT_UP(&pAd->reg_atomic2);
+
+
+}
+
+
+static VOID ProcessEDCAToHCCA(
+ RTMP_ADAPTER *pAd)
+{
+ PAPCLI_STRUCT pApCliEntry = NULL;
+
+ pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0];
+
+ UINT32 Data;
+
+ if ((pApCliEntry->Valid) && INFRA_ON(pAd))
+ {
+ MACBuffer_Change(pAd,FALSE, TRUE);
+ RTMPSetTimer(&pAd->Mlme.MCCTimer, pAd->Mlme.HCCAToEDCATimerValue);
+ }
+}
+
+
+static VOID ProcessHCCAToEDCA(
+ PRTMP_ADAPTER pAd)
+{
+ UINT32 MacValue;
+ UINT32 i = 0;
+ INT ret;
+ BOOLEAN bBlockIn2Out=FALSE;
+ UINT32 Data;
+
+ if (P2P_INF_ON(pAd) && P2P_GO_ON(pAd))
+ {
+ ;//APUpdateAllBeaconFrame(pAd);
+ }
+ else
+ {
+ MAC_TABLE_ENTRY *pEntry = NULL;
+ PAPCLI_STRUCT pApCliEntry = NULL;
+ pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0];
+
+ if ((pApCliEntry->Valid) && INFRA_ON(pAd))
+ {
+ MACBuffer_Change(pAd,TRUE, FALSE);
+ RTMPSetTimer(&pAd->Mlme.MCCTimer, pAd->Mlme.EDCAToHCCATimerValue);
+ }
+ }
+}
+
+static INT MultiChannelTaskThread(
+ IN ULONG Context)
+{
+ RTMP_OS_TASK *pTask;
+ RTMP_ADAPTER *pAd;
+ INT Status = 0;
+
+ pTask = (RTMP_OS_TASK *)Context;
+ pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask);
+
+ if (pAd == NULL)
+ return 0;
+
+ RtmpOSTaskCustomize(pTask);
+
+
+ while (pTask && !RTMP_OS_TASK_IS_KILLED(pTask))
+ {
+ if (RtmpOSTaskWait(pAd, pTask, &Status) == FALSE)
+ {
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+ break;
+ }
+
+ if (Status != 0)
+ break;
+
+
+ if (INFRA_ON(pAd) && P2P_CLI_ON(pAd))
+ {
+ if (pAd->LatchRfRegs.Channel == pAd->ApCliMlmeAux.CentralChannel)
+ pAd->MultiChannelAction = HCCA_TO_EDCA;
+ else if (pAd->LatchRfRegs.Channel == pAd->CommonCfg.CentralChannel)
+ pAd->MultiChannelAction = EDCA_TO_HCCA;
+
+ }
+ else if (INFRA_ON(pAd))
+ {
+ // reset to default switct to ra0
+ // MultiChannelSwitchToRa(pAd);
+ }
+ else if (P2P_CLI_ON(pAd))
+ {
+ // reset to default switch to p2p0
+ // MultiChannelSwitchToP2P(pAd);
+
+ }
+
+
+#ifdef RTMP_MAC_USB
+ /* device had been closed */
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ break;
+#endif /* RTMP_MAC_USB */
+ if (pAd->MultiChannelAction == HCCA_TO_EDCA)
+ ProcessHCCAToEDCA(pAd);
+ else if (pAd->MultiChannelAction == EDCA_TO_HCCA)
+ ProcessEDCAToHCCA(pAd);
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Unkown Action(=%d)\n", __FUNCTION__, pAd->MultiChannelAction));
+
+
+
+ }
+
+ if (pTask)
+ RtmpOSTaskNotifyToExit(pTask);
+
+ return 0;
+}
+
+NDIS_STATUS MultiChannelThreadInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ NDIS_STATUS status = NDIS_STATUS_FAILURE;
+ RTMP_OS_TASK *pTask;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> %s\n", __FUNCTION__));
+
+ pTask = &pAd->MultiChannelTask;
+ pAd->MultiChannelAction = 0xFF;
+ pAd->Mlme.HCCAToEDCATimerValue = HCCA_TIMEOUT;
+ pAd->Mlme.EDCAToHCCATimerValue = EDCA_TIMEOUT;
+ pAd->P2pCfg.bStartP2pConnect = FALSE;
+ pAd->MultiChannelFlowCtl = 0;
+
+ RTMPInitTimer(pAd, &pAd->Mlme.MCCTimer, GET_TIMER_FUNCTION(MCC_ChangeAction), pAd, FALSE);
+ RTMPInitTimer(pAd, &pAd->Mlme.ConcurrentP2PConnectTimer, GET_TIMER_FUNCTION(ConcurrentP2PConnectTimeout), pAd, FALSE);
+
+ RTMP_OS_TASK_INIT(pTask, "MultiChannelTask", pAd);
+ status = RtmpOSTaskAttach(pTask, MultiChannelTaskThread, (ULONG)&pAd->MultiChannelTask);
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- %s, status=%d!\n", __FUNCTION__, status));
+
+ return status;
+}
+
+BOOLEAN MultiChannelThreadExit(
+ IN PRTMP_ADAPTER pAd)
+{
+ INT ret;
+
+ MultiChannelTimerStop(pAd);
+
+ ret = RtmpOSTaskKill(&pAd->MultiChannelTask);
+ if (ret == NDIS_STATUS_FAILURE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: kill multi-channel task failed!\n", __FUNCTION__));
+ }
+ return TRUE;
+}
+
+VOID MultiChannelTimerStop(
+ IN PRTMP_ADAPTER pAd)
+{
+
+ BOOLEAN bCancelled = FALSE;
+ PAPCLI_STRUCT pApCliEntry = NULL;
+
+
+ pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0];
+ pAd->MultiChannelAction = 0xFF;
+ RTMPCancelTimer(&pAd->Mlme.MCCTimer, &bCancelled);
+
+ RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev);
+ RTMP_OS_NETDEV_WAKE_QUEUE(pApCliEntry->dev);
+
+ OS_WAIT(200);
+}
+
+VOID MultiChannelTimerStart(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+
+ BOOLEAN bCancelled = FALSE;
+
+ if (pAd->P2pCfg.bStartP2pConnect)
+ {
+ pAd->P2pCfg.bStartP2pConnect = FALSE;
+
+ pAd->StaCfg.ReConnectCountDown = 5;
+
+ if (pAd->Mlme.ConcurrentP2PConnectTimerRunning)
+ {
+ printk("iversondebug MultiChannelTimer start3 \n");
+
+ RTMPCancelTimer(&pAd->Mlme.ConcurrentP2PConnectTimer, &bCancelled);
+ pAd->Mlme.ConcurrentP2PConnectTimerRunning = FALSE;
+ }
+ }
+
+ RTMPSetTimer(&pAd->Mlme.MCCTimer, 200);
+
+ pAd->Mlme.P2pStayTick = 0;
+ pAd->Mlme.StaStayTick = 0;
+}
+
+VOID MultiChannelSwitchToRa(
+ IN PRTMP_ADAPTER pAd)
+{
+ PAPCLI_STRUCT pApCliEntry = NULL;
+ pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0];
+ INT ext_ch;
+
+
+// MACBuffer_Change(pAd,TRUE, FALSE);
+ MAC_TABLE_ENTRY *pEntry = NULL;
+ UINT32 MacValue, Data, Data2;
+ INT ret,i;
+ UINT32 MTxCycle;
+ BOOLEAN bBlockIn2Out=FALSE;
+ pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0];
+
+ RTMP_OS_NETDEV_STOP_QUEUE(pApCliEntry->dev);
+
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET);
+ pAd->MultiChannelFlowCtl |= HCCA_DEQUEUE_DISABLE;//16
+ RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &SwitchTime1);
+ RTMP_IO_READ32(pAd, WMM_CTRL, &Data);
+
+ Data &= 0x7fffffff;/* bit 31 set to 0 */ /* WMM Channel switch to EDCA1 */
+
+ RTMP_IO_WRITE32(pAd, WMM_CTRL, Data);
+ RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &SwitchTime2);
+
+ /* Polling EDCA or EDCA2 Out-Q until empty */
+
+ for (MTxCycle = 0;; MTxCycle++)
+ {
+ if (!bBlockIn2Out)
+ {
+ RTMP_IO_READ32(pAd, 0x438, &Data);
+ if ((((Data >> 24) & 0xff) == 0))
+ {
+ /* Disable HCCA/EDCA2 In-Q to Out-Q */
+ RTMP_IO_READ32(pAd, PBF_CFG, &Data);
+ Data &= 0xffffDfff;/* set bit 13 set to 0 */ //zero modify 20120807
+ //Data |= ((1 << 10) | (1 << 11));
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Data);
+ bBlockIn2Out=TRUE;
+ }
+ else
+ RTMPusecDelay(50);
+ }
+ else
+ {
+ RTMP_IO_READ32(pAd, TXQ_STA, &Data);
+ if ((((Data >> 27) & 0x1f) == 0))
+ break;
+ else
+ RTMPusecDelay(50);
+ }
+
+ }
+
+ if (MTxCycle >= 2000)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Polling HCCA Out-Q max\n"));
+
+ }
+
+ RtmpOsMsDelay(20);
+ /* Disable all Tx Out-Q */
+ RTMP_IO_READ32(pAd, PBF_CFG, &Data);
+ Data &= 0xfffffff3;/* bit 3 and bit 2 set to 0 */ //zero modify 20120807
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Data);
+
+
+ if (pAd->StaCfg.BW == BW_40)
+ {
+ if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
+ ext_ch = EXTCHA_ABOVE;
+ else
+ ext_ch = EXTCHA_BELOW;
+ }
+ else
+ {
+ ext_ch = EXTCHA_NONE;
+ }
+
+ AsicSetChannel(pAd, pAd->CommonCfg.CentralChannel, pAd->StaCfg.BW, ext_ch, FALSE);
+
+
+
+
+ RTMPHwSendNullFrame(pAd,
+ pAd->CommonCfg.TxRate,
+ (pAd->CommonCfg.bWmmCapable & pAd->CommonCfg.APEdcaParm.bValid),
+ PWR_ACTIVE, 0);
+
+ RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &SwitchTime7);
+
+ /* Enable EDCA or EDCA2 Tx In-Q and Out-Q */
+ RTMP_IO_READ32(pAd, PBF_CFG, &Data);
+ Data |= ((1 << 2) | (1 << 12));/* bit 2 and bit 12 set to 1 */
+
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Data);
+
+ if ((i == 10) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Multi Channel Switch Retry count exhausted\n"));
+ }
+
+ /* Enable EDCA or EDCA2 dequeue */
+
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET);
+
+ pAd->MultiChannelFlowCtl = 0;
+
+ RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev);
+
+}
+
+VOID MultiChannelSwitchToP2P(
+ IN PRTMP_ADAPTER pAd)
+{
+ PAPCLI_STRUCT pApCliEntry = NULL;
+ pApCliEntry = &pAd->ApCfg.ApCliTab[BSS0];
+ INT ext_ch;
+
+ MAC_TABLE_ENTRY *pEntry = NULL;
+ UINT i = 0;
+ UINT32 MacValue, Data, Data2;
+ INT ret;
+ UINT32 MTxCycle;
+ BOOLEAN bBlockIn2Out=FALSE;
+
+
+ RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev);
+
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET);
+
+ /* Disable EDCA or HCCA dequeue */
+ pAd->MultiChannelFlowCtl |= EDCA_AC0_DEQUEUE_DISABLE;// 1
+
+ RTMP_IO_READ32(pAd, TSF_TIMER_DW0, &SwitchTime1);
+
+ RTMP_IO_READ32(pAd, WMM_CTRL, &Data);
+
+ Data |= 0x80000000;/* bit 31 set to 1 */ /* WMM Channel switch to EDCA2 */
+
+ RTMP_IO_WRITE32(pAd, WMM_CTRL, Data);
+
+ /* Polling EDCA or EDCA2 Out-Q until empty */
+
+ for (MTxCycle = 0;; MTxCycle++)
+ {
+ if (!bBlockIn2Out)
+ {
+ RTMP_IO_READ32(pAd, 0x438, &Data);
+ if ((((Data >> 16) & 0xff) == 0))
+ {
+ /* Disable EDCA1 In-Q to Out-Q */
+ RTMP_IO_READ32(pAd, PBF_CFG, &Data);
+ Data &= 0xffffEfff;/* bit 12 set to 0 */ //zero modify 20120807
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Data);
+ bBlockIn2Out=TRUE;
+ }
+ else
+ RTMPusecDelay(50);
+ }
+ else
+ {
+ RTMP_IO_READ32(pAd, TXQ_STA, &Data);
+ if ((((Data >> 19) & 0x1f) == 0))
+ break;
+ else
+ RTMPusecDelay(50);
+ }
+
+ }
+
+ if (MTxCycle >= 2000)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Polling EDCA Out-Q max(%x)\n", Data));
+ }
+
+
+ RtmpOsMsDelay(20);
+ /* Disable all Tx Out-Q */
+ RTMP_IO_READ32(pAd, PBF_CFG, &Data);
+ Data &= 0xfffffff3;/* bit 3 and bit 2 set to 0 */ //zero modify 20120807
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Data);
+
+
+ if (pAd->P2pCfg.BW == BW_40)
+ {
+ if (pAd->ApCliMlmeAux.CentralChannel > pAd->ApCliMlmeAux.Channel)
+ ext_ch = EXTCHA_ABOVE;
+ else
+ ext_ch = EXTCHA_BELOW;
+
+ }
+ else
+ {
+ ext_ch = EXTCHA_NONE;
+ }
+
+ AsicSetChannel(pAd, pAd->ApCliMlmeAux.CentralChannel, pAd->P2pCfg.BW, ext_ch, FALSE);
+
+
+
+
+ RTMPHwSendNullFrame(pAd,
+ pAd->CommonCfg.TxRate,
+ (pAd->CommonCfg.bWmmCapable & pAd->CommonCfg.APEdcaParm.bValid),
+ PWR_ACTIVE, 1);
+
+ /* Enable EDCA or EDCA2 Tx In-Q and Out-Q */
+ RTMP_IO_READ32(pAd, PBF_CFG, &Data);
+ Data |= ((1 << 3) | (1 << 13));/* bit 3 and bit 13 set to 1 */
+
+
+ RTMP_IO_WRITE32(pAd, PBF_CFG, Data);
+
+ if ((i == 10) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Multi Channel Switch Retry count exhausted\n"));
+ }
+
+ /* Enable EDCA or EDCA2 dequeue */
+ pAd->MultiChannelFlowCtl = 0; // 0
+
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET);
+
+ RTMP_OS_NETDEV_WAKE_QUEUE(pApCliEntry->dev);
+
+
+}
+
+
+#endif /* CONFIG_MULTI_CHANNEL */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/netif_block.c b/cleopatre/devkit/mt7601udrv/common/netif_block.c
new file mode 100644
index 0000000000..98f06c0299
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/netif_block.c
@@ -0,0 +1,121 @@
+#ifdef BLOCK_NET_IF
+
+#include "rt_config.h"
+#include "netif_block.h"
+
+static NETIF_ENTRY freeNetIfEntryPool[FREE_NETIF_POOL_SIZE];
+static LIST_HEADER freeNetIfEntryList;
+
+void initblockQueueTab(
+ IN PRTMP_ADAPTER pAd)
+{
+ int i;
+
+ initList(&freeNetIfEntryList);
+ for (i = 0; i < FREE_NETIF_POOL_SIZE; i++)
+ insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)&freeNetIfEntryPool[i]);
+
+ for (i=0; i < NUM_OF_TX_RING; i++)
+ initList(&pAd->blockQueueTab[i].NetIfList);
+
+ return;
+}
+
+BOOLEAN blockNetIf(
+ IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry,
+ IN PNET_DEV pNetDev)
+{
+ PNETIF_ENTRY pNetIfEntry = NULL;
+
+ if ((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(&freeNetIfEntryList)) != NULL)
+ {
+ RTMP_OS_NETDEV_STOP_QUEUE(pNetDev);
+ pNetIfEntry->pNetDev = pNetDev;
+ insertTailList(&pBlockQueueEntry->NetIfList, (PLIST_ENTRY)pNetIfEntry);
+
+ pBlockQueueEntry->SwTxQueueBlockFlag = TRUE;
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMP_OS_NETDEV_STOP_QUEUE(%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(pNetDev)));
+ }
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+VOID releaseNetIf(
+ IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry)
+{
+ PNETIF_ENTRY pNetIfEntry = NULL;
+ PLIST_HEADER pNetIfList = &pBlockQueueEntry->NetIfList;
+
+ while((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(pNetIfList)) != NULL)
+ {
+ PNET_DEV pNetDev = pNetIfEntry->pNetDev;
+ RTMP_OS_NETDEV_WAKE_QUEUE(pNetDev);
+ insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)pNetIfEntry);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMP_OS_NETDEV_WAKE_QUEUE(%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(pNetDev)));
+ }
+ pBlockQueueEntry->SwTxQueueBlockFlag = FALSE;
+ return;
+}
+
+
+VOID StopNetIfQueue(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket)
+{
+ PNET_DEV NetDev = NULL;
+ UCHAR IfIdx = 0;
+ BOOLEAN valid = FALSE;
+
+
+#ifdef APCLI_SUPPORT
+ if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_APCLI)
+ {
+ IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_APCLI) % MAX_APCLI_NUM;
+ NetDev = pAd->ApCfg.ApCliTab[IfIdx].dev;
+ }
+ else
+#endif /* APCLI_SUPPORT */
+#ifdef WDS_SUPPORT
+ if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_WDS)
+ {
+ IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_WDS) % MAX_WDS_ENTRY;
+ NetDev = pAd->WdsTab.WdsEntry[IfIdx].dev;
+ }
+ else
+#endif /* WDS_SUPPORT */
+ {
+#ifdef MBSS_SUPPORT
+ if (pAd->OpMode == OPMODE_AP)
+ {
+ IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_MBSSID) % MAX_MBSSID_NUM(pAd);
+ NetDev = pAd->ApCfg.MBSSID[IfIdx].MSSIDDev;
+ }
+ else
+ {
+ IfIdx = MAIN_MBSSID;
+ NetDev = pAd->net_dev;
+ }
+#else
+ IfIdx = MAIN_MBSSID;
+ NetDev = pAd->net_dev;
+#endif
+ }
+
+ /* WMM support 4 software queues.*/
+ /* One software queue full doesn't mean device have no capbility to transmit packet.*/
+ /* So disable block Net-If queue function while WMM enable.*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ valid = (pAd->ApCfg.MBSSID[IfIdx].bWmmCapable == TRUE) ? FALSE : TRUE;
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (valid)
+ blockNetIf(&pAd->blockQueueTab[QueIdx], NetDev);
+ return;
+}
+
+#endif /* BLOCK_NET_IF */
diff --git a/cleopatre/devkit/mt7601udrv/common/ps.c b/cleopatre/devkit/mt7601udrv/common/ps.c
new file mode 100644
index 0000000000..a719627e30
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/ps.c
@@ -0,0 +1,370 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2010, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************/
+
+/****************************************************************************
+
+ Abstract:
+
+ All related POWER SAVE function body.
+
+***************************************************************************/
+
+#include "rt_config.h"
+
+
+/*
+ ========================================================================
+ Routine Description:
+ This routine is used to do insert packet into power-saveing queue.
+
+ Arguments:
+ pAd: Pointer to our adapter
+ pPacket: Pointer to send packet
+ pMacEntry: portint to entry of MacTab. the pMacEntry store attribute of client (STA).
+ QueIdx: Priority queue idex.
+
+ Return Value:
+ NDIS_STATUS_SUCCESS:If succes to queue the packet into TxSwQueue.
+ NDIS_STATUS_FAILURE: If failed to do en-queue.
+========================================================================
+*/
+NDIS_STATUS RtmpInsertPsQueue(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN MAC_TABLE_ENTRY *pMacEntry,
+ IN UCHAR QueIdx)
+{
+ ULONG IrqFlags;
+#ifdef UAPSD_SUPPORT
+ /* put the U-APSD packet to its U-APSD queue by AC ID */
+ UINT32 ac_id = QueIdx - QID_AC_BE; /* should be >= 0 */
+
+
+ if (UAPSD_MR_IS_UAPSD_AC(pMacEntry, ac_id))
+ {
+ UAPSD_PacketEnqueue(pAd, pMacEntry, pPacket, ac_id);
+
+ }
+ else
+#endif /* UAPSD_SUPPORT */
+ {
+ if (pMacEntry->PsQueue.Number >= MAX_PACKETS_IN_PS_QUEUE)
+ {
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ return NDIS_STATUS_FAILURE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("legacy ps> queue a packet!\n"));
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+ InsertTailQueue(&pMacEntry->PsQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+ }
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ /* mark corresponding TIM bit in outgoing BEACON frame */
+#ifdef UAPSD_SUPPORT
+ if (UAPSD_MR_IS_NOT_TIM_BIT_NEEDED_HANDLED(pMacEntry, QueIdx))
+ {
+ /* 1. the station is UAPSD station;
+ 2. one of AC is non-UAPSD (legacy) AC;
+ 3. the destinated AC of the packet is UAPSD AC. */
+ /* So we can not set TIM bit due to one of AC is legacy AC */
+ }
+ else
+#endif /* UAPSD_SUPPORT */
+ {
+ WLAN_MR_TIM_BIT_SET(pAd, pMacEntry->apidx, pMacEntry->Aid);
+
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ This routine is used to clean up a specified power-saving queue. It's
+ used whenever a wireless client is deleted.
+ ==========================================================================
+ */
+VOID RtmpCleanupPsQueue(
+ IN PRTMP_ADAPTER pAd,
+ IN PQUEUE_HEADER pQueue)
+{
+ PQUEUE_ENTRY pEntry;
+ PNDIS_PACKET pPacket;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RtmpCleanupPsQueue (0x%08lx)...\n", (ULONG)pQueue));
+
+ while (pQueue->Head)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("RtmpCleanupPsQueue %ld...\n",pQueue->Number));
+
+ pEntry = RemoveHeadQueue(pQueue);
+ /*pPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx); */
+ pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RtmpCleanupPsQueue pkt = %lx...\n", (ULONG)pPacket));
+ }
+}
+
+
+/*
+ ========================================================================
+ Description:
+ This routine frees all packets in PSQ that's destined to a specific DA.
+ BCAST/MCAST in DTIMCount=0 case is also handled here, just like a PS-POLL
+ is received from a WSTA which has MAC address FF:FF:FF:FF:FF:FF
+ ========================================================================
+*/
+VOID RtmpHandleRxPsPoll(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN USHORT Aid,
+ IN BOOLEAN isActive)
+{
+ PQUEUE_ENTRY pEntry;
+ PMAC_TABLE_ENTRY pMacEntry;
+ unsigned long IrqFlags;
+
+ /*DBGPRINT(RT_DEBUG_TRACE,("rcv PS-POLL (AID=%d) from %02x:%02x:%02x:%02x:%02x:%02x\n", */
+ /* Aid, pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5])); */
+
+ pMacEntry = &pAd->MacTab.Content[Aid];
+ if (RTMPEqualMemory(pMacEntry->Addr, pAddr, MAC_ADDR_LEN))
+ {
+ /*
+ Sta is change to Power Active stat.
+ Reset ContinueTxFailCnt
+ */
+ pMacEntry->ContinueTxFailCnt = 0;
+
+#ifdef UAPSD_SUPPORT
+ if (UAPSD_MR_IS_ALL_AC_UAPSD(isActive, pMacEntry))
+ {
+ /*
+ IEEE802.11e spec.
+ 11.2.1.7 Receive operation for STAs in PS mode during the CP
+ When a non-AP QSTA that is using U-APSD and has all ACs
+ delivery-enabled detects that the bit corresponding to its AID
+ is set in the TIM, the non-AP QSTA shall issue a trigger frame
+ or a PS-Poll frame to retrieve the buffered MSDU or management
+ frames.
+
+ WMM Spec. v1.1a 070601
+ 3.6.2 U-APSD STA Operation
+ 3.6.2.3 In case one or more ACs are not
+ delivery-enabled ACs, the WMM STA may retrieve MSDUs and
+ MMPDUs belonging to those ACs by sending PS-Polls to the WMM AP.
+ In case all ACs are delivery enabled ACs, WMM STA should only
+ use trigger frames to retrieve MSDUs and MMPDUs belonging to
+ those ACs, and it should not send PS-Poll frames.
+
+ Different definitions in IEEE802.11e and WMM spec.
+ But we follow the WiFi WMM Spec.
+ */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("All AC are UAPSD, can not use PS-Poll\n"));
+ return; /* all AC are U-APSD, can not use PS-Poll */
+ } /* End of if */
+#endif /* UAPSD_SUPPORT */
+
+ /*NdisAcquireSpinLock(&pAd->MacTabLock); */
+ /*NdisAcquireSpinLock(&pAd->TxSwQueueLock); */
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+ if (isActive == FALSE)
+ {
+ if (pMacEntry->PsQueue.Head)
+ {
+#ifdef UAPSD_SUPPORT
+ UINT32 NumOfOldPsPkt;
+ NumOfOldPsPkt = pAd->TxSwQueue[QID_AC_BE].Number;
+#endif /* UAPSD_SUPPORT */
+
+ pEntry = RemoveHeadQueue(&pMacEntry->PsQueue);
+ if ( pMacEntry->PsQueue.Number >=1 )
+ RTMP_SET_PACKET_MOREDATA(RTPKT_TO_OSPKT(pEntry), TRUE);
+ InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pEntry);
+
+#ifdef UAPSD_SUPPORT
+ /* we need to call RTMPDeQueuePacket() immediately as below */
+ if (NumOfOldPsPkt != pAd->TxSwQueue[QID_AC_BE].Number)
+ {
+ if (RTMP_GET_PACKET_DHCP(RTPKT_TO_OSPKT(pEntry)) ||
+ RTMP_GET_PACKET_EAPOL(RTPKT_TO_OSPKT(pEntry)) ||
+ RTMP_GET_PACKET_WAI(RTPKT_TO_OSPKT(pEntry)))
+ {
+ /*
+ These packets will use 1M/6M rate to send.
+ If you use 1M(2.4G)/6M(5G) to send, no statistics
+ count in NICUpdateFifoStaCounters().
+
+ So we can not count it for UAPSD; Or the SP will
+ not closed until timeout.
+ */
+ ;
+ }
+ else
+ UAPSD_MR_MIX_PS_POLL_RCV(pAd, pMacEntry);
+ }
+#endif /* UAPSD_SUPPORT */
+ }
+ else
+ {
+ /*
+ or transmit a (QoS) Null Frame;
+
+ In addtion, in Station Keep Alive mechanism, we need to
+ send a QoS Null frame to detect the station live status.
+ */
+ BOOLEAN bQosNull = FALSE;
+
+ if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
+ bQosNull = TRUE;
+
+ RtmpEnqueueNullFrame(pAd, pMacEntry->Addr, pMacEntry->CurrTxRate,
+ Aid, pMacEntry->apidx, bQosNull, TRUE, 0);
+ }
+ }
+ else
+ {
+#ifdef UAPSD_SUPPORT
+ /* deliver all queued UAPSD packets */
+ UAPSD_AllPacketDeliver(pAd, pMacEntry);
+
+ /* end the SP if exists */
+ UAPSD_MR_ENTRY_RESET(pAd, pMacEntry);
+#endif /* UAPSD_SUPPORT */
+
+ while(pMacEntry->PsQueue.Head)
+ {
+/* if (pAd->TxSwQueue[QID_AC_BE].Number <= */
+/* (pAd->PortCfg.TxQueueSize + (MAX_PACKETS_IN_PS_QUEUE>>1))) */
+ {
+ pEntry = RemoveHeadQueue(&pMacEntry->PsQueue);
+ InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pEntry);
+ }
+/* else */
+/* break; */
+ /* End of if */
+ } /* End of while */
+ } /* End of if */
+
+ /*NdisReleaseSpinLock(&pAd->TxSwQueueLock); */
+ /*NdisReleaseSpinLock(&pAd->MacTabLock); */
+
+ if ((Aid > 0) && (Aid < MAX_LEN_OF_MAC_TABLE) &&
+ (pMacEntry->PsQueue.Number == 0))
+ {
+ /* clear corresponding TIM bit because no any PS packet */
+#ifdef CONFIG_AP_SUPPORT
+ WLAN_MR_TIM_BIT_CLEAR(pAd, pMacEntry->apidx, Aid);
+#endif /* CONFIG_AP_SUPPORT */
+ pMacEntry->PsQIdleCount = 0;
+ }
+
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+
+ /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it */
+ /* TODO: 2004-12-27 it's not a good idea to handle "More Data" bit here. because the */
+ /* RTMPDeQueue process doesn't guarantee to de-queue the desired MSDU from the corresponding */
+ /* TxSwQueue/PsQueue when QOS in-used. We should consider "HardTransmt" this MPDU */
+ /* using MGMT queue or things like that. */
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("rcv PS-POLL (AID=%d not match) from %02x:%02x:%02x:%02x:%02x:%02x\n",
+ Aid, pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5]));
+
+ }
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Update the station current power save mode. Calling this routine also
+ prove the specified client is still alive. Otherwise AP will age-out
+ this client once IdleCount exceeds a threshold.
+ ==========================================================================
+ */
+BOOLEAN RtmpPsIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN ULONG Wcid,
+ IN UCHAR Psm)
+{
+ MAC_TABLE_ENTRY *pEntry;
+ UCHAR old_psmode;
+
+ if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+ {
+ return PWR_ACTIVE;
+ }
+
+ pEntry = &pAd->MacTab.Content[Wcid];
+ old_psmode = pEntry->PsMode;
+/* if (pEntry) */
+ {
+ /*
+ Change power save mode first because we will call
+ RTMPDeQueuePacket() in RtmpHandleRxPsPoll().
+
+ Or when Psm = PWR_ACTIVE, we will not do Aggregation in
+ RTMPDeQueuePacket().
+ */
+ pEntry->NoDataIdleCount = 0;
+ pEntry->PsMode = Psm;
+
+ if ((old_psmode == PWR_ACTIVE) && (Psm == PWR_SAVE))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("RtmpPsIndicate - %02x:%02x:%02x:%02x:%02x:%02x sleep!\n",
+ pAddr[0],pAddr[1],pAddr[2],pAddr[3],pAddr[4],pAddr[5]));
+ }
+
+ if ((old_psmode == PWR_SAVE) && (Psm == PWR_ACTIVE))
+ {
+ /* TODO: For RT2870, how to handle about the BA when STA in PS mode???? */
+
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("RtmpPsIndicate - %02x:%02x:%02x:%02x:%02x:%02x wakes up, "
+ "act like rx PS-POLL\n",
+ pAddr[0],pAddr[1],pAddr[2],pAddr[3],pAddr[4],pAddr[5]));
+
+ /* sleep station awakes, move all pending frames from PSQ to TXQ if any */
+ RtmpHandleRxPsPoll(pAd, pAddr, pEntry->Aid, TRUE);
+ }
+
+ /* move to above section */
+/* pEntry->NoDataIdleCount = 0; */
+/* pEntry->PsMode = Psm; */
+ }
+/* else */
+/* { */
+ /* not in table, try to learn it ???? why bother? */
+/* } */
+ return old_psmode;
+}
+
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/rt2860.bin.dfs b/cleopatre/devkit/mt7601udrv/common/rt2860.bin.dfs
new file mode 100644
index 0000000000..dcdc97bf98
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rt2860.bin.dfs
Binary files differ
diff --git a/cleopatre/devkit/mt7601udrv/common/rt2860.bin.old b/cleopatre/devkit/mt7601udrv/common/rt2860.bin.old
new file mode 100644
index 0000000000..5a058e1455
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rt2860.bin.old
Binary files differ
diff --git a/cleopatre/devkit/mt7601udrv/common/rt2870_wow.bin b/cleopatre/devkit/mt7601udrv/common/rt2870_wow.bin
new file mode 100644
index 0000000000..bfae0f0ab0
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rt2870_wow.bin
Binary files differ
diff --git a/cleopatre/devkit/mt7601udrv/common/rt_channel.c b/cleopatre/devkit/mt7601udrv/common/rt_channel.c
new file mode 100644
index 0000000000..52b241bf29
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rt_channel.c
@@ -0,0 +1,2057 @@
+/*
+
+*/
+#include "rt_config.h"
+
+
+CH_FREQ_MAP CH_HZ_ID_MAP[]=
+ {
+ {1, 2412},
+ {2, 2417},
+ {3, 2422},
+ {4, 2427},
+ {5, 2432},
+ {6, 2437},
+ {7, 2442},
+ {8, 2447},
+ {9, 2452},
+ {10, 2457},
+ {11, 2462},
+ {12, 2467},
+ {13, 2472},
+ {14, 2484},
+
+ /* UNII */
+ {36, 5180},
+ {40, 5200},
+ {44, 5220},
+ {48, 5240},
+ {52, 5260},
+ {56, 5280},
+ {60, 5300},
+ {64, 5320},
+ {149, 5745},
+ {153, 5765},
+ {157, 5785},
+ {161, 5805},
+ {165, 5825},
+ {167, 5835},
+ {169, 5845},
+ {171, 5855},
+ {173, 5865},
+
+ /* HiperLAN2 */
+ {100, 5500},
+ {104, 5520},
+ {108, 5540},
+ {112, 5560},
+ {116, 5580},
+ {120, 5600},
+ {124, 5620},
+ {128, 5640},
+ {132, 5660},
+ {136, 5680},
+ {140, 5700},
+
+ /* Japan MMAC */
+ {34, 5170},
+ {38, 5190},
+ {42, 5210},
+ {46, 5230},
+
+ /* Japan */
+ {184, 4920},
+ {188, 4940},
+ {192, 4960},
+ {196, 4980},
+
+ {208, 5040}, /* Japan, means J08 */
+ {212, 5060}, /* Japan, means J12 */
+ {216, 5080}, /* Japan, means J16 */
+};
+
+INT CH_HZ_ID_MAP_NUM = (sizeof(CH_HZ_ID_MAP)/sizeof(CH_FREQ_MAP));
+
+CH_DESC Country_Region0_ChDesc_2GHZ[] =
+{
+ {1, 11, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region1_ChDesc_2GHZ[] =
+{
+ {1, 13, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region2_ChDesc_2GHZ[] =
+{
+ {10, 2, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region3_ChDesc_2GHZ[] =
+{
+ {10, 4, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region4_ChDesc_2GHZ[] =
+{
+ {14, 1, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region5_ChDesc_2GHZ[] =
+{
+ {1, 14, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region6_ChDesc_2GHZ[] =
+{
+ {3, 7, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region7_ChDesc_2GHZ[] =
+{
+ {5, 9, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region31_ChDesc_2GHZ[] =
+{
+ {1, 11, CHANNEL_DEFAULT_PROP},
+ {12, 3, CHANNEL_PASSIVE_SCAN},
+ {}
+};
+
+CH_DESC Country_Region32_ChDesc_2GHZ[] =
+{
+ {1, 11, CHANNEL_DEFAULT_PROP},
+ {12, 2, CHANNEL_PASSIVE_SCAN},
+ {}
+};
+
+CH_DESC Country_Region33_ChDesc_2GHZ[] =
+{
+ {1, 14, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+COUNTRY_REGION_CH_DESC Country_Region_ChDesc_2GHZ[] =
+{
+ {REGION_0_BG_BAND, Country_Region0_ChDesc_2GHZ},
+ {REGION_1_BG_BAND, Country_Region1_ChDesc_2GHZ},
+ {REGION_2_BG_BAND, Country_Region2_ChDesc_2GHZ},
+ {REGION_3_BG_BAND, Country_Region3_ChDesc_2GHZ},
+ {REGION_4_BG_BAND, Country_Region4_ChDesc_2GHZ},
+ {REGION_5_BG_BAND, Country_Region5_ChDesc_2GHZ},
+ {REGION_6_BG_BAND, Country_Region6_ChDesc_2GHZ},
+ {REGION_7_BG_BAND, Country_Region7_ChDesc_2GHZ},
+ {REGION_31_BG_BAND, Country_Region31_ChDesc_2GHZ},
+ {REGION_32_BG_BAND, Country_Region32_ChDesc_2GHZ},
+ {REGION_33_BG_BAND, Country_Region33_ChDesc_2GHZ},
+ {}
+};
+
+UINT16 const Country_Region_GroupNum_2GHZ = sizeof(Country_Region_ChDesc_2GHZ) / sizeof(COUNTRY_REGION_CH_DESC);
+
+CH_DESC Country_Region0_ChDesc_5GHZ[] =
+{
+ {36, 8, CHANNEL_DEFAULT_PROP},
+ {149, 5, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region1_ChDesc_5GHZ[] =
+{
+ {36, 8, CHANNEL_DEFAULT_PROP},
+ {100, 11, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region2_ChDesc_5GHZ[] =
+{
+ {36, 8, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region3_ChDesc_5GHZ[] =
+{
+ {52, 4, CHANNEL_DEFAULT_PROP},
+ {149, 4, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region4_ChDesc_5GHZ[] =
+{
+ {149, 5, CHANNEL_DEFAULT_PROP},
+ {}
+};
+CH_DESC Country_Region5_ChDesc_5GHZ[] =
+{
+ {149, 4, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region6_ChDesc_5GHZ[] =
+{
+ {36, 4, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region7_ChDesc_5GHZ[] =
+{
+ {36, 8, CHANNEL_DEFAULT_PROP},
+ {100, 11, CHANNEL_DEFAULT_PROP},
+ {149, 7, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region8_ChDesc_5GHZ[] =
+{
+ {52, 4, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region9_ChDesc_5GHZ[] =
+{
+ {36, 8 , CHANNEL_DEFAULT_PROP},
+ {100, 5, CHANNEL_DEFAULT_PROP},
+ {132, 3, CHANNEL_DEFAULT_PROP},
+ {149, 5, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region10_ChDesc_5GHZ[] =
+{
+ {36,4, CHANNEL_DEFAULT_PROP},
+ {149, 5, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region11_ChDesc_5GHZ[] =
+{
+ {36, 8, CHANNEL_DEFAULT_PROP},
+ {100, 6, CHANNEL_DEFAULT_PROP},
+ {149, 4, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region12_ChDesc_5GHZ[] =
+{
+ {36, 8, CHANNEL_DEFAULT_PROP},
+ {100, 11, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region13_ChDesc_5GHZ[] =
+{
+ {52, 4, CHANNEL_DEFAULT_PROP},
+ {100, 11, CHANNEL_DEFAULT_PROP},
+ {149, 4, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region14_ChDesc_5GHZ[] =
+{
+ {36, 8, CHANNEL_DEFAULT_PROP},
+ {100, 5, CHANNEL_DEFAULT_PROP},
+ {136, 2, CHANNEL_DEFAULT_PROP},
+ {149, 5, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region15_ChDesc_5GHZ[] =
+{
+ {149, 7, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region16_ChDesc_5GHZ[] =
+{
+ {52, 4, CHANNEL_DEFAULT_PROP},
+ {149, 5, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region17_ChDesc_5GHZ[] =
+{
+ {36, 4, CHANNEL_DEFAULT_PROP},
+ {149, 4, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region18_ChDesc_5GHZ[] =
+{
+ {36, 8, CHANNEL_DEFAULT_PROP},
+ {100, 5, CHANNEL_DEFAULT_PROP},
+ {132, 3, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region19_ChDesc_5GHZ[] =
+{
+ {56, 3, CHANNEL_DEFAULT_PROP},
+ {100, 11, CHANNEL_DEFAULT_PROP},
+ {149, 4, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region20_ChDesc_5GHZ[] =
+{
+ {36, 8, CHANNEL_DEFAULT_PROP},
+ {100, 7, CHANNEL_DEFAULT_PROP},
+ {149, 4, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+CH_DESC Country_Region21_ChDesc_5GHZ[] =
+{
+ {36, 8, CHANNEL_DEFAULT_PROP},
+ {100, 11, CHANNEL_DEFAULT_PROP},
+ {149, 4, CHANNEL_DEFAULT_PROP},
+ {}
+};
+
+
+COUNTRY_REGION_CH_DESC Country_Region_ChDesc_5GHZ[] =
+{
+ {REGION_0_A_BAND, Country_Region0_ChDesc_5GHZ},
+ {REGION_1_A_BAND, Country_Region1_ChDesc_5GHZ},
+ {REGION_2_A_BAND, Country_Region2_ChDesc_5GHZ},
+ {REGION_3_A_BAND, Country_Region3_ChDesc_5GHZ},
+ {REGION_4_A_BAND, Country_Region4_ChDesc_5GHZ},
+ {REGION_5_A_BAND, Country_Region5_ChDesc_5GHZ},
+ {REGION_6_A_BAND, Country_Region6_ChDesc_5GHZ},
+ {REGION_7_A_BAND, Country_Region7_ChDesc_5GHZ},
+ {REGION_8_A_BAND, Country_Region8_ChDesc_5GHZ},
+ {REGION_9_A_BAND, Country_Region9_ChDesc_5GHZ},
+ {REGION_10_A_BAND, Country_Region10_ChDesc_5GHZ},
+ {REGION_11_A_BAND, Country_Region11_ChDesc_5GHZ},
+ {REGION_12_A_BAND, Country_Region12_ChDesc_5GHZ},
+ {REGION_13_A_BAND, Country_Region13_ChDesc_5GHZ},
+ {REGION_14_A_BAND, Country_Region14_ChDesc_5GHZ},
+ {REGION_15_A_BAND, Country_Region15_ChDesc_5GHZ},
+ {REGION_16_A_BAND, Country_Region16_ChDesc_5GHZ},
+ {REGION_17_A_BAND, Country_Region17_ChDesc_5GHZ},
+ {REGION_18_A_BAND, Country_Region18_ChDesc_5GHZ},
+ {REGION_19_A_BAND, Country_Region19_ChDesc_5GHZ},
+ {REGION_20_A_BAND, Country_Region20_ChDesc_5GHZ},
+ {REGION_21_A_BAND, Country_Region21_ChDesc_5GHZ},
+ {}
+};
+
+UINT16 const Country_Region_GroupNum_5GHZ = sizeof(Country_Region_ChDesc_5GHZ) / sizeof(COUNTRY_REGION_CH_DESC);
+
+UINT16 TotalChNum(PCH_DESC pChDesc)
+{
+ UINT16 TotalChNum = 0;
+
+ while(pChDesc->FirstChannel)
+ {
+ TotalChNum += pChDesc->NumOfCh;
+ pChDesc++;
+ }
+
+ return TotalChNum;
+}
+
+UCHAR GetChannel_5GHZ(PCH_DESC pChDesc, UCHAR index)
+{
+ while (pChDesc->FirstChannel)
+ {
+ if (index < pChDesc->NumOfCh)
+ return pChDesc->FirstChannel + index * 4;
+ else
+ {
+ index -= pChDesc->NumOfCh;
+ pChDesc++;
+ }
+ }
+
+ return 0;
+}
+
+UCHAR GetChannel_2GHZ(PCH_DESC pChDesc, UCHAR index)
+{
+
+ while (pChDesc->FirstChannel)
+ {
+ if (index < pChDesc->NumOfCh)
+ return pChDesc->FirstChannel + index;
+ else
+ {
+ index -= pChDesc->NumOfCh;
+ pChDesc++;
+ }
+ }
+
+ return 0;
+}
+
+UCHAR GetChannelFlag(PCH_DESC pChDesc, UCHAR index)
+{
+
+ while (pChDesc->FirstChannel)
+ {
+ if (index < pChDesc->NumOfCh)
+ return pChDesc->ChannelProp;
+ else
+ {
+ index -= pChDesc->NumOfCh;
+ pChDesc++;
+ }
+ }
+
+ return 0;
+}
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+
+/*Albania*/
+CH_DESP Country_AL_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Algeria*/
+CH_DESP Country_DZ_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Argentina*/
+CH_DESP Country_AR_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Armenia*/
+CH_DESP Country_AM_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 18, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 18, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Aruba*/
+CH_DESP Country_AW_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Australia*/
+CH_DESP Country_AU_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 23, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Austria*/
+CH_DESP Country_AT_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Azerbaijan*/
+CH_DESP Country_AZ_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 18, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 18, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Bahrain*/
+CH_DESP Country_BH_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 149, 5, 20, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Bangladesh*/
+CH_DESP Country_BD_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Barbados*/
+CH_DESP Country_BB_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 23, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Belarus*/
+CH_DESP Country_BY_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Belgium*/
+CH_DESP Country_BE_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Belize*/
+CH_DESP Country_BZ_ChDesp[] =
+{
+ { 1, 13, 30, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Bolivia*/
+CH_DESP Country_BO_ChDesp[] =
+{
+ { 1, 13, 30, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Bosnia and Herzegovina*/
+CH_DESP Country_BA_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Brazil*/
+CH_DESP Country_BR_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Brunei Darussalam*/
+CH_DESP Country_BN_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Bulgaria*/
+CH_DESP Country_BG_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 23, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 2, 23, BOTH, TRUE}, /*5250~5290MHz, Ch 52~56, Max BW: 40 */
+ { 100, 11, 30, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Cambodia*/
+CH_DESP Country_KH_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Canada*/
+CH_DESP Country_CA_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */
+ { 36, 4, 17, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Chile*/
+CH_DESP Country_CL_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 20, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*China*/
+CH_DESP Country_CN_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Colombia*/
+CH_DESP Country_CO_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Costa Rica*/
+CH_DESP Country_CR_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Croatia*/
+CH_DESP Country_HR_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Cyprus*/
+CH_DESP Country_CY_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Czech Republic*/
+CH_DESP Country_CZ_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2400~2483.5MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 23, IDOR, FALSE}, /*5150~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5350MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5470~5725MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Denmark*/
+CH_DESP Country_DK_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Dominican Republic*/
+CH_DESP Country_DO_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Ecuador*/
+CH_DESP Country_EC_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Egypt*/
+CH_DESP Country_EG_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*El Salvador*/
+CH_DESP Country_SV_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Estonia*/
+CH_DESP Country_EE_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Finland*/
+CH_DESP Country_FI_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*France*/
+CH_DESP Country_FR_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Georgia*/
+CH_DESP Country_GE_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 18, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 18, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Germany*/
+CH_DESP Country_DE_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2400~2483.5MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, IDOR, FALSE}, /*5150~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5350MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5470~5725MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Greece*/
+CH_DESP Country_GR_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Greenland*/
+CH_DESP Country_GL_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Grenada*/
+CH_DESP Country_GD_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Guam*/
+CH_DESP Country_GU_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Guatemala*/
+CH_DESP Country_GT_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Haiti*/
+CH_DESP Country_HT_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Honduras*/
+CH_DESP Country_HN_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Hong Kong*/
+CH_DESP Country_HK_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Hungary*/
+CH_DESP Country_HU_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Iceland*/
+CH_DESP Country_IS_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*India*/
+CH_DESP Country_IN_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 20, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Indonesia*/
+CH_DESP Country_ID_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Iran, Islamic Republic of*/
+CH_DESP Country_IR_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Ireland*/
+CH_DESP Country_IE_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Israel*/
+CH_DESP Country_IL_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 23, IDOR, FALSE}, /*5150~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 23, IDOR, TRUE}, /*5250~5350MHz, Ch 52~64, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Italy*/
+CH_DESP Country_IT_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Jamaica*/
+CH_DESP Country_JM_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Japan*/
+CH_DESP Country_JP_ChDesp[] =
+{
+ { 1, 14, 20, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 20 */
+ /*2457~2482MHz, Ch10~13, Max BW: 20 */
+ /*2474~2494MHz, Ch14, Max BW: 20, No OFDM */
+ { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 23, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Jordan*/
+CH_DESP Country_JO_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 18, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Kazakhstan*/
+CH_DESP Country_KZ_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Kenya*/
+CH_DESP Country_KE_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Korea, Democratic People's Republic of*/
+CH_DESP Country_KP_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, TRUE}, /*5160~5250MHz, Ch 36~48, Max BW: 40 */
+ { 36, 8, 20, BOTH, FALSE}, /*5170~5330MHz, Ch 36~64, Max BW: 40 */
+ { 100, 7, 30, BOTH, TRUE}, /*5490~5630MHz, Ch 100~124, Max BW: 40 */
+ { 149, 4, 30, BOTH, FALSE}, /*5735~5815MHz, Ch 149~161, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Korea, Republic of*/
+CH_DESP Country_KR_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 20 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 100, 7, 30, BOTH, TRUE}, /*5490~5630MHz, Ch 100~124, Max BW: 40 */
+ { 149, 4, 30, BOTH, FALSE}, /*5735~5815MHz, Ch 149~161, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Kuwait*/
+CH_DESP Country_KW_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Latvia*/
+CH_DESP Country_LV_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Lebanon*/
+CH_DESP Country_LB_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Liechtenstein*/
+CH_DESP Country_LI_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Lithuania*/
+CH_DESP Country_LT_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Luxembourg*/
+CH_DESP Country_LU_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Macao*/
+CH_DESP Country_MO_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 23, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Macedonia, Republic of*/
+CH_DESP Country_MK_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Malaysia*/
+CH_DESP Country_MY_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 52, 4, 30, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Malta*/
+CH_DESP Country_MT_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Mexico*/
+CH_DESP Country_MX_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Monaco*/
+CH_DESP Country_MC_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 18, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 18, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Morocco*/
+CH_DESP Country_MA_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Nepal*/
+CH_DESP Country_NP_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Netherlands*/
+CH_DESP Country_NL_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Netherlands Antilles*/
+CH_DESP Country_AN_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*New Zealand*/
+CH_DESP Country_NZ_ChDesp[] =
+{
+ { 1, 13, 30, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 23, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Norway*/
+CH_DESP Country_NO_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Oman*/
+CH_DESP Country_OM_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Pakistan*/
+CH_DESP Country_PK_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Panama*/
+CH_DESP Country_PA_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Papua New Guinea*/
+CH_DESP Country_PG_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Peru*/
+CH_DESP Country_PE_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Philippines*/
+CH_DESP Country_PH_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Poland*/
+CH_DESP Country_PL_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Portuga*/
+CH_DESP Country_PT_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Puerto Rico*/
+CH_DESP Country_PR_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Qatar*/
+CH_DESP Country_QA_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Romania*/
+CH_DESP Country_RO_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Russian Federation*/
+CH_DESP Country_RU_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Saint Barth'elemy*/
+CH_DESP Country_BL_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 18, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 18, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Saudi Arabia*/
+CH_DESP Country_SA_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 23, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 23, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Singapore*/
+CH_DESP Country_SG_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 149, 5, 20, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Slovakia*/
+CH_DESP Country_SK_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Slovenia*/
+CH_DESP Country_SI_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*South Africa*/
+CH_DESP Country_ZA_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Spain*/
+CH_DESP Country_ES_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Sri Lanka*/
+CH_DESP Country_LK_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 20 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Sweden*/
+CH_DESP Country_SE_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Switzerland*/
+CH_DESP Country_CH_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Syrian Arab Republic*/
+CH_DESP Country_SY_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Taiwan*/
+CH_DESP Country_TW_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */
+ { 56, 3, 17, IDOR, TRUE}, /*5270~5330MHz, Ch 56~64, Max BW: 40 */
+ { 149, 4, 30, BOTH, FALSE}, /*5735~5815MHz, Ch 149~161, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Thailand*/
+CH_DESP Country_TH_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Trinidad and Tobago*/
+CH_DESP Country_TT_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Tunisia*/
+CH_DESP Country_TN_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Turkey*/
+CH_DESP Country_TR_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 20 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 20 */
+ { 0}, /* end*/
+};
+/*Ukraine*/
+CH_DESP Country_UA_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*United Arab Emirates*/
+CH_DESP Country_AE_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*United Kingdom*/
+CH_DESP Country_GB_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, IDOR, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 27, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*United States*/
+CH_DESP Country_US_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */
+ { 36, 4, 17, IDOR, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 5, 20, BOTH, TRUE}, /*5490~5600MHz, Ch 100~116, Max BW: 40 */
+ { 132, 3, 20, BOTH, TRUE}, /*5650~5710MHz, Ch 132~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Uruguay*/
+CH_DESP Country_UY_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Uzbekistan*/
+CH_DESP Country_UZ_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /*2402~2472MHz, Ch 1~11, Max BW: 40 */
+ { 36, 4, 17, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 100, 11, 20, BOTH, TRUE}, /*5490~5710MHz, Ch 100~140, Max BW: 40 */
+ { 149, 5, 30, BOTH, FALSE}, /*5735~5835MHz, Ch 149~165, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Venezuela*/
+CH_DESP Country_VE_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 149, 4, 23, BOTH, FALSE}, /*5735~5815MHz, Ch 149~161, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Viet Nam*/
+CH_DESP Country_VN_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 36, 4, 20, BOTH, FALSE}, /*5170~5250MHz, Ch 36~48, Max BW: 40 */
+ { 52, 4, 20, BOTH, TRUE}, /*5250~5330MHz, Ch 52~64, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Yemen*/
+CH_DESP Country_YE_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 0}, /* end*/
+};
+/*Zimbabwe*/
+CH_DESP Country_ZW_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /*2402~2482MHz, Ch 1~13, Max BW: 40 */
+ { 0}, /* end*/
+};
+
+/* Group Region */
+/*Europe*/
+CH_DESP Country_EU_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /* 2.4 G, ch 1~13 */
+ { 36, 4, 17, BOTH, FALSE}, /* 5G band 1, ch 36~48*/
+ { 0}, /* end*/
+};
+/*North America*/
+CH_DESP Country_NA_ChDesp[] =
+{
+ { 1, 11, 27, BOTH, FALSE}, /* 2.4 G, ch 1~11*/
+ { 36, 4, 17, IDOR, FALSE}, /* 5G band 1, ch 36~48*/
+ { 149, 5, 30, BOTH, FALSE}, /* 5G band 4, ch 149~165*/
+ { 0}, /* end*/
+};
+/*World Wide*/
+CH_DESP Country_WO_ChDesp[] =
+{
+ { 1, 13, 20, BOTH, FALSE}, /* 2.4 G, ch 1~13*/
+ { 36, 4, 17, BOTH, FALSE}, /* 5G band 1, ch 36~48*/
+ { 149, 5, 22, BOTH, FALSE}, /* 5G band 4, ch 149~165*/
+ { 0}, /* end*/
+};
+
+CH_REGION ChRegion[] =
+{
+ {"AL", CE, Country_AL_ChDesp}, /* Albania */
+ {"DZ", CE, Country_DZ_ChDesp}, /* Algeria */
+ {"AR", CE, Country_AR_ChDesp}, /* Argentina */
+ {"AM", CE, Country_AM_ChDesp}, /* Armenia */
+ {"AW", CE, Country_AW_ChDesp}, /* Aruba */
+ {"AU", CE, Country_AU_ChDesp}, /* Australia */
+ {"AT", CE, Country_AT_ChDesp}, /* Austria */
+ {"AZ", CE, Country_AZ_ChDesp}, /* Azerbaijan */
+ {"BH", CE, Country_BH_ChDesp}, /* Bahrain */
+ {"BD", CE, Country_BD_ChDesp}, /* Bangladesh */
+ {"BB", CE, Country_BB_ChDesp}, /* Barbados */
+ {"BY", CE, Country_BY_ChDesp}, /* Belarus */
+ {"BE", CE, Country_BE_ChDesp}, /* Belgium */
+ {"BZ", CE, Country_BZ_ChDesp}, /* Belize */
+ {"BO", CE, Country_BO_ChDesp}, /* Bolivia */
+ {"BA", CE, Country_BA_ChDesp}, /* Bosnia and Herzegovina */
+ {"BR", CE, Country_BR_ChDesp}, /* Brazil */
+ {"BN", CE, Country_BN_ChDesp}, /* Brunei Darussalam */
+ {"BG", CE, Country_BG_ChDesp}, /* Bulgaria */
+ {"KH", CE, Country_KH_ChDesp}, /* Cambodia */
+ {"CA", FCC,Country_CA_ChDesp}, /* Canada */
+ {"CL", CE, Country_CL_ChDesp}, /* Chile */
+ {"CN", CE, Country_CN_ChDesp}, /* China */
+ {"CO", CE, Country_CO_ChDesp}, /* Colombia */
+ {"CR", CE, Country_CR_ChDesp}, /* Costa Rica */
+ {"HR", CE, Country_HR_ChDesp}, /* Croatia */
+ {"CY", CE, Country_CY_ChDesp}, /* Cyprus */
+ {"CZ", CE, Country_CZ_ChDesp}, /* Czech Republic */
+ {"DK", CE, Country_DK_ChDesp}, /* Denmark */
+ {"DO", CE, Country_DO_ChDesp}, /* Dominican Republic */
+ {"EC", CE, Country_EC_ChDesp}, /* Ecuador */
+ {"EG", CE, Country_EG_ChDesp}, /* Egypt */
+ {"SV", CE, Country_SV_ChDesp}, /* El Salvador */
+ {"EE", CE, Country_EE_ChDesp}, /* Estonia */
+ {"FI", CE, Country_FI_ChDesp}, /* Finland */
+ {"FR", CE, Country_FR_ChDesp}, /* France */
+ {"GE", CE, Country_GE_ChDesp}, /* Georgia */
+ {"DE", CE, Country_DE_ChDesp}, /* Germany */
+ {"GR", CE, Country_GR_ChDesp}, /* Greece */
+ {"GL", CE, Country_GL_ChDesp}, /* Greenland */
+ {"GD", CE, Country_GD_ChDesp}, /* Grenada */
+ {"GU", CE, Country_GU_ChDesp}, /* Guam */
+ {"GT", CE, Country_GT_ChDesp}, /* Guatemala */
+ {"HT", CE, Country_HT_ChDesp}, /* Haiti */
+ {"HN", CE, Country_HN_ChDesp}, /* Honduras */
+ {"HK", CE, Country_HK_ChDesp}, /* Hong Kong */
+ {"HU", CE, Country_HU_ChDesp}, /* Hungary */
+ {"IS", CE, Country_IS_ChDesp}, /* Iceland */
+ {"IN", CE, Country_IN_ChDesp}, /* India */
+ {"ID", CE, Country_ID_ChDesp}, /* Indonesia */
+ {"IR", CE, Country_IR_ChDesp}, /* Iran, Islamic Republic of */
+ {"IE", CE, Country_IE_ChDesp}, /* Ireland */
+ {"IL", CE, Country_IL_ChDesp}, /* Israel */
+ {"IT", CE, Country_IT_ChDesp}, /* Italy */
+ {"JM", CE, Country_JM_ChDesp}, /* Jamaica */
+ {"JP", JAP,Country_JP_ChDesp}, /* Japan */
+ {"JO", CE, Country_JO_ChDesp}, /* Jordan */
+ {"KZ", CE, Country_KZ_ChDesp}, /* Kazakhstan */
+ {"KE", CE, Country_KE_ChDesp}, /* Kenya */
+ {"KP", CE, Country_KP_ChDesp}, /* Korea, Democratic People's Republic of */
+ {"KR", CE, Country_KR_ChDesp}, /* Korea, Republic of */
+ {"KW", CE, Country_KW_ChDesp}, /* Kuwait */
+ {"LV", CE, Country_LV_ChDesp}, /* Latvia */
+ {"LB", CE, Country_LB_ChDesp}, /* Lebanon */
+ {"LI", CE, Country_LI_ChDesp}, /* Liechtenstein */
+ {"LT", CE, Country_LT_ChDesp}, /* Lithuania */
+ {"LU", CE, Country_LU_ChDesp}, /* Luxembourg */
+ {"MO", CE, Country_MO_ChDesp}, /* Macao */
+ {"MK", CE, Country_MK_ChDesp}, /* Macedonia, Republic of */
+ {"MY", CE, Country_MY_ChDesp}, /* Malaysia */
+ {"MT", CE, Country_MT_ChDesp}, /* Malta */
+ {"MX", CE, Country_MX_ChDesp}, /* Mexico */
+ {"MC", CE, Country_MC_ChDesp}, /* Monaco */
+ {"MA", CE, Country_MA_ChDesp}, /* Morocco */
+ {"NP", CE, Country_NP_ChDesp}, /* Nepal */
+ {"NL", CE, Country_NL_ChDesp}, /* Netherlands */
+ {"AN", CE, Country_AN_ChDesp}, /* Netherlands Antilles */
+ {"NZ", CE, Country_NZ_ChDesp}, /* New Zealand */
+ {"NO", CE, Country_NO_ChDesp}, /* Norway */
+ {"OM", CE, Country_OM_ChDesp}, /* Oman */
+ {"PK", CE, Country_PK_ChDesp}, /* Pakistan */
+ {"PA", CE, Country_PA_ChDesp}, /* Panama */
+ {"PG", CE, Country_PG_ChDesp}, /* Papua New Guinea */
+ {"PE", CE, Country_PE_ChDesp}, /* Peru */
+ {"PH", CE, Country_PH_ChDesp}, /* Philippines */
+ {"PL", CE, Country_PL_ChDesp}, /* Poland */
+ {"PT", CE, Country_PT_ChDesp}, /* Portuga l*/
+ {"PR", CE, Country_PR_ChDesp}, /* Puerto Rico */
+ {"QA", CE, Country_QA_ChDesp}, /* Qatar */
+ {"RO", CE, Country_RO_ChDesp}, /* Romania */
+ {"RU", CE, Country_RU_ChDesp}, /* Russian Federation */
+ {"BL", CE, Country_BL_ChDesp}, /* Saint Barth'elemy */
+ {"SA", CE, Country_SA_ChDesp}, /* Saudi Arabia */
+ {"SG", CE, Country_SG_ChDesp}, /* Singapore */
+ {"SK", CE, Country_SK_ChDesp}, /* Slovakia */
+ {"SI", CE, Country_SI_ChDesp}, /* Slovenia */
+ {"ZA", CE, Country_ZA_ChDesp}, /* South Africa */
+ {"ES", CE, Country_ES_ChDesp}, /* Spain */
+ {"LK", CE, Country_LK_ChDesp}, /* Sri Lanka */
+ {"SE", CE, Country_SE_ChDesp}, /* Sweden */
+ {"CH", CE, Country_CH_ChDesp}, /* Switzerland */
+ {"SY", CE, Country_SY_ChDesp}, /* Syrian Arab Republic */
+ {"TW", FCC,Country_TW_ChDesp}, /* Taiwan */
+ {"TH", CE, Country_TH_ChDesp}, /* Thailand */
+ {"TT", CE, Country_TT_ChDesp}, /* Trinidad and Tobago */
+ {"TN", CE, Country_TN_ChDesp}, /* Tunisia */
+ {"TR", CE, Country_TR_ChDesp}, /* Turkey */
+ {"UA", CE, Country_UA_ChDesp}, /* Ukraine */
+ {"AE", CE, Country_AE_ChDesp}, /* United Arab Emirates */
+ {"GB", CE, Country_GB_ChDesp}, /* United Kingdom */
+ {"US", FCC,Country_US_ChDesp}, /* United States */
+ {"UY", CE, Country_UY_ChDesp}, /* Uruguay */
+ {"UZ", CE, Country_UZ_ChDesp}, /* Uzbekistan */
+ {"VE", CE, Country_VE_ChDesp}, /* Venezuela */
+ {"VN", CE, Country_VN_ChDesp}, /* Viet Nam */
+ {"YE", CE, Country_YE_ChDesp}, /* Yemen */
+ {"ZW", CE, Country_ZW_ChDesp}, /* Zimbabwe */
+ {"EU", CE, Country_EU_ChDesp}, /* Europe */
+ {"NA", FCC,Country_NA_ChDesp}, /* North America */
+ {"WO", CE, Country_WO_ChDesp}, /* World Wide */
+ {"" , 0, NULL} , /* End */
+};
+
+static PCH_REGION GetChRegion(
+ IN PUCHAR CntryCode)
+{
+ INT loop = 0;
+ PCH_REGION pChRegion = NULL;
+
+ while (strcmp((PSTRING) ChRegion[loop].CountReg, "") != 0)
+ {
+ if (strncmp((PSTRING) ChRegion[loop].CountReg, (PSTRING) CntryCode, 2) == 0)
+ {
+ pChRegion = &ChRegion[loop];
+ break;
+ }
+ loop++;
+ }
+
+ /* Default: use WO*/
+ if (pChRegion == NULL)
+ pChRegion = GetChRegion("WO");
+
+ return pChRegion;
+}
+
+static VOID ChBandCheck(
+ IN UCHAR PhyMode,
+ OUT PUCHAR pChType)
+{
+ *pChType = 0;
+ if (WMODE_CAP_5G(PhyMode))
+ *pChType |= BAND_5G;
+ if (WMODE_CAP_2G(PhyMode))
+ *pChType |= BAND_24G;
+
+ if (*pChType == 0)
+ *pChType = BAND_24G;
+}
+
+static UCHAR FillChList(
+ IN PRTMP_ADAPTER pAd,
+ IN PCH_DESP pChDesp,
+ IN UCHAR Offset,
+ IN UCHAR increment,
+ IN UCHAR regulatoryDomain)
+{
+ INT i, j, l;
+ UCHAR channel;
+
+ j = Offset;
+ for (i = 0; i < pChDesp->NumOfCh; i++)
+ {
+ channel = pChDesp->FirstChannel + i * increment;
+ if (!strncmp((PSTRING) pAd->CommonCfg.CountryCode, "JP", 2))
+ {
+ /* for JP, ch14 can only be used when PhyMode is "B only" */
+ if ( (channel==14) &&
+ (!WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)))
+ {
+ pChDesp->NumOfCh--;
+ break;
+ }
+ }
+/*New FCC spec restrict the used channel under DFS */
+#ifdef CONFIG_AP_SUPPORT
+ if ((pAd->CommonCfg.bIEEE80211H == 1) &&
+ (pAd->CommonCfg.RDDurRegion == FCC) &&
+ (pAd->Dot11_H.bDFSIndoor == 1))
+ {
+ if (RESTRICTION_BAND_1(pAd))
+ continue;
+ }
+ else if ((pAd->CommonCfg.bIEEE80211H == 1) &&
+ (pAd->CommonCfg.RDDurRegion == FCC) &&
+ (pAd->Dot11_H.bDFSIndoor == 0))
+ {
+ if ((channel >= 100) && (channel <= 140))
+ continue;
+ }
+
+#endif /* CONFIG_AP_SUPPORT */
+ for (l=0; l<MAX_NUM_OF_CHANNELS; l++)
+ {
+ if (channel == pAd->TxPower[l].Channel)
+ {
+ pAd->ChannelList[j].Power = pAd->TxPower[l].Power;
+ pAd->ChannelList[j].Power2 = pAd->TxPower[l].Power2;
+#ifdef DOT11N_SS3_SUPPORT
+ pAd->ChannelList[j].Power3 = pAd->TxPower[l].Power3;
+#endif /* DOT11N_SS3_SUPPORT */
+ break;
+ }
+ }
+ if (l == MAX_NUM_OF_CHANNELS)
+ continue;
+
+ pAd->ChannelList[j].Channel = pChDesp->FirstChannel + i * increment;
+ pAd->ChannelList[j].MaxTxPwr = pChDesp->MaxTxPwr;
+ pAd->ChannelList[j].DfsReq = pChDesp->DfsReq;
+ pAd->ChannelList[j].RegulatoryDomain = regulatoryDomain;
+#ifdef DOT11_N_SUPPORT
+ if (N_ChannelGroupCheck(pAd, pAd->ChannelList[j].Channel))
+ pAd->ChannelList[j].Flags |= CHANNEL_40M_CAP;
+#endif /* DOT11_N_SUPPORT */
+
+#ifdef RT_CFG80211_SUPPORT
+ CFG80211OS_ChanInfoInit(
+ pAd->pCfg80211_CB,
+ j,
+ pAd->ChannelList[j].Channel,
+ pAd->ChannelList[j].MaxTxPwr,
+ WMODE_CAP_N(pAd->CommonCfg.PhyMode),
+ (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20));
+#endif /* RT_CFG80211_SUPPORT */
+
+ j++;
+ }
+ pAd->ChannelListNum = j;
+
+ return j;
+}
+
+
+static inline VOID CreateChList(
+ IN PRTMP_ADAPTER pAd,
+ IN PCH_REGION pChRegion,
+ IN UCHAR Geography)
+{
+ INT i;
+ UCHAR offset = 0;
+ PCH_DESP pChDesp;
+ UCHAR ChType;
+ UCHAR increment;
+ UCHAR regulatoryDomain;
+
+ if (pChRegion == NULL)
+ return;
+
+ ChBandCheck(pAd->CommonCfg.PhyMode, &ChType);
+
+ if (pAd->CommonCfg.pChDesp != NULL)
+ pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp;
+ else
+ pChDesp = pChRegion->pChDesp;
+
+ for (i = 0; pChDesp[i].FirstChannel != 0; i++)
+ {
+ if (pChDesp[i].FirstChannel == 0)
+ break;
+
+ if (ChType == BAND_5G)
+ {
+ if (pChDesp[i].FirstChannel <= 14)
+ continue;
+ }
+ else if (ChType == BAND_24G)
+ {
+ if (pChDesp[i].FirstChannel > 14)
+ continue;
+ }
+
+ if ((pChDesp[i].Geography == BOTH)
+ || (Geography == BOTH)
+ || (pChDesp[i].Geography == Geography))
+ {
+ if (pChDesp[i].FirstChannel > 14)
+ increment = 4;
+ else
+ increment = 1;
+ if (pAd->CommonCfg.DfsType != MAX_RD_REGION)
+ regulatoryDomain = pAd->CommonCfg.DfsType;
+ else
+ regulatoryDomain = pChRegion->DfsType;
+ offset = FillChList(pAd, &pChDesp[i], offset, increment, regulatoryDomain);
+ }
+ }
+}
+
+
+VOID BuildChannelListEx(
+ IN PRTMP_ADAPTER pAd)
+{
+ PCH_REGION pChReg;
+
+ pChReg = GetChRegion(pAd->CommonCfg.CountryCode);
+ CreateChList(pAd, pChReg, pAd->CommonCfg.Geography);
+}
+
+VOID BuildBeaconChList(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf,
+ OUT PULONG pBufLen)
+{
+ INT i;
+ ULONG TmpLen;
+ PCH_REGION pChRegion;
+ PCH_DESP pChDesp;
+ UCHAR ChType;
+
+ pChRegion = GetChRegion(pAd->CommonCfg.CountryCode);
+
+ if (pChRegion == NULL)
+ return;
+
+ ChBandCheck(pAd->CommonCfg.PhyMode, &ChType);
+ *pBufLen = 0;
+
+ if (pAd->CommonCfg.pChDesp != NULL)
+ pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp;
+ else
+ pChDesp = pChRegion->pChDesp;
+
+ for (i=0; pChRegion->pChDesp[i].FirstChannel != 0; i++)
+ {
+ if (pChDesp[i].FirstChannel == 0)
+ break;
+
+ if (ChType == BAND_5G)
+ {
+ if (pChDesp[i].FirstChannel <= 14)
+ continue;
+ }
+ else if (ChType == BAND_24G)
+ {
+ if (pChDesp[i].FirstChannel > 14)
+ continue;
+ }
+
+ if ((pChDesp[i].Geography == BOTH) ||
+ (pChDesp[i].Geography == pAd->CommonCfg.Geography))
+ {
+ MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen,
+ 1, &pChDesp[i].FirstChannel,
+ 1, &pChDesp[i].NumOfCh,
+ 1, &pChDesp[i].MaxTxPwr,
+ END_OF_ARGS);
+ *pBufLen += TmpLen;
+ }
+ }
+}
+#endif /* EXT_BUILD_CHANNEL_LIST */
+
+#ifdef DOT11_N_SUPPORT
+static BOOLEAN IsValidChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR channel)
+
+{
+ INT i;
+
+ for (i = 0; i < pAd->ChannelListNum; i++)
+ {
+ if (pAd->ChannelList[i].Channel == channel)
+ break;
+ }
+
+ if (i == pAd->ChannelListNum)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static UCHAR GetExtCh(
+ IN UCHAR Channel,
+ IN UCHAR Direction)
+{
+ CHAR ExtCh;
+
+ if (Direction == EXTCHA_ABOVE)
+ ExtCh = Channel + 4;
+ else
+ ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0;
+
+ return ExtCh;
+}
+
+BOOLEAN N_ChannelGroupCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel)
+{
+ BOOLEAN RetVal = FALSE;
+
+ if (Channel > 14)
+ {
+ if ((Channel == 36) || (Channel == 44) || (Channel == 52) || (Channel == 60) || (Channel == 100) || (Channel == 108) ||
+ (Channel == 116) || (Channel == 124) || (Channel == 132) || (Channel == 149) || (Channel == 157))
+ {
+ RetVal = TRUE;
+ }
+ else if ((Channel == 40) || (Channel == 48) || (Channel == 56) || (Channel == 64) || (Channel == 104) || (Channel == 112) ||
+ (Channel == 120) || (Channel == 128) || (Channel == 136) || (Channel == 153) || (Channel == 161))
+ {
+ RetVal = TRUE;
+ }
+ }
+ else
+ {
+ do
+ {
+ UCHAR ExtCh;
+
+ if (Channel == 14)
+ {
+ RetVal = FALSE;
+ break;
+ }
+
+ ExtCh = GetExtCh(Channel, EXTCHA_ABOVE);
+ if (IsValidChannel(pAd, ExtCh))
+ RetVal = TRUE;
+ else
+ {
+ ExtCh = GetExtCh(Channel, EXTCHA_BELOW);
+ if (IsValidChannel(pAd, ExtCh))
+ RetVal = TRUE;
+ }
+ } while(FALSE);
+ }
+
+ return RetVal;
+}
+
+
+VOID N_ChannelCheck(RTMP_ADAPTER *pAd)
+{
+ INT idx;
+ UCHAR Channel = pAd->CommonCfg.Channel;
+ static const UCHAR wfa_ht_ch_ext[] = {
+ 36, EXTCHA_ABOVE, 40, EXTCHA_BELOW,
+ 44, EXTCHA_ABOVE, 48, EXTCHA_BELOW,
+ 52, EXTCHA_ABOVE, 56, EXTCHA_BELOW,
+ 60, EXTCHA_ABOVE, 64, EXTCHA_BELOW,
+ 100, EXTCHA_ABOVE, 104, EXTCHA_BELOW,
+ 108, EXTCHA_ABOVE, 112, EXTCHA_BELOW,
+ 116, EXTCHA_ABOVE, 120, EXTCHA_BELOW,
+ 124, EXTCHA_ABOVE, 128, EXTCHA_BELOW,
+ 132, EXTCHA_ABOVE, 136, EXTCHA_BELOW,
+ 149, EXTCHA_ABOVE, 153, EXTCHA_BELOW,
+ 157, EXTCHA_ABOVE, 161, EXTCHA_BELOW,
+ 0, 0};
+
+ if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) &&
+ (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
+ {
+ if (Channel > 14)
+ {
+ idx = 0;
+ while(wfa_ht_ch_ext[idx] != 0) {
+ if (wfa_ht_ch_ext[idx] == Channel) {
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = wfa_ht_ch_ext[idx + 1];
+ break;
+ }
+ idx += 2;
+ };
+ if (wfa_ht_ch_ext[idx] == 0)
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ }
+ else
+ {
+ do
+ {
+ UCHAR ExtCh;
+ UCHAR Dir = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA;
+ ExtCh = GetExtCh(Channel, Dir);
+ if (IsValidChannel(pAd, ExtCh))
+ break;
+
+ Dir = (Dir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE;
+ ExtCh = GetExtCh(Channel, Dir);
+ if (IsValidChannel(pAd, ExtCh))
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = Dir;
+ break;
+ }
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ } while(FALSE);
+
+ if (Channel == 14)
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ /*pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; We didn't set the ExtCh as NONE due to it'll set in RTMPSetHT()*/
+ }
+ }
+ }
+}
+
+
+UCHAR N_SetCenCh(RTMP_ADAPTER *pAd, UCHAR prim_ch)
+{
+ if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
+ {
+ if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE)
+ pAd->CommonCfg.CentralChannel = prim_ch + 2;
+ else
+ {
+ if (prim_ch == 14)
+ pAd->CommonCfg.CentralChannel = prim_ch - 1;
+ else
+ pAd->CommonCfg.CentralChannel = prim_ch - 2;
+ }
+ }
+ else
+ pAd->CommonCfg.CentralChannel = prim_ch;
+
+ return pAd->CommonCfg.CentralChannel;
+}
+#endif /* DOT11_N_SUPPORT */
+
+
+UINT8 GetCuntryMaxTxPwr(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 channel)
+{
+ int i;
+ for (i = 0; i < pAd->ChannelListNum; i++)
+ {
+ if (pAd->ChannelList[i].Channel == channel)
+ break;
+ }
+
+ if (i == pAd->ChannelListNum)
+ return 0xff;
+#ifdef SINGLE_SKU
+ if (pAd->CommonCfg.bSKUMode == TRUE)
+ {
+ UINT deltaTxStreamPwr = 0;
+
+#ifdef DOT11_N_SUPPORT
+ if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && (pAd->CommonCfg.TxStream == 2))
+ deltaTxStreamPwr = 3; /* If 2Tx case, antenna gain will increase 3dBm*/
+#endif /* DOT11_N_SUPPORT */
+
+ if (pAd->ChannelList[i].RegulatoryDomain == FCC)
+ {
+ /* FCC should maintain 20/40 Bandwidth, and without antenna gain */
+#ifdef DOT11_N_SUPPORT
+ if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) &&
+ (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) &&
+ (channel == 1 || channel == 11))
+ return (pAd->ChannelList[i].MaxTxPwr - pAd->CommonCfg.BandedgeDelta - deltaTxStreamPwr);
+ else
+#endif /* DOT11_N_SUPPORT */
+ return (pAd->ChannelList[i].MaxTxPwr - deltaTxStreamPwr);
+ }
+ else if (pAd->ChannelList[i].RegulatoryDomain == CE)
+ {
+ return (pAd->ChannelList[i].MaxTxPwr - pAd->CommonCfg.AntGain - deltaTxStreamPwr);
+ }
+ else
+ return 0xff;
+ }
+ else
+#endif /* SINGLE_SKU */
+ return pAd->ChannelList[i].MaxTxPwr;
+}
+
+
+/* for OS_ABL */
+VOID RTMP_MapChannelID2KHZ(
+ IN UCHAR Ch,
+ OUT UINT32 *pFreq)
+{
+ int chIdx;
+ for (chIdx = 0; chIdx < CH_HZ_ID_MAP_NUM; chIdx++)
+ {
+ if ((Ch) == CH_HZ_ID_MAP[chIdx].channel)
+ {
+ (*pFreq) = CH_HZ_ID_MAP[chIdx].freqKHz * 1000;
+ break;
+ }
+ }
+ if (chIdx == CH_HZ_ID_MAP_NUM)
+ (*pFreq) = 2412000;
+}
+
+/* for OS_ABL */
+VOID RTMP_MapKHZ2ChannelID(
+ IN ULONG Freq,
+ OUT INT *pCh)
+{
+ int chIdx;
+ for (chIdx = 0; chIdx < CH_HZ_ID_MAP_NUM; chIdx++)
+ {
+ if ((Freq) == CH_HZ_ID_MAP[chIdx].freqKHz)
+ {
+ (*pCh) = CH_HZ_ID_MAP[chIdx].channel;
+ break;
+ }
+ }
+ if (chIdx == CH_HZ_ID_MAP_NUM)
+ (*pCh) = 1;
+}
+
diff --git a/cleopatre/devkit/mt7601udrv/common/rt_os_util.c b/cleopatre/devkit/mt7601udrv/common/rt_os_util.c
new file mode 100644
index 0000000000..954f64e133
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rt_os_util.c
@@ -0,0 +1,161 @@
+/****************************************************************************
+
+ Module Name:
+ rt_os_util.c
+
+ Abstract:
+ All functions provided from UTIL module are put here (OS independent).
+
+ Revision History:
+ Who When What
+ --------- ---------- ----------------------------------------------
+
+***************************************************************************/
+
+#define RTMP_MODULE_OS
+#define RTMP_MODULE_OS_UTIL
+
+/*#include "rt_config.h"
+*/
+#include "rtmp_comm.h"
+#include "rt_os_util.h"
+#include "rtmp_osabl.h"
+
+
+UINT32 RalinkRate[256] =
+ {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 109, 110, 111, 112,
+ 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260,
+ 39, 78, 117, 156, 234, 312, 351, 390,
+ 27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540,
+ 81, 162, 243, 324, 486, 648, 729, 810,
+ 14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288,
+ 43, 87, 130, 173, 260, 317, 390, 433,
+ 30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600,
+ 90, 180, 270, 360, 540, 720, 810, 900,
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
+ 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,
+ 40,41,42,43,44,45,46,47}; /* 3*3
+*/
+
+VOID RtmpDrvMaxRateGet(
+ IN VOID *pReserved,
+/* IN PHTTRANSMIT_SETTING pHtPhyMode,
+*/
+ IN UINT8 MODE,
+ IN UINT8 ShortGI,
+ IN UINT8 BW,
+ IN UINT8 MCS,
+ OUT UINT32 *pRate)
+{
+ int rate_index = 0;
+
+#ifdef DOT11_N_SUPPORT
+ if (MODE >= MODE_HTMIX)
+ {
+ /* rate_index = 16 + ((UCHAR)pHtPhyMode->field.BW *16) + ((UCHAR)pHtPhyMode->field.ShortGI *32) + ((UCHAR)pHtPhyMode->field.MCS);
+*/
+ rate_index = 16 + ((UCHAR)BW *24) + ((UCHAR)ShortGI *48) + ((UCHAR)MCS);
+ }
+ else
+#endif /* DOT11_N_SUPPORT */
+ if (MODE == MODE_OFDM)
+ rate_index = (UCHAR)(MCS) + 4;
+ else
+ rate_index = (UCHAR)(MCS);
+
+ if (rate_index < 0)
+ rate_index = 0;
+
+ if (rate_index > 255)
+ rate_index = 255;
+
+ *pRate = RalinkRate[rate_index] * 500000;
+}
+
+
+char *rtstrchr(const char * s, int c)
+{
+ for(; *s != (char) c; ++s)
+ if (*s == '\0')
+ return NULL;
+ return (char *) s;
+}
+
+
+VOID RtmpMeshDown(
+ IN VOID *pDrvCtrlBK,
+ IN BOOLEAN WaitFlag,
+ IN BOOLEAN (*RtmpMeshLinkCheck)(IN VOID *pAd))
+{
+}
+
+
+
+
+BOOLEAN RtmpOsCmdDisplayLenCheck(
+ IN UINT32 LenSrc,
+ IN UINT32 Offset)
+{
+ if (LenSrc > (IW_PRIV_SIZE_MASK - Offset))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+#if defined(WPA_SUPPLICANT_SUPPORT) || defined(APCLI_WPA_SUPPLICANT_SUPPORT)
+VOID WpaSendMicFailureToWpaSupplicant(
+ IN PNET_DEV pNetDev,
+ IN BOOLEAN bUnicast)
+{
+ char custom[IW_CUSTOM_MAX] = {0};
+
+ snprintf(custom, sizeof(custom), "MLME-MICHAELMICFAILURE.indication");
+ if(bUnicast)
+ sprintf(custom, "%s unicast", custom);
+
+ RtmpOSWrielessEventSend(pNetDev, RT_WLAN_EVENT_CUSTOM, -1, NULL, (PUCHAR)custom, strlen(custom));
+
+ return;
+}
+#endif /* defined(WPA_SUPPLICANT_SUPPORT) || defined(APCLI_WPA_SUPPLICANT_SUPPORT) */
+
+
+
+
+
+
+INT32 RtPrivIoctlSetVal(VOID)
+{
+ return (INT32)RTPRIV_IOCTL_SET;
+}
+
+
+#ifdef RTMP_USB_SUPPORT
+PVOID RtmpInitCompletion(VOID)
+{
+ struct completion *comp = NULL;
+ os_alloc_mem(NULL, (UCHAR **)&comp, sizeof(struct completion));
+ init_completion(comp);
+ return (PVOID)comp;
+}
+
+
+ULONG RtmpWaitForCompletionTimeout(VOID *Completion, ULONG Expire)
+{
+ return wait_for_completion_timeout((struct completion *)Completion, Expire);
+}
+
+
+VOID RtmpComplete(VOID *Completion)
+{
+ complete((struct completion *)Completion);
+}
+#endif /* RTMP_USB_SUPPORT */
+
+ULONG RtmpMsecsToJiffies(UINT32 msecs)
+{
+ return msecs_to_jiffies(msecs);
+}
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/rt_rf.c b/cleopatre/devkit/mt7601udrv/common/rt_rf.c
new file mode 100644
index 0000000000..98a02d589a
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rt_rf.c
@@ -0,0 +1,33 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ rt_rf.c
+
+ Abstract:
+ Ralink Wireless driver RF related functions
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+*/
+
+
+#include "rt_config.h"
+
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/rtmp_init.c b/cleopatre/devkit/mt7601udrv/common/rtmp_init.c
new file mode 100644
index 0000000000..52278f2f38
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rtmp_init.c
@@ -0,0 +1,3849 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ rtmp_init.c
+
+ Abstract:
+ Miniport generic portion header file
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+*/
+#include "rt_config.h"
+
+#ifdef OS_ABL_FUNC_SUPPORT
+/* Os utility link: printk, scanf */
+RTMP_OS_ABL_OPS RaOsOps, *pRaOsOps = &RaOsOps;
+#endif /* OS_ABL_FUNC_SUPPORT */
+
+#define RT3090A_DEFAULT_INTERNAL_LNA_GAIN 0x0A
+UCHAR NUM_BIT8[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
+#ifdef DBG
+char* CipherName[] = {"none","wep64","wep128","TKIP","AES","CKIP64","CKIP128","CKIP152","SMS4"};
+#endif
+
+
+/*
+ ASIC register initialization sets
+*/
+RTMP_REG_PAIR MACRegTable[] = {
+#ifndef MT7601
+#if defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x200)
+ {BCN_OFFSET0, 0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */
+ {BCN_OFFSET1, 0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */
+#elif defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x100)
+ {BCN_OFFSET0, 0xece8e4e0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */
+ {BCN_OFFSET1, 0xfcf8f4f0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */
+#endif /* HW_BEACON_OFFSET */
+#endif /* MT7601 */
+
+ {LEGACY_BASIC_RATE, 0x0000013f}, /* Basic rate set bitmap*/
+ {HT_BASIC_RATE, 0x00008003}, /* Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI.*/
+ {MAC_SYS_CTRL, 0x00}, /* 0x1004, , default Disable RX*/
+ {RX_FILTR_CFG, 0x17f97}, /*0x1400 , RX filter control, */
+ {BKOFF_SLOT_CFG, 0x209}, /* default set short slot time, CC_DELAY_TIME should be 2 */
+ /*{TX_SW_CFG0, 0x40a06}, Gary,2006-08-23 */
+ {TX_SW_CFG0, 0x0}, /* Gary,2008-05-21 for CWC test */
+ {TX_SW_CFG1, 0x80606}, /* Gary,2006-08-23 */
+ {TX_LINK_CFG, 0x1020}, /* Gary,2006-08-23 */
+ /*{TX_TIMEOUT_CFG, 0x00182090}, CCK has some problem. So increase timieout value. 2006-10-09 MArvek RT*/
+ {TX_TIMEOUT_CFG, 0x000a2090}, /* CCK has some problem. So increase timieout value. 2006-10-09 MArvek RT , Modify for 2860E ,2007-08-01*/
+ {MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x00001000}, /* 0x3018, MAX frame length. Max PSDU = 16kbytes.*/
+#ifndef MT7601
+ {LED_CFG, 0x7f031e46}, /* Gary, 2006-08-23*/
+#endif /* MT7601 */
+
+#ifdef RLT_MAC
+
+#ifdef MT7601
+#ifdef CONFIG_MULTI_CHANNEL
+ {TX_MAX_PCNT, 0x1f1f1f1f/*0x1fbf1f1f */},
+#else
+ {TX_MAX_PCNT, 0x1fbf1f1f},
+#endif /* CONFIG_MULTI_CHANNEL */
+ {RX_MAX_PCNT, 0x9f},
+#else
+ {TX_MAX_PCNT, 0xbfbf3f1f},
+ {RX_MAX_PCNT, 0x9f},
+#endif
+
+// TODO: shiang-6590, need set this in FPGA mode
+#ifdef RTMP_MAC_USB
+#endif /* RTMP_MAC_USB */
+#else
+#ifdef INF_AMAZON_SE
+ {PBF_MAX_PCNT, 0x1F3F6F6F}, /*iverson modify for usb issue, 2008/09/19*/
+ /* 6F + 6F < total page count FE*/
+ /* so that RX doesn't occupy TX's buffer space when WMM congestion.*/
+#else
+ {PBF_MAX_PCNT, 0x1F3FBF9F}, /*0x1F3f7f9f}, Jan, 2006/04/20*/
+#endif /* INF_AMAZON_SE */
+#endif /* RLT_MAC */
+
+ /*{TX_RTY_CFG, 0x6bb80408}, Jan, 2006/11/16*/
+/* WMM_ACM_SUPPORT*/
+/* {TX_RTY_CFG, 0x6bb80101}, sample*/
+ {TX_RTY_CFG, 0x47d01f0f}, /* Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03*/
+
+ {AUTO_RSP_CFG, 0x00000013}, /* Initial Auto_Responder, because QA will turn off Auto-Responder*/
+ {CCK_PROT_CFG, 0x05740003 /*0x01740003*/}, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */
+ {OFDM_PROT_CFG, 0x05740003 /*0x01740003*/}, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */
+#ifdef RTMP_MAC_USB
+#ifndef MT7601
+ {PBF_CFG, 0xf40006}, /* Only enable Queue 2*/
+ {WPDMA_GLO_CFG, 0x00000030}, // MT7601U not support WPDMA
+#endif /* MT7601 */
+ {MM40_PROT_CFG, 0x3F44084}, /* Initial Auto_Responder, because QA will turn off Auto-Responder*/
+#endif /* RTMP_MAC_USB */
+ {GF20_PROT_CFG, 0x01744004}, /* set 19:18 --> Short NAV for MIMO PS*/
+ {GF40_PROT_CFG, 0x03F44084},
+ {MM20_PROT_CFG, 0x01744004},
+ {TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f*/ /*0x000024bf*/}, /*Extension channel backoff.*/
+ {TX_RTS_CFG, 0x01092b20}, // enable RTS fall back
+
+ {EXP_ACK_TIME, 0x002400ca}, /* default value */
+ {TXOP_HLDR_ET, 0x00000002},
+
+ /* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us
+ is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0
+ and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping
+ will always lost. So we change the SIFS of CCK from 10us to 16us. */
+ {XIFS_TIME_CFG, 0x33a41010},
+#if defined(RT65xx) || defined(MT7601)
+ {PWR_PIN_CFG, 0x00000000},
+#else
+ {PWR_PIN_CFG, 0x00000003}, /* patch for 2880-E*/
+#endif /* defined(RT65xx) || defined(MT7601) */
+};
+
+#ifdef CONFIG_AP_SUPPORT
+RTMP_REG_PAIR APMACRegTable[] = {
+ {WMM_AIFSN_CFG, 0x00001173},
+ {WMM_CWMIN_CFG, 0x00002344},
+ {WMM_CWMAX_CFG, 0x000034a6},
+ {WMM_TXOP0_CFG, 0x00100020},
+ {WMM_TXOP1_CFG, 0x002F0038},
+ {TBTT_SYNC_CFG, 0x00012000},
+#ifdef STREAM_MODE_SUPPORT
+ {TX_CHAIN_ADDR0_L, 0xFFFFFFFF}, /* Broadcast frames are in stream mode*/
+ {TX_CHAIN_ADDR0_H, 0x3FFFF},
+#endif /* STREAM_MODE_SUPPORT */
+};
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+#define NUM_MAC_REG_PARMS (sizeof(MACRegTable) / sizeof(RTMP_REG_PAIR))
+#ifdef CONFIG_AP_SUPPORT
+#define NUM_AP_MAC_REG_PARMS (sizeof(APMACRegTable) / sizeof(RTMP_REG_PAIR))
+#endif /* CONFIG_AP_SUPPORT */
+
+
+/*
+ Use the global variable is not a good solution.
+ But we can not put it to pAd and use the lock in pAd of RALINK_TIMER_STRUCT;
+ Or when the structure is cleared, we maybe get NULL for pAd and can not lock.
+ Maybe we can put pAd in RTMPSetTimer/ RTMPModTimer/ RTMPCancelTimer.
+*/
+NDIS_SPIN_LOCK TimerSemLock;
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Allocate RTMP_ADAPTER data block and do some initialization
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_FAILURE
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS RTMPAllocAdapterBlock(
+ IN PVOID handle,
+ OUT VOID **ppAdapter)
+{
+ PRTMP_ADAPTER pAd = NULL;
+ NDIS_STATUS Status;
+ INT index;
+ UCHAR *pBeaconBuf = NULL;
+
+
+#ifdef OS_ABL_FUNC_SUPPORT
+ /* must put the function before any print message */
+ /* init OS utilities provided from UTIL module */
+ RtmpOsOpsInit(&RaOsOps);
+#endif /* OS_ABL_FUNC_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocAdapterBlock\n"));
+
+ /* init UTIL module */
+ RtmpUtilInit();
+
+ *ppAdapter = NULL;
+
+ do
+ {
+ /* Allocate RTMP_ADAPTER memory block*/
+/* pBeaconBuf = kmalloc(MAX_BEACON_SIZE, MEM_ALLOC_FLAG);*/
+ os_alloc_mem(NULL, (UCHAR **)&pBeaconBuf, MAX_BEACON_SIZE);
+ if (pBeaconBuf == NULL)
+ {
+ Status = NDIS_STATUS_FAILURE;
+ DBGPRINT_ERR(("Failed to allocate memory - BeaconBuf!\n"));
+ break;
+ }
+ NdisZeroMemory(pBeaconBuf, MAX_BEACON_SIZE);
+
+ Status = AdapterBlockAllocateMemory(handle, (PVOID *)&pAd, sizeof(RTMP_ADAPTER));
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("Failed to allocate memory - ADAPTER\n"));
+ break;
+ }
+ else
+ {
+ /* init resource list (must be after pAd allocation) */
+ initList(&pAd->RscTimerMemList);
+ initList(&pAd->RscTaskMemList);
+ initList(&pAd->RscLockMemList);
+ initList(&pAd->RscTaskletMemList);
+ initList(&pAd->RscSemMemList);
+ initList(&pAd->RscAtomicMemList);
+
+ initList(&pAd->RscTimerCreateList);
+
+ pAd->OS_Cookie = handle;
+#ifdef WORKQUEUE_BH
+ ((POS_COOKIE)(handle))->pAd_va = pAd;
+#endif /* WORKQUEUE_BH */
+ }
+ pAd->BeaconBuf = pBeaconBuf;
+ DBGPRINT(RT_DEBUG_OFF, ("\n\n=== pAd = %p, size = %d ===\n\n", pAd, (UINT32)sizeof(RTMP_ADAPTER)));
+
+ if (RtmpOsStatsAlloc(&pAd->stats, &pAd->iw_stats) == FALSE)
+ {
+ Status = NDIS_STATUS_FAILURE;
+ break;
+ }
+
+ /* Init spin locks*/
+ NdisAllocateSpinLock(pAd, &pAd->MgmtRingLock);
+
+#if defined(RT3290) || defined(RT65xx) || defined(MT7601)
+#endif /* defined(RT3290) || defined(RT65xx) || defined(MT7601) */
+
+ for (index =0 ; index < NUM_OF_TX_RING; index++)
+ {
+ NdisAllocateSpinLock(pAd, &pAd->TxSwQueueLock[index]);
+ NdisAllocateSpinLock(pAd, &pAd->DeQueueLock[index]);
+ pAd->DeQueueRunning[index] = FALSE;
+ }
+
+#ifdef RESOURCE_PRE_ALLOC
+ /*
+ move this function from rt28xx_init() to here. now this function only allocate memory and
+ leave the initialization job to RTMPInitTxRxRingMemory() which called in rt28xx_init().
+ */
+ Status = RTMPAllocTxRxRingMemory(pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("Failed to allocate memory - TxRxRing\n"));
+ break;
+ }
+#endif /* RESOURCE_PRE_ALLOC */
+
+ NdisAllocateSpinLock(pAd, &pAd->irq_lock);
+
+
+ NdisAllocateSpinLock(pAd, &TimerSemLock);
+
+
+
+#ifdef RALINK_ATE
+#ifdef RTMP_MAC_USB
+ RTMP_OS_ATMOIC_INIT(&pAd->BulkOutRemained, &pAd->RscAtomicMemList);
+ RTMP_OS_ATMOIC_INIT(&pAd->BulkInRemained, &pAd->RscAtomicMemList);
+#endif /* RTMP_MAC_USB */
+#endif /* RALINK_ATE */
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef UAPSD_SUPPORT
+/* UAPSD_Init(pAd); move to rt28xx_init*/
+#endif /* UAPSD_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* assign function pointers*/
+#ifdef MAT_SUPPORT
+ /* init function pointers, used in OS_ABL */
+/* RTMP_MATOpsInit(pAd); move to rt28xx_init*/
+#endif /* MAT_SUPPORT */
+ } while (FALSE);
+
+ if ((Status != NDIS_STATUS_SUCCESS) && (pBeaconBuf))
+/* kfree(pBeaconBuf);*/
+ os_free_mem(NULL, pBeaconBuf);
+
+ if ((Status != NDIS_STATUS_SUCCESS) && (pAd != NULL))
+ {
+ if (pAd->stats != NULL)
+ os_free_mem(NULL, pAd->stats);
+
+ if (pAd->iw_stats != NULL)
+ os_free_mem(NULL, pAd->iw_stats);
+ }
+
+ if (pAd != NULL) /* compile warning: avoid use NULL pointer when pAd == NULL */
+ *ppAdapter = (VOID *)pAd;
+
+
+ /*
+ Init ProbeRespIE Table
+ */
+ for (index = 0; index < MAX_LEN_OF_BSS_TABLE; index++)
+ {
+ if (os_alloc_mem(pAd,&pAd->ProbeRespIE[index].pIe, MAX_VIE_LEN) == NDIS_STATUS_SUCCESS)
+ RTMPZeroMemory(pAd->ProbeRespIE[index].pIe, MAX_VIE_LEN);
+ else
+ pAd->ProbeRespIE[index].pIe = NULL;
+ }
+
+ DBGPRINT_S(Status, ("<-- RTMPAllocAdapterBlock, Status=%x\n", Status));
+ return Status;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Read initial parameters from EEPROM
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID NICReadEEPROMParameters(RTMP_ADAPTER *pAd, PSTRING mac_addr)
+{
+ USHORT i, value, value2;
+ EEPROM_TX_PWR_STRUC Power;
+ EEPROM_VERSION_STRUC Version;
+ EEPROM_ANTENNA_STRUC Antenna;
+ EEPROM_NIC_CONFIG2_STRUC NicConfig2;
+ USHORT Addr01,Addr23,Addr45 ;
+ MAC_DW0_STRUC csr2;
+ MAC_DW1_STRUC csr3;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICReadEEPROMParameters\n"));
+
+#ifdef RT3290
+ if (IS_RT3290(pAd))
+ RT3290_eeprom_access_grant(pAd, TRUE);
+#endif /* RT3290 */
+
+ if (pAd->chipOps.eeinit)
+ {
+ pAd->chipOps.eeinit(pAd);
+#ifdef RTMP_EFUSE_SUPPORT
+#ifdef RALINK_ATE
+ if(!pAd->bFroceEEPROMBuffer && pAd->bEEPROMFile)
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("--> NICReadEEPROMParameters::(Efuse)Load to EEPROM Buffer Mode\n"));
+ eFuseLoadEEPROM(pAd);
+ }
+#endif /* RALINK_ATE */
+#endif /* RTMP_EFUSE_SUPPORT */
+ }
+
+ /* Read MAC setting from EEPROM and record as permanent MAC address */
+ DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from E2PROM \n"));
+
+ RT28xx_EEPROM_READ16(pAd, 0x04, Addr01);
+ RT28xx_EEPROM_READ16(pAd, 0x06, Addr23);
+ RT28xx_EEPROM_READ16(pAd, 0x08, Addr45);
+
+ pAd->PermanentAddress[0] = (UCHAR)(Addr01 & 0xff);
+ pAd->PermanentAddress[1] = (UCHAR)(Addr01 >> 8);
+ pAd->PermanentAddress[2] = (UCHAR)(Addr23 & 0xff);
+ pAd->PermanentAddress[3] = (UCHAR)(Addr23 >> 8);
+ pAd->PermanentAddress[4] = (UCHAR)(Addr45 & 0xff);
+ pAd->PermanentAddress[5] = (UCHAR)(Addr45 >> 8);
+
+ /*more conveninet to test mbssid, so ap's bssid &0xf1*/
+ if (pAd->PermanentAddress[0] == 0xff)
+ pAd->PermanentAddress[0] = RandomByte(pAd)&0xf8;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n",
+ PRINT_MAC(pAd->PermanentAddress)));
+
+ /* Assign the actually working MAC Address */
+ if (pAd->bLocalAdminMAC)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Use the MAC address what is assigned from Configuration file(.dat). \n"));
+ }
+ else if (mac_addr &&
+ strlen((PSTRING)mac_addr) == 17 &&
+ (strcmp(mac_addr, "00:00:00:00:00:00") != 0))
+ {
+ INT j;
+ PSTRING macptr;
+
+ macptr = (PSTRING) mac_addr;
+ for (j=0; j<MAC_ADDR_LEN; j++)
+ {
+ AtoH(macptr, &pAd->CurrentAddress[j], 1);
+ macptr=macptr+3;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Use the MAC address what is assigned from Moudle Parameter. \n"));
+ }
+ else
+ {
+ COPY_MAC_ADDR(pAd->CurrentAddress, pAd->PermanentAddress);
+ DBGPRINT(RT_DEBUG_TRACE, ("Use the MAC address what is assigned from EEPROM. \n"));
+ }
+
+ /* Set the current MAC to ASIC */
+ csr2.field.Byte0 = pAd->CurrentAddress[0];
+ csr2.field.Byte1 = pAd->CurrentAddress[1];
+ csr2.field.Byte2 = pAd->CurrentAddress[2];
+ csr2.field.Byte3 = pAd->CurrentAddress[3];
+ RTMP_IO_WRITE32(pAd, MAC_ADDR_DW0, csr2.word);
+ csr3.word = 0;
+ csr3.field.Byte4 = pAd->CurrentAddress[4];
+ {
+ csr3.field.Byte5 = pAd->CurrentAddress[5];
+ csr3.field.U2MeMask = 0xff;
+ }
+ RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word);
+
+#ifdef HDR_TRANS_SUPPORT
+ RTMP_IO_WRITE32(pAd, HT_MAC_ADDR_DW0, csr2.word);
+ csr3.word &= 0xff00ffff;
+ csr3.word |= 0x00410000; // HW test code
+ RTMP_IO_WRITE32(pAd, HT_MAC_ADDR_DW1, csr3.word);
+#endif /* HDR_TRANS_SUPPORT */
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("Current MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n",
+ PRINT_MAC(pAd->CurrentAddress)));
+
+ /* if E2PROM version mismatch with driver's expectation, then skip*/
+ /* all subsequent E2RPOM retieval and set a system error bit to notify GUI*/
+ RT28xx_EEPROM_READ16(pAd, EEPROM_VERSION_OFFSET, Version.word);
+ pAd->EepromVersion = Version.field.Version + Version.field.FaeReleaseNumber * 256;
+ DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: Version = %d, FAE release #%d\n", Version.field.Version, Version.field.FaeReleaseNumber));
+
+#ifdef MT7601
+ if ( IS_MT7601(pAd) )
+ {
+ if (Version.field.Version > MT7601_VALID_EEPROM_VERSION)
+ {
+ DBGPRINT_ERR(("MT7601 E2PROM: WRONG VERSION 0x%x, should be %d\n",Version.field.Version, MT7601_VALID_EEPROM_VERSION));
+ }
+
+ }
+ else
+#endif /* MT7601 */
+ if (Version.field.Version > VALID_EEPROM_VERSION)
+ {
+ DBGPRINT_ERR(("E2PROM: WRONG VERSION 0x%x, should be %d\n",Version.field.Version, VALID_EEPROM_VERSION));
+ }
+
+ /* Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAd*/
+ RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, value);
+ pAd->EEPROMDefaultValue[EEPROM_NIC_CFG1_OFFSET] = value;
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value);
+ pAd->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET] = value;
+
+ /* if not return early. cause fail at emulation.*/
+ /* Init the channel number for TX channel power*/
+#ifdef RT8592
+ if (IS_RT8592(pAd))
+ RT85592_ReadChannelPwr(pAd);
+ else
+#endif /* RT8592 */
+#ifdef RT65xx
+ if (IS_RT6590(pAd))
+ RT6590_ReadChannelPwr(pAd);
+ else
+#endif /* RT65xx */
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ MT7601_ReadChannelPwr(pAd);
+ else
+#endif /* MT7601 */
+ RTMPReadChannelPwr(pAd);
+
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_COUNTRY_REGION, value); /* Country Region*/
+ pAd->EEPROMDefaultValue[EEPROM_COUNTRY_REG_OFFSET] = value;
+ }
+
+#if defined(BT_COEXISTENCE_SUPPORT) || defined(RT3290)
+ RT28xx_EEPROM_READ16(pAd, EEPROM_NIC3_OFFSET, value);
+ pAd->EEPROMDefaultValue[EEPROM_NIC_CFG3_OFFSET] = value;
+ pAd->NicConfig3.word = pAd->EEPROMDefaultValue[EEPROM_NIC_CFG3_OFFSET];
+#endif /* defined(BT_COEXISTENCE_SUPPORT) || defined(RT3290) */
+
+// TODO: check this after receive TC6008 EEPROM format
+#if !defined(RT65xx) && !defined(MT7601)
+ for(i = 0; i < 8; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_BBP_BASE_OFFSET + i*2, value);
+ pAd->EEPROMDefaultValue[i+EEPROM_BBP_ARRAY_OFFSET] = value;
+ }
+#endif /* !defined(RT65xx) && !defined(MT7601) */
+
+ /* We have to parse NIC configuration 0 at here.*/
+ /* If TSSI did not have preloaded value, it should reset the TxAutoAgc to false*/
+ /* Therefore, we have to read TxAutoAgc control beforehand.*/
+ /* Read Tx AGC control bit*/
+ Antenna.word = pAd->EEPROMDefaultValue[EEPROM_NIC_CFG1_OFFSET];
+
+#ifdef RT65xx
+ if (IS_RT8592(pAd)) {
+ DBGPRINT(RT_DEBUG_OFF, ("RT85592: Antenna.RfIcType=%d, TxPath=%d, RxPath=%d\n",
+ Antenna.field.RfIcType, Antenna.field.TxPath, Antenna.field.RxPath));
+ // TODO: fix me!!
+ Antenna.word = 0;
+ Antenna.field.BoardType = 0;
+ Antenna.field.RfIcType = 0xf;
+ Antenna.field.TxPath = 2;
+ Antenna.field.RxPath = 2;
+ }
+ else if (IS_RT65XX(pAd)) {
+ // TODO: shiang-6590, now we force the ant as 1*1, remove it after EEPROM is ready!
+ Antenna.word = 0;
+ Antenna.field.BoardType = 0;
+ Antenna.field.RfIcType = 0xf;
+ Antenna.field.TxPath = 1;
+ Antenna.field.RxPath = 1;
+ }
+#endif /* RT65xx */
+
+ /* must be put here, because RTMP_CHIP_ANTENNA_INFO_DEFAULT_RESET() will clear *
+ * EPROM 0x34~3 */
+#ifdef TXRX_SW_ANTDIV_SUPPORT
+ /* EEPROM 0x34[15:12] = 0xF is invalid, 0x2~0x3 is TX/RX SW AntDiv */
+ if (((Antenna.word & 0xFF00) != 0xFF00) && (Antenna.word & 0x2000))
+ {
+ pAd->chipCap.bTxRxSwAntDiv = TRUE; /* for GPIO switch */
+ DBGPRINT(RT_DEBUG_OFF, ("\x1b[mAntenna word %X/%d, AntDiv %d\x1b[m\n",
+ Antenna.word, Antenna.field.BoardType, pAd->NicConfig2.field.AntDiversity));
+ }
+#endif /* TXRX_SW_ANTDIV_SUPPORT */
+
+
+ // TODO: shiang, why we only check oxff00??
+ if ((Antenna.word & 0xFF00) == 0xFF00)
+/* if (Antenna.word == 0xFFFF)*/
+ RTMP_CHIP_ANTENNA_INFO_DEFAULT_RESET(pAd, &Antenna);
+
+ /* Choose the desired Tx&Rx stream.*/
+ if ((pAd->CommonCfg.TxStream == 0) || (pAd->CommonCfg.TxStream > Antenna.field.TxPath))
+ pAd->CommonCfg.TxStream = Antenna.field.TxPath;
+
+ if ((pAd->CommonCfg.RxStream == 0) || (pAd->CommonCfg.RxStream > Antenna.field.RxPath))
+ {
+ pAd->CommonCfg.RxStream = Antenna.field.RxPath;
+
+ if ((pAd->MACVersion != RALINK_3883_VERSION) &&
+ (pAd->MACVersion != RALINK_2883_VERSION) &&
+ (pAd->CommonCfg.RxStream > 2))
+ {
+ /* only 2 Rx streams for RT2860 series*/
+ pAd->CommonCfg.RxStream = 2;
+ }
+ }
+
+ /* EEPROM offset 0x36 - NIC Configuration 1 */
+ NicConfig2.word = pAd->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET];
+
+#ifdef WSC_INCLUDED
+ /* WSC hardware push button function 0811 */
+ //if ((pAd->MACVersion == 0x28600100) || (pAd->MACVersion == 0x28700100))
+ WSC_HDR_BTN_MR_HDR_SUPPORT_SET(pAd, NicConfig2.field.EnableWPSPBC);
+#endif /* WSC_INCLUDED */
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if (NicConfig2.word == 0xffff)
+ NicConfig2.word = 0;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ if (NicConfig2.field.DynamicTxAgcControl == 1)
+ pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE;
+ else
+ pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE;
+
+
+ /* Save value for future using */
+ pAd->NicConfig2.word = NicConfig2.word;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("NICReadEEPROMParameters: RxPath = %d, TxPath = %d\n", Antenna.field.RxPath, Antenna.field.TxPath));
+
+ /* Save the antenna for future use*/
+ pAd->Antenna.word = Antenna.word;
+
+ /* Set the RfICType here, then we can initialize RFIC related operation callbacks*/
+ pAd->Mlme.RealRxPath = (UCHAR) Antenna.field.RxPath;
+
+ pAd->RfIcType = (UCHAR) Antenna.field.RfIcType;
+
+#ifdef RT65xx
+ // TODO: shiang-6590, currently we don't have eeprom value, so directly force to set it as 0xff
+ if (IS_RT8592(pAd)) {
+ pAd->Mlme.RealRxPath = 2;
+ pAd->RfIcType = RFIC_UNKNOWN;
+ }
+ else if (IS_RT65XX(pAd)) {
+ pAd->Mlme.RealRxPath = 1;
+ pAd->RfIcType = RFIC_UNKNOWN;
+ }
+#endif /* RT65xx */
+
+ /* check if the chip supports 5G band */
+ if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode))
+ {
+ if (!RFIC_IS_5G_BAND(pAd))
+ {
+ DBGPRINT_RAW(RT_DEBUG_ERROR,
+ ("%s():Err! chip not support 5G band %d!\n",
+ __FUNCTION__, pAd->RfIcType));
+#ifdef DOT11_N_SUPPORT
+ /* change to bgn mode */
+ Set_WirelessMode_Proc(pAd, "9");
+#else
+ /* change to bg mode */
+ Set_WirelessMode_Proc(pAd, "0");
+#endif /* DOT11_N_SUPPORT */
+ pAd->RFICType = RFIC_24GHZ;
+ }
+ pAd->RFICType = RFIC_24GHZ | RFIC_5GHZ;
+ }
+ else
+ pAd->RFICType = RFIC_24GHZ;
+
+ RTMP_NET_DEV_NICKNAME_INIT(pAd);
+
+#ifdef RT65xx
+ if (IS_RT6590(pAd))
+ {
+ ; // TODO: wait TC6008 EEPROM format
+ }
+ else
+#endif /* RT65xx */
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ {
+ ; // move to MT7601_InitDesiredTSSITable
+ }
+ else
+#endif /* MT7601 */
+ /* Read TSSI reference and TSSI boundary for temperature compensation. This is ugly*/
+ /* 0. 11b/g*/
+ {
+ /* these are tempature reference value (0x00 ~ 0xFE)
+ ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
+ TssiPlusBoundaryG [4] [3] [2] [1] [0] (smaller) +
+ TssiMinusBoundaryG[0] [1] [2] [3] [4] (larger) */
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND1, Power.word);
+ pAd->TssiMinusBoundaryG[4] = Power.field.Byte0;
+ pAd->TssiMinusBoundaryG[3] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND2, Power.word);
+ pAd->TssiMinusBoundaryG[2] = Power.field.Byte0;
+ pAd->TssiMinusBoundaryG[1] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND3, Power.word);
+ pAd->TssiRefG = Power.field.Byte0; /* reference value [0] */
+ pAd->TssiPlusBoundaryG[1] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND4, Power.word);
+ pAd->TssiPlusBoundaryG[2] = Power.field.Byte0;
+ pAd->TssiPlusBoundaryG[3] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND5, Power.word);
+ pAd->TssiPlusBoundaryG[4] = Power.field.Byte0;
+ pAd->TxAgcStepG = Power.field.Byte1;
+ pAd->TxAgcCompensateG = 0;
+ pAd->TssiMinusBoundaryG[0] = pAd->TssiRefG;
+ pAd->TssiPlusBoundaryG[0] = pAd->TssiRefG;
+
+ /* Disable TxAgc if the based value is not right*/
+ if (pAd->TssiRefG == 0xff)
+ pAd->bAutoTxAgcG = FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("E2PROM: G Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n",
+ pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1],
+ pAd->TssiRefG,
+ pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4],
+ pAd->TxAgcStepG, pAd->bAutoTxAgcG));
+ }
+
+#ifdef RT65xx
+ if (IS_RT6590(pAd))
+ {
+ ; // TODO: wait TC6008 EEPROM format
+ }
+ else
+#endif /* RT65xx */
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ {
+ ; // MT7601 not support A Band
+ }
+ else
+#endif /* MT7601 */
+ /* 1. 11a*/
+ {
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND1, Power.word);
+ pAd->TssiMinusBoundaryA[4] = Power.field.Byte0;
+ pAd->TssiMinusBoundaryA[3] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND2, Power.word);
+ pAd->TssiMinusBoundaryA[2] = Power.field.Byte0;
+ pAd->TssiMinusBoundaryA[1] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND3, Power.word);
+ pAd->TssiRefA = Power.field.Byte0;
+ pAd->TssiPlusBoundaryA[1] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND4, Power.word);
+ pAd->TssiPlusBoundaryA[2] = Power.field.Byte0;
+ pAd->TssiPlusBoundaryA[3] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND5, Power.word);
+ pAd->TssiPlusBoundaryA[4] = Power.field.Byte0;
+ pAd->TxAgcStepA = Power.field.Byte1;
+ pAd->TxAgcCompensateA = 0;
+ pAd->TssiMinusBoundaryA[0] = pAd->TssiRefA;
+ pAd->TssiPlusBoundaryA[0] = pAd->TssiRefA;
+
+ /* Disable TxAgc if the based value is not right*/
+ if (pAd->TssiRefA == 0xff)
+ pAd->bAutoTxAgcA = FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("E2PROM: A Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n",
+ pAd->TssiMinusBoundaryA[4], pAd->TssiMinusBoundaryA[3], pAd->TssiMinusBoundaryA[2], pAd->TssiMinusBoundaryA[1],
+ pAd->TssiRefA,
+ pAd->TssiPlusBoundaryA[1], pAd->TssiPlusBoundaryA[2], pAd->TssiPlusBoundaryA[3], pAd->TssiPlusBoundaryA[4],
+ pAd->TxAgcStepA, pAd->bAutoTxAgcA));
+ }
+ pAd->BbpRssiToDbmDelta = 0x0;
+
+ /* Read frequency offset setting for RF*/
+ RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, value);
+
+ if ((value & 0x00FF) != 0x00FF)
+ pAd->RfFreqOffset = (ULONG) (value & 0x00FF);
+ else
+ pAd->RfFreqOffset = 0;
+
+#ifdef MT7601
+ if ( IS_MT7601(pAd) )
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET_COMPERSATION, value);
+ value = (value >> 8) & 0xFF;
+ if ( value != 0xFF )
+ {
+ if ( value & 0x80 )
+ pAd->RfFreqOffset -= (value & 0x7F);
+ else
+ pAd->RfFreqOffset += value;
+ }
+
+ }
+#endif /* MT7601 */
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: RF FreqOffset=0x%lx \n", pAd->RfFreqOffset));
+
+ // 40M BW in 2.4GHz band (37h)
+ if ( pAd->NicConfig2.field.BW40MAvailForG )
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: BW_20\n"));
+ }
+
+ /*CountryRegion byte offset (38h)*/
+ {
+ value = pAd->EEPROMDefaultValue[EEPROM_COUNTRY_REG_OFFSET] >> 8; /* 2.4G band*/
+ value2 = pAd->EEPROMDefaultValue[EEPROM_COUNTRY_REG_OFFSET] & 0x00FF; /* 5G band*/
+ }
+
+ if ((value <= REGION_MAXIMUM_BG_BAND) || (value == REGION_32_BG_BAND) || (value == REGION_33_BG_BAND))
+ {
+ pAd->CommonCfg.CountryRegion = ((UCHAR) value) | 0x80;
+ }
+
+ if (value2 <= REGION_MAXIMUM_A_BAND)
+ {
+ pAd->CommonCfg.CountryRegionForABand = ((UCHAR) value2) | 0x80;
+ }
+
+ /* Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch.*/
+ /* The valid value are (-10 ~ 10) */
+ /* */
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value);
+ pAd->BGRssiOffset[0] = value & 0x00ff;
+ pAd->BGRssiOffset[1] = (value >> 8);
+ }
+
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ {
+ ; // MT7601 not support BGRssiOffset[2]
+ }
+ else
+#endif /* MT7601 */
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET+2, value);
+/* if (IS_RT2860(pAd)) RT2860 supports 3 Rx and the 2.4 GHz RSSI #2 offset is in the EEPROM 0x48*/
+ pAd->BGRssiOffset[2] = value & 0x00ff;
+ pAd->ALNAGain1 = (value >> 8);
+ }
+
+#ifdef RT65xx
+ if (IS_RT6590(pAd))
+ {
+ /*
+ MT7650 E1 doesn't support external LNA.
+ 2012/04/12
+ */
+ ; // TODO: wait TC6008 EEPROM format
+ }
+ else
+#endif /* RT65xx */
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, value);
+ pAd->BLNAGain = value & 0x00ff;
+ pAd->ALNAGain0 = (value >> 8);
+ }
+
+
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ {
+ ; // MT7601 not support A Band
+ }
+ else
+#endif /* MT7601 */
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value);
+ pAd->ARssiOffset[0] = value & 0x00ff;
+ pAd->ARssiOffset[1] = (value >> 8);
+ }
+
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ {
+ ; // MT7601 not support A Band
+ }
+ else
+#endif /* MT7601 */
+ {
+ RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET+2), value);
+ pAd->ARssiOffset[2] = value & 0x00ff;
+ pAd->ALNAGain2 = (value >> 8);
+ }
+
+
+ if (((UCHAR)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00))
+ pAd->ALNAGain1 = pAd->ALNAGain0;
+ if (((UCHAR)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00))
+ pAd->ALNAGain2 = pAd->ALNAGain0;
+
+ /* Validate 11a/b/g RSSI 0/1/2 offset.*/
+ for (i =0 ; i < 3; i++)
+ {
+ if ((pAd->BGRssiOffset[i] < -10) || (pAd->BGRssiOffset[i] > 10))
+ pAd->BGRssiOffset[i] = 0;
+
+ if ((pAd->ARssiOffset[i] < -10) || (pAd->ARssiOffset[i] > 10))
+ pAd->ARssiOffset[i] = 0;
+ }
+
+
+#ifdef LED_CONTROL_SUPPORT
+ /* LED Setting */
+ RTMPGetLEDSetting(pAd);
+#endif /* LED_CONTROL_SUPPORT */
+
+ RTMPReadTxPwrPerRate(pAd);
+
+#ifdef SINGLE_SKU
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_DEFINE_MAX_TXPWR, pAd->CommonCfg.DefineMaxTxPwr);
+ }
+
+ /*
+ Some dongle has old EEPROM value, use ModuleTxpower for saving correct value fo DefineMaxTxPwr.
+ ModuleTxpower will override DefineMaxTxPwr (value from EEPROM) if ModuleTxpower is not zero.
+ */
+ if (pAd->CommonCfg.ModuleTxpower > 0)
+ pAd->CommonCfg.DefineMaxTxPwr = pAd->CommonCfg.ModuleTxpower;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("TX Power set for SINGLE SKU MODE is : 0x%04x \n", pAd->CommonCfg.DefineMaxTxPwr));
+
+ pAd->CommonCfg.bSKUMode = FALSE;
+ if ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF) <= 0x50)
+ {
+ if (IS_RT3883(pAd))
+ pAd->CommonCfg.bSKUMode = TRUE;
+ else if ((pAd->CommonCfg.AntGain > 0) && (pAd->CommonCfg.BandedgeDelta >= 0))
+ pAd->CommonCfg.bSKUMode = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("Single SKU Mode is %s\n",
+ pAd->CommonCfg.bSKUMode ? "Enable" : "Disable"));
+#endif /* SINGLE_SKU */
+
+#ifdef SINGLE_SKU_V2
+ InitSkuRateDiffTable(pAd);
+#endif /* SINGLE_SKU_V2 */
+
+
+#ifdef RTMP_INTERNAL_TX_ALC
+#ifdef RT65xx
+ if (IS_RT6590(pAd))
+ {
+ ; // TODO: wait TC6008 EEPROM format
+ }
+ else
+#endif /* RT65xx */
+ {
+ /*
+ Internal Tx ALC support is starting from RT3370 / RT3390, which combine PA / LNA in single chip.
+ The old chipset don't have this, add new feature flag RTMP_INTERNAL_TX_ALC.
+ */
+ RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value);
+ if (value == 0xFFFF) /*EEPROM is empty*/
+ pAd->TxPowerCtrl.bInternalTxALC = FALSE;
+ else if (value & 1<<13)
+ pAd->TxPowerCtrl.bInternalTxALC = TRUE;
+ else
+ pAd->TxPowerCtrl.bInternalTxALC = FALSE;
+
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("TXALC> bInternalTxALC = %d\n", pAd->TxPowerCtrl.bInternalTxALC));
+#endif /* RTMP_INTERNAL_TX_ALC */
+
+
+
+#ifdef RT3290
+ if (IS_RT3290(pAd))
+ RT3290_eeprom_access_grant(pAd, FALSE);
+#endif /* RT3290 */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: pAd->Antenna.field.BoardType = %d, IS_MINI_CARD(pAd) = %d, IS_RT5390U(pAd) = %d\n",
+ __FUNCTION__,
+ pAd->Antenna.field.BoardType,
+ IS_MINI_CARD(pAd),
+ IS_RT5390U(pAd)));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICReadEEPROMParameters\n"));
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Set default value from EEPROM
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID NICInitAsicFromEEPROM(
+ IN PRTMP_ADAPTER pAd)
+{
+ USHORT i;
+#ifdef RALINK_ATE
+ USHORT value;
+#endif /* RALINK_ATE */
+ EEPROM_NIC_CONFIG2_STRUC NicConfig2;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitAsicFromEEPROM\n"));
+
+#if !defined(RT65xx) && !defined(MT7601)
+ for(i = EEPROM_BBP_ARRAY_OFFSET; i < NUM_EEPROM_BBP_PARMS; i++)
+ {
+ UCHAR BbpRegIdx, BbpValue;
+
+ if ((pAd->EEPROMDefaultValue[i] != 0xFFFF) && (pAd->EEPROMDefaultValue[i] != 0))
+ {
+ BbpRegIdx = (UCHAR)(pAd->EEPROMDefaultValue[i] >> 8);
+ BbpValue = (UCHAR)(pAd->EEPROMDefaultValue[i] & 0xff);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BbpRegIdx, BbpValue);
+ }
+ }
+#endif /* #if !defined(RT65xx) && !defined(MT7601) */
+
+ NicConfig2.word = pAd->NicConfig2.word;
+
+ /* finally set primary ant */
+ AntCfgInit(pAd);
+
+ RTMP_CHIP_ASIC_INIT_TEMPERATURE_COMPENSATION(pAd);
+
+ if (pAd->chipOps.AsicRfInit)
+ pAd->chipOps.AsicRfInit(pAd);
+
+
+#ifdef RTMP_MAC_USB
+ if (IS_RT30xx(pAd)|| IS_RT3572(pAd))
+ {
+ RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
+ if (pChipOps->AsicReverseRfFromSleepMode)
+ pChipOps->AsicReverseRfFromSleepMode(pAd, TRUE);
+ }
+#endif /* RTMP_MAC_USB */
+ /* Turn off patching for cardbus controller*/
+ if (NicConfig2.field.CardbusAcceleration == 1)
+ {
+/* pAd->bTest1 = TRUE;*/
+ }
+
+ if (NicConfig2.field.DynamicTxAgcControl == 1)
+ pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE;
+ else
+ pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE;
+
+#ifdef RTMP_INTERNAL_TX_ALC
+ /*
+ Internal Tx ALC support is starting from RT3370 / RT3390, which combine PA / LNA in single chip.
+ The old chipset don't have this, add new feature flag RTMP_INTERNAL_TX_ALC.
+ */
+
+ /* Internal Tx ALC */
+ if (((NicConfig2.field.DynamicTxAgcControl == 1) &&
+ (NicConfig2.field.bInternalTxALC == 1)) ||
+ ((!IS_RT3390(pAd)) && (!IS_RT3350(pAd)) &&
+ (!IS_RT3352(pAd)) && (!IS_RT5350(pAd)) && (!IS_RT5390(pAd)) && (!IS_RT3290(pAd)) && (!IS_MT7601(pAd))))
+ {
+ /*
+ If both DynamicTxAgcControl and bInternalTxALC are enabled,
+ it is a wrong configuration.
+ If the chipset does not support Internal TX ALC, we shall disable it.
+ */
+ pAd->TxPowerCtrl.bInternalTxALC = FALSE;
+ }
+ else
+ {
+ if (NicConfig2.field.bInternalTxALC == 1)
+ {
+ pAd->TxPowerCtrl.bInternalTxALC = TRUE;
+ }
+ else
+ {
+ pAd->TxPowerCtrl.bInternalTxALC = FALSE;
+ }
+ }
+
+
+ /* Old 5390 NIC always disables the internal ALC */
+
+ if (pAd->MACVersion == 0x53900501)
+ {
+ pAd->TxPowerCtrl.bInternalTxALC = FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: pAd->TxPowerCtrl.bInternalTxALC = %d\n",
+ __FUNCTION__,
+ pAd->TxPowerCtrl.bInternalTxALC));
+#endif /* RTMP_INTERNAL_TX_ALC */
+
+#ifdef RALINK_ATE
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TSSI_GAIN_AND_ATTENUATION, value);
+ value = (value & 0x00FF);
+
+ if (IS_RT5390(pAd))
+ {
+ pAd->TssiGain = 0x02; /* RT5390 uses 2 as TSSI gain/attenuation default value */
+ }
+ else
+ {
+ pAd->TssiGain = 0x03; /* RT5392 uses 3 as TSSI gain/attenuation default value */
+ }
+
+ if ((value != 0x00) && (value != 0xFF))
+ {
+ pAd->TssiGain = (UCHAR) (value & 0x000F);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: EEPROM_TSSI_GAIN_AND_ATTENUATION = 0x%X, pAd->TssiGain=0x%x\n",
+ __FUNCTION__,
+ value,
+ pAd->TssiGain));
+#endif // RALINK_ATE //
+
+ rtmp_bbp_set_rxpath(pAd, pAd->Antenna.field.RxPath);
+
+
+ RTMP_EEPROM_ASIC_INIT(pAd);
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("TxPath = %d, RxPath = %d, RFIC=%d\n",
+ pAd->Antenna.field.TxPath, pAd->Antenna.field.RxPath, pAd->RfIcType));
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitAsicFromEEPROM\n"));
+}
+
+
+#ifdef DBG
+VOID dump_pdma_reg(RTMP_ADAPTER *pAd)
+{
+
+
+}
+#endif /* DBG */
+
+
+
+
+VOID AsicInitBcnBuf(IN RTMP_ADAPTER *pAd)
+{
+ int idx;
+ RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
+
+
+ for (idx = 0; idx < pChipCap->BcnMaxHwNum; idx++)
+ pAd->BeaconOffset[idx] = pChipCap->BcnBase[idx];
+
+ DBGPRINT(RT_DEBUG_TRACE, ("< Beacon Information: >\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("\tFlgIsSupSpecBcnBuf = %s\n", pChipCap->FlgIsSupSpecBcnBuf ? "TRUE" : "FALSE"));
+ DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxHwNum = %d\n", pChipCap->BcnMaxHwNum));
+ DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxNum = %d\n", pChipCap->BcnMaxNum));
+ DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxHwSize = 0x%x\n", pChipCap->BcnMaxHwSize));
+ DBGPRINT(RT_DEBUG_TRACE, ("\tWcidHwRsvNum = %d\n", pChipCap->WcidHwRsvNum));
+ for (idx = 0; idx < pChipCap->BcnMaxHwNum; idx++) {
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\tBcnBase[%d] = 0x%x, pAd->BeaconOffset[%d]=0x%x\n",
+ idx, pChipCap->BcnBase[idx], idx, pAd->BeaconOffset[idx]));
+ }
+
+
+#ifdef RLT_MAC
+ {
+ RTMP_REG_PAIR bcn_mac_reg_tb[] = {
+ {BCN_OFFSET0, 0x18100800},
+ {BCN_OFFSET1, 0x38302820},
+ {BCN_OFFSET2, 0x58504840},
+ {BCN_OFFSET3, 0x78706860},
+ };
+ for (idx = 0; idx < 4; idx ++)
+ {
+ RTMP_IO_WRITE32(pAd, (USHORT)bcn_mac_reg_tb[idx].Register,
+ bcn_mac_reg_tb[idx].Value);
+ }
+ }
+#endif /* RLT_MAC */
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Initialize NIC hardware
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS NICInitializeAdapter(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bHardReset)
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ WPDMA_GLO_CFG_STRUC GloCfg;
+ ULONG j=0;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAdapter\n"));
+
+ /* Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits */
+retry:
+
+ if (AsicWaitPDMAIdle(pAd, 100, 1000) != TRUE) {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return NDIS_STATUS_FAILURE;
+ }
+
+
+
+ /* Initialze ASIC for TX & Rx operation*/
+ if (NICInitializeAsic(pAd , bHardReset) != NDIS_STATUS_SUCCESS)
+ {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return NDIS_STATUS_FAILURE;
+
+ if (pAd->chipOps.loadFirmware)
+ {
+ if (j++ == 0)
+ {
+ NICLoadFirmware(pAd);
+ goto retry;
+ }
+ }
+ return NDIS_STATUS_FAILURE;
+ }
+
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAdapter\n"));
+ return Status;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Initialize ASIC
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS NICInitializeAsic(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bHardReset)
+{
+ ULONG Index = 0;
+ UINT32 MACValue = 0;
+#ifdef RTMP_MAC_USB
+ UINT32 Counter = 0;
+ USB_DMA_CFG_STRUC UsbCfg;
+#endif /* RTMP_MAC_USB */
+ USHORT KeyIdx;
+
+#ifdef RLT_MAC
+ RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
+#endif
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n"));
+
+
+
+#ifdef RTMP_MAC_USB
+ /* Make sure MAC gets ready after NICLoadFirmware().*/
+
+ Index = 0;
+
+ /*To avoid hang-on issue when interface up in kernel 2.4, */
+ /*we use a local variable "MacCsr0" instead of using "pAd->MACVersion" directly.*/
+ if (WaitForAsicReady(pAd) != TRUE)
+ return NDIS_STATUS_FAILURE;
+
+ // TODO: shiang, how about the value setting of pAd->MACVersion?? Original it assigned here
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():MACVersion[Ver:Rev=0x%08x]\n",
+ __FUNCTION__, pAd->MACVersion));
+
+
+ if ( !IS_MT7601(pAd) )
+ {
+ /* turn on bit13 (set to zero) after rt2860D. This is to solve high-current issue.*/
+ RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MACValue);
+ MACValue &= (~0x2000);
+ RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, MACValue);
+ }
+
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3);
+ RTMP_IO_WRITE32(pAd, USB_DMA_CFG, 0x0);
+
+#ifdef RTMP_MAC
+ RTUSBVenderReset(pAd);
+#endif
+ RTMPusecDelay(1000);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
+#endif /* RTMP_MAC_USB */
+
+#ifdef RTMP_MAC_USB
+ UsbCfg.word = 0;
+
+ /* USB1.1 do not use bulk in aggregation */
+ if (pAd->BulkInMaxPacketSize == 512)
+ UsbCfg.field.RxBulkAggEn = 1;
+
+ /* for last packet, PBF might use more than limited, so minus 2 to prevent from error */
+ UsbCfg.field.RxBulkAggLmt = (MAX_RXBULK_SIZE /1024)-3;
+ UsbCfg.field.RxBulkAggTOut = 0x80;
+
+ UsbCfg.field.RxBulkEn = 1;
+ UsbCfg.field.TxBulkEn = 1;
+
+ RTMP_IO_WRITE32(pAd, USB_DMA_CFG, UsbCfg.word);
+
+#ifdef MT7601
+ if ( IS_MT7601(pAd) )
+ {
+ UsbCfg.field.UDMA_RX_WL_DROP = 1;
+ RTMP_IO_WRITE32(pAd, USB_DMA_CFG, UsbCfg.word);
+
+ UsbCfg.field.UDMA_RX_WL_DROP = 0;
+ RTMP_IO_WRITE32(pAd, USB_DMA_CFG, UsbCfg.word);
+
+ }
+
+#endif /* MT7601 */
+
+#ifdef RLT_MAC
+ /* Select Q2 to receive command response */
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD);
+ AndesFunSetOP(pAd, Q_SELECT, pChipCap->CmdRspRxRing);
+ RTUSBBulkCmdRspEventReceive(pAd);
+
+ RTUSBBulkReceive(pAd);
+#endif /* RLT_MAC */
+#endif /* RTMP_MAC_USB */
+
+#if defined(RTMP_MAC_USB) && defined(RLT_MAC)
+
+ AndesRandomWritePair(pAd, MACRegTable, NUM_MAC_REG_PARMS);
+#else
+
+ /* Initialize MAC register to default value*/
+ for(Index=0; Index<NUM_MAC_REG_PARMS; Index++)
+ {
+ RTMP_IO_WRITE32(pAd, (USHORT)MACRegTable[Index].Register, MACRegTable[Index].Value);
+ }
+#endif /* defined(RTMP_MAC_USB) && defined(RLT_MAC) */
+
+ AsicInitBcnBuf(pAd);
+
+ /* re-set specific MAC registers for individual chip */
+ if (pAd->chipOps.AsicMacInit != NULL)
+ pAd->chipOps.AsicMacInit(pAd);
+
+
+ /* Before program BBP, we need to wait BBP/RF get wake up.*/
+ Index = 0;
+ do
+ {
+ RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MACValue);
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return NDIS_STATUS_FAILURE;
+
+ if ((MACValue & 0x03) == 0) /* if BB.RF is stable*/
+ break;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Check MAC_STATUS_CFG = Busy = %x\n", MACValue));
+ RTMPusecDelay(1000);
+ } while (Index++ < 100);
+
+
+#ifdef RTMP_MAC_USB
+ if ( !IS_MT7601(pAd) )
+ {
+ /* The commands to firmware should be after these commands, these commands will init firmware*/
+ /* PCI and USB are not the same because PCI driver needs to wait for PCI bus ready*/
+ RTUSBWriteMACRegister(pAd, H2M_BBP_AGENT, 0, FALSE); /* initialize BBP R/W access agent. */
+ RTUSBWriteMACRegister(pAd,H2M_MAILBOX_CSR,0, FALSE);
+ RTUSBWriteMACRegister(pAd, H2M_INT_SRC, 0, FALSE);
+ AsicSendCommandToMcu(pAd, 0x72, 0x00, 0x00, 0x00, FALSE); /* reset rf by MCU supported by new firmware */
+ }
+#endif /* RTMP_MAC_USB */
+
+ /* Wait to be stable.*/
+ RTMPusecDelay(1000);
+ pAd->LastMCUCmd = 0x72;
+
+ NICInitBBP(pAd);
+
+
+ if ((IS_RT3883(pAd)) || IS_RT65XX(pAd) || IS_MT7601(pAd) ||
+ ((pAd->MACVersion >= RALINK_2880E_VERSION) &&
+ (pAd->MACVersion < RALINK_3070_VERSION))) /* 3*3*/
+ {
+ /* enlarge MAX_LEN_CFG*/
+ UINT32 csr;
+ RTMP_IO_READ32(pAd, MAX_LEN_CFG, &csr);
+#if defined(RT2883) || defined(RT3883) || defined(RT3593) || defined(RT65xx) || defined(MT7601)
+ if (IS_RT2883(pAd) || IS_RT3883(pAd) || IS_RT3593(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd))
+ {
+ csr |= 0x3fff;
+ }
+ else
+#endif /* defined(RT2883) || defined(RT3883) || defined(RT3593) */
+ {
+ csr &= 0xFFF;
+ csr |= 0x2000;
+ }
+ RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, csr);
+ }
+
+#ifdef RTMP_MAC_USB
+#ifdef RLT_MAC
+ {
+ UINT32 MACValue[128 * 2];
+
+ for (Index = 0; Index < 128 * 2; Index+=2)
+ {
+ MACValue[Index] = 0xffffffff;
+ MACValue[Index + 1] = 0x00ffffff;
+ }
+
+ AndesBurstWrite(pAd, MAC_WCID_BASE, MACValue, 128 * 2);
+
+ }
+#else
+ {
+ UCHAR MAC_Value[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0,0};
+
+ /*Initialize WCID table*/
+ for(Index =0 ;Index < 254;Index++)
+ {
+ RTUSBMultiWrite(pAd, (USHORT)(MAC_WCID_BASE + Index * 8), MAC_Value, 8, FALSE);
+ }
+ }
+
+#endif /* RLT_MAC */
+#endif /* RTMP_MAC_USB */
+
+
+ /* Clear raw counters*/
+ NicResetRawCounters(pAd);
+
+ /* ASIC will keep garbage value after boot*/
+ /* Clear all shared key table when initial*/
+ /* This routine can be ignored in radio-ON/OFF operation. */
+ if (bHardReset)
+ {
+#if defined(RTMP_MAC_USB) && defined(RLT_MAC)
+ {
+ UINT32 MACValue[4];
+
+ for (Index = 0; Index < 4; Index++)
+ MACValue[Index] = 0;
+
+ AndesBurstWrite(pAd, SHARED_KEY_MODE_BASE, MACValue, 4);
+ }
+
+ /* Clear all pairwise key table when initial*/
+ {
+ UINT32 MACValue[256];
+
+ for (Index = 0; Index < 256; Index++)
+ MACValue[Index] = 1;
+
+ AndesBurstWrite(pAd, MAC_WCID_ATTRIBUTE_BASE, MACValue, 256);
+ }
+#else
+
+ printk("SHARED_KEY_MODE_BASE = %x\n", SHARED_KEY_MODE_BASE);
+ printk("MAC_WCID_ATTRIBUTE_BASE = %x\n", MAC_WCID_ATTRIBUTE_BASE);
+ for (KeyIdx = 0; KeyIdx < 4; KeyIdx++)
+ {
+ RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4*KeyIdx, 0);
+ }
+
+ /* Clear all pairwise key table when initial*/
+ for (KeyIdx = 0; KeyIdx < 256; KeyIdx++)
+ {
+ RTMP_IO_WRITE32(pAd, MAC_WCID_ATTRIBUTE_BASE + (KeyIdx * HW_WCID_ATTRI_SIZE), 1);
+ }
+#endif /* defined(RTMP_MAC_USB) && defined(RLT_MAC) */
+ }
+
+ /* assert HOST ready bit*/
+/* RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x0); 2004-09-14 asked by Mark*/
+/* RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x4);*/
+
+ /* It isn't necessary to clear this space when not hard reset. */
+ if (bHardReset == TRUE)
+ {
+ /* clear all on-chip BEACON frame space */
+#ifdef CONFIG_AP_SUPPORT
+ INT i, apidx;
+ for (apidx = 0; apidx < HW_BEACON_MAX_COUNT(pAd); apidx++)
+ {
+ if (pAd->BeaconOffset[apidx] > 0) {
+ // TODO: shiang-6590, if we didn't define MBSS_SUPPORT, the pAd->BeaconOffset[x] may set as 0 when chipCap.BcnMaxHwNum != HW_BEACON_MAX_COUNT
+ for (i = 0; i < HW_BEACON_OFFSET; i+=4)
+ RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[apidx] + i, 0x00, 4);
+ }
+#ifdef RTMP_MAC_USB
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if (pAd->CommonCfg.pBeaconSync)
+ pAd->CommonCfg.pBeaconSync->BeaconBitMap &= (~(BEACON_BITMAP_MASK & (1 << apidx)));
+ }
+#endif /* RTMP_MAC_USB */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+#ifdef RTMP_MAC_USB
+ AsicDisableSync(pAd);
+
+ /* Clear raw counters*/
+ NicResetRawCounters(pAd);
+
+ /* Default PCI clock cycle per ms is different as default setting, which is based on PCI.*/
+ RTMP_IO_READ32(pAd, USB_CYC_CFG, &Counter);
+ Counter&=0xffffff00;
+ Counter|=0x000001e;
+ RTMP_IO_WRITE32(pAd, USB_CYC_CFG, Counter);
+#endif /* RTMP_MAC_USB */
+
+
+#ifdef RT3290
+ if (IS_RT3290(pAd))
+ {
+ UINT32 coex_val;
+ //halt wlan tx when bt_rx_busy asserted
+ RTMP_IO_READ32(pAd, COEXCFG2, &coex_val);
+ coex_val |= 0x100;
+ RTMP_IO_WRITE32(pAd, COEXCFG2, coex_val);
+ }
+#endif /* RT3290 */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAsic\n"));
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+#endif /* CONFIG_AP_SUPPORT */
+
+VOID NICUpdateFifoStaCounters(
+ IN PRTMP_ADAPTER pAd)
+{
+ TX_STA_FIFO_STRUC StaFifo;
+ MAC_TABLE_ENTRY *pEntry = NULL;
+ UINT32 i = 0;
+ UCHAR pid = 0, wcid = 0;
+ INT32 reTry;
+ UCHAR succMCS;
+
+#ifdef RALINK_ATE
+ /* Nothing to do in ATE mode */
+ if (ATE_ON(pAd))
+ return;
+#endif /* RALINK_ATE */
+
+#ifdef RTMP_MAC_USB
+#endif /* RTMP_MAC_USB */
+
+
+#ifdef RT65xx
+ // TODO: shiang-6590, for 8592 now we have tx-status report packet from hardware!!
+ if (IS_RT65XX(pAd))
+ return;
+#endif /* RT65xx */
+
+
+ do
+ {
+ RTMP_IO_READ32(pAd, TX_STA_FIFO, &StaFifo.word);
+
+ if (StaFifo.field.bValid == 0)
+ break;
+
+ wcid = (UCHAR)StaFifo.field.wcid;
+
+#ifdef DBG_CTRL_SUPPORT
+#ifdef INCLUDE_DEBUG_QUEUE
+ if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFIFO) {
+ dbQueueEnqueue(0x73, (UCHAR *)(&StaFifo.word));
+ }
+#endif /* INCLUDE_DEBUG_QUEUE */
+#endif /* DBG_CTRL_SUPPORT */
+
+ /* ignore NoACK and MGMT frame use 0xFF as WCID */
+ if ((StaFifo.field.TxAckRequired == 0) || (wcid >= MAX_LEN_OF_MAC_TABLE))
+ {
+ i++;
+ continue;
+ }
+
+ /* PID store Tx MCS Rate */
+ pid = (UCHAR)StaFifo.field.PidType;
+
+ pEntry = &pAd->MacTab.Content[wcid];
+
+ pEntry->DebugFIFOCount++;
+
+
+#ifdef DOT11_N_SUPPORT
+#ifdef TXBF_SUPPORT
+ /* Update BF statistics*/
+ if (pAd->chipCap.FlgHwTxBfCap)
+ {
+ int succMCS = (StaFifo.field.SuccessRate & 0x7F);
+ int origMCS = pid;
+
+ if (succMCS==32)
+ origMCS = 32;
+#ifdef DOT11N_SS3_SUPPORT
+ if (succMCS>origMCS && pEntry->HTCapability.MCSSet[2]==0xff)
+ origMCS += 16;
+#endif /* DOT11N_SS3_SUPPORT */
+
+ if (succMCS>origMCS)
+ origMCS = succMCS+1;
+
+ /* MCS16 falls back to MCS8*/
+ if (origMCS>=16 && succMCS<=8)
+ succMCS += 8;
+
+ /* MCS8 falls back to 0 */
+ if (origMCS >= 8 && succMCS == 0)
+ succMCS += 7;
+
+ reTry = origMCS-succMCS;
+
+ if (StaFifo.field.eTxBF) {
+ if (StaFifo.field.TxSuccess)
+ pEntry->TxBFCounters.ETxSuccessCount++;
+ else
+ pEntry->TxBFCounters.ETxFailCount++;
+ pEntry->TxBFCounters.ETxRetryCount += reTry;
+ }
+ else if (StaFifo.field.iTxBF) {
+ if (StaFifo.field.TxSuccess)
+ pEntry->TxBFCounters.ITxSuccessCount++;
+ else
+ pEntry->TxBFCounters.ITxFailCount++;
+ pEntry->TxBFCounters.ITxRetryCount += reTry;
+ }
+ else {
+ if (StaFifo.field.TxSuccess)
+ pEntry->TxBFCounters.TxSuccessCount++;
+ else
+ pEntry->TxBFCounters.TxFailCount++;
+ pEntry->TxBFCounters.TxRetryCount += reTry;
+ }
+ }
+#endif /* TXBF_SUPPORT */
+#endif /* DOT11_N_SUPPORT */
+
+#ifdef UAPSD_SUPPORT
+ UAPSD_SP_AUE_Handle(pAd, pEntry, StaFifo.field.TxSuccess);
+#endif /* UAPSD_SUPPORT */
+
+
+ if (!StaFifo.field.TxSuccess)
+ {
+ pEntry->FIFOCount++;
+ pEntry->OneSecTxFailCount++;
+
+ if (pEntry->FIFOCount >= 1)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("#"));
+#ifdef DOT11_N_SUPPORT
+ pEntry->NoBADataCountDown = 64;
+#endif /* DOT11_N_SUPPORT */
+
+
+ /* Update the continuous transmission counter.*/
+ pEntry->ContinueTxFailCnt++;
+
+ if(pEntry->PsMode == PWR_ACTIVE)
+ {
+#ifdef DOT11_N_SUPPORT
+ int tid;
+ for (tid=0; tid<NUM_OF_TID; tid++)
+ BAOriSessionTearDown(pAd, pEntry->Aid, tid, FALSE, FALSE);
+#endif /* DOT11_N_SUPPORT */
+
+#ifdef WDS_SUPPORT
+ /* fix WDS Jam issue*/
+ if(IS_ENTRY_WDS(pEntry)
+ && (pEntry->LockEntryTx == FALSE)
+ && (pEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Entry %02x:%02x:%02x:%02x:%02x:%02x Blocked!! (Fail Cnt = %d)\n",
+ PRINT_MAC(pEntry->Addr), pEntry->ContinueTxFailCnt ));
+
+ pEntry->LockEntryTx = TRUE;
+ }
+#endif /* WDS_SUPPORT */
+ }
+ }
+#ifdef CONFIG_AP_SUPPORT
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ else
+ {
+#ifdef DOT11_N_SUPPORT
+ if ((pEntry->PsMode != PWR_SAVE) && (pEntry->NoBADataCountDown > 0))
+ {
+ pEntry->NoBADataCountDown--;
+ if (pEntry->NoBADataCountDown==0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("@\n"));
+ }
+ }
+#endif /* DOT11_N_SUPPORT */
+ pEntry->FIFOCount = 0;
+ pEntry->OneSecTxNoRetryOkCount++;
+
+
+ /* update NoDataIdleCount when sucessful send packet to STA.*/
+ pEntry->NoDataIdleCount = 0;
+ pEntry->ContinueTxFailCnt = 0;
+#ifdef WDS_SUPPORT
+ pEntry->LockEntryTx = FALSE;
+#endif /* WDS_SUPPORT */
+
+ }
+
+ succMCS = StaFifo.field.SuccessRate & 0x7F;
+#ifdef DOT11N_SS3_SUPPORT
+ if (pEntry->HTCapability.MCSSet[2] == 0xff)
+ {
+ if (succMCS > pid)
+ pid = pid + 16;
+ }
+#endif /* DOT11N_SS3_SUPPORT */
+
+ if (StaFifo.field.TxSuccess)
+ {
+ pEntry->TXMCSExpected[pid]++;
+ if (pid == succMCS)
+ pEntry->TXMCSSuccessful[pid]++;
+ else
+ pEntry->TXMCSAutoFallBack[pid][succMCS]++;
+ }
+ else
+ {
+ pEntry->TXMCSFailed[pid]++;
+ }
+
+#ifdef DOT11N_SS3_SUPPORT
+ if (pid >= 16 && succMCS <= 8)
+ succMCS += (2 - (succMCS >> 3)) * 7;
+#endif /* DOT11N_SS3_SUPPORT */
+
+ reTry = pid - succMCS;
+
+ if (reTry > 0)
+ {
+ /* MCS8 falls back to 0 */
+ if (pid>=8 && succMCS==0)
+ reTry -= 7;
+ else if ((pid >= 12) && succMCS <=7)
+ reTry -= 4;
+
+ pEntry->OneSecTxRetryOkCount += reTry;
+ }
+
+ i++; /* ASIC store 16 stack*/
+ } while ( i < (TX_RING_SIZE<<1) );
+
+}
+
+
+#ifdef FIFO_EXT_SUPPORT
+BOOLEAN NicGetMacFifoTxCnt(
+ IN RTMP_ADAPTER *pAd,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ if (pEntry->Aid >= 1 && pEntry->Aid <= 8)
+ {
+ WCID_TX_CNT_STRUC wcidTxCnt;
+ UINT32 regAddr;
+
+ regAddr = WCID_TX_CNT_0 + (pEntry->Aid - 1) * 4;
+ RTMP_IO_READ32(pAd, regAddr, &wcidTxCnt.word);
+
+ pEntry->fifoTxSucCnt += wcidTxCnt.field.succCnt;
+ pEntry->fifoTxRtyCnt += wcidTxCnt.field.reTryCnt;
+ }
+
+ return TRUE;
+}
+
+
+VOID AsicFifoExtSet(IN RTMP_ADAPTER *pAd)
+{
+ if (pAd->chipCap.FlgHwFifoExtCap)
+ {
+ RTMP_IO_WRITE32(pAd, WCID_MAPPING_0, 0x04030201);
+ RTMP_IO_WRITE32(pAd, WCID_MAPPING_1, 0x08070605);
+ }
+}
+
+
+VOID AsicFifoExtEntryClean(
+ IN RTMP_ADAPTER * pAd,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ WCID_TX_CNT_STRUC wcidTxCnt;
+ UINT32 regAddr;
+
+ if (pAd->chipCap.FlgHwFifoExtCap)
+ {
+ /* We clean the fifo info when MCS is 0 and Aid is from 1~8 */
+ if (pEntry->Aid >=1 && pEntry->Aid <= 8)
+ {
+ regAddr = WCID_TX_CNT_0 + (pEntry->Aid - 1) * 4;
+ RTMP_IO_READ32(pAd, regAddr, &wcidTxCnt.word);
+ }
+ }
+}
+#endif /* FIFO_EXT_SUPPORT */
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Read Tx statistic raw counters from hardware registers and record to
+ related software variables for later on query
+
+ Arguments:
+ pAd Pointer to our adapter
+ pStaTxCnt0 Pointer to record "TX_STA_CNT0" (0x170c)
+ pStaTxCnt1 Pointer to record "TX_STA_CNT1" (0x1710)
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID NicGetTxRawCounters(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_STA_CNT0_STRUC *pStaTxCnt0,
+ IN TX_STA_CNT1_STRUC *pStaTxCnt1)
+{
+
+ RTMP_IO_READ32(pAd, TX_STA_CNT0, &pStaTxCnt0->word);
+ RTMP_IO_READ32(pAd, TX_STA_CNT1, &pStaTxCnt1->word);
+
+ pAd->bUpdateBcnCntDone = TRUE; /* not appear in Rory's code */
+ pAd->RalinkCounters.OneSecBeaconSentCnt += pStaTxCnt0->field.TxBeaconCount;
+ pAd->RalinkCounters.OneSecTxRetryOkCount += pStaTxCnt1->field.TxRetransmit;
+ pAd->RalinkCounters.OneSecTxNoRetryOkCount += pStaTxCnt1->field.TxSuccess;
+ pAd->RalinkCounters.OneSecTxFailCount += pStaTxCnt0->field.TxFailCount;
+
+#ifdef STATS_COUNT_SUPPORT
+ pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += pStaTxCnt1->field.TxSuccess;
+ pAd->WlanCounters.RetryCount.u.LowPart += pStaTxCnt1->field.TxRetransmit;
+ pAd->WlanCounters.FailedCount.u.LowPart += pStaTxCnt0->field.TxFailCount;
+#endif /* STATS_COUNT_SUPPORT */
+
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Clean all Tx/Rx statistic raw counters from hardware registers
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID NicResetRawCounters(RTMP_ADAPTER *pAd)
+{
+ UINT32 Counter;
+
+ RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter);
+ RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter);
+ RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter);
+ RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter);
+ RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter);
+ RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Read statistical counters from hardware registers and record them
+ in software variables for later on query
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+VOID NICUpdateRawCounters(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 OldValue;/*, Value2;*/
+ /*ULONG PageSum, OneSecTransmitCount;*/
+ /*ULONG TxErrorRatio, Retry, Fail;*/
+ RX_STA_CNT0_STRUC RxStaCnt0;
+ RX_STA_CNT1_STRUC RxStaCnt1;
+ RX_STA_CNT2_STRUC RxStaCnt2;
+ TX_STA_CNT0_STRUC TxStaCnt0;
+ TX_STA_CNT1_STRUC StaTx1;
+ TX_STA_CNT2_STRUC StaTx2;
+#ifdef STATS_COUNT_SUPPORT
+ TX_NAG_AGG_CNT_STRUC TxAggCnt;
+ TX_AGG_CNT0_STRUC TxAggCnt0;
+ TX_AGG_CNT1_STRUC TxAggCnt1;
+ TX_AGG_CNT2_STRUC TxAggCnt2;
+ TX_AGG_CNT3_STRUC TxAggCnt3;
+ TX_AGG_CNT4_STRUC TxAggCnt4;
+ TX_AGG_CNT5_STRUC TxAggCnt5;
+ TX_AGG_CNT6_STRUC TxAggCnt6;
+ TX_AGG_CNT7_STRUC TxAggCnt7;
+#endif /* STATS_COUNT_SUPPORT */
+ COUNTER_RALINK *pRalinkCounters;
+
+
+ pRalinkCounters = &pAd->RalinkCounters;
+#ifdef RTMP_MAC_USB
+#ifdef STATS_COUNT_SUPPORT
+ if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
+ return;
+
+ if(RTMP_TEST_FLAG(pAd, fRTMP_PS_MCU_SLEEP))
+ return;
+#endif /* STATS_COUNT_SUPPORT */
+#endif /* RTMP_MAC_USB */
+
+
+ RTMP_IO_READ32(pAd, RX_STA_CNT0, &RxStaCnt0.word);
+ RTMP_IO_READ32(pAd, RX_STA_CNT2, &RxStaCnt2.word);
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef CARRIER_DETECTION_SUPPORT
+ if ((pAd->CommonCfg.CarrierDetect.Enable == FALSE) || (pAd->OpMode == OPMODE_STA))
+#endif /* CARRIER_DETECTION_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ {
+#ifdef MICROWAVE_OVEN_SUPPORT
+ /* Update RX PLCP error counter*/
+ pAd->PrivateInfo.PhyRxErrCnt += NICSumPLCPErrCnt(pAd); /* get PLCP error count per sec */
+ /* Update False CCA counter*/
+ pAd->RalinkCounters.OneSecFalseCCACnt += NICSumFalseCCACnt(pAd); /* get FalseCCA count per sec */
+ pAd->RalinkCounters.FalseCCACnt += pAd->RalinkCounters.OneSecFalseCCACnt;
+#else
+ RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word);
+ /* Update RX PLCP error counter*/
+ pAd->PrivateInfo.PhyRxErrCnt += RxStaCnt1.field.PlcpErr;
+ /* Update False CCA counter*/
+ pAd->RalinkCounters.OneSecFalseCCACnt += RxStaCnt1.field.FalseCca;
+ pAd->RalinkCounters.FalseCCACnt += RxStaCnt1.field.FalseCca;
+
+#endif /* MICROWAVE_OVEN_SUPPORT */
+ }
+
+#ifdef STATS_COUNT_SUPPORT
+ /* Update FCS counters*/
+ OldValue= pAd->WlanCounters.FCSErrorCount.u.LowPart;
+ pAd->WlanCounters.FCSErrorCount.u.LowPart += (RxStaCnt0.field.CrcErr); /* >> 7);*/
+ if (pAd->WlanCounters.FCSErrorCount.u.LowPart < OldValue)
+ pAd->WlanCounters.FCSErrorCount.u.HighPart++;
+#endif /* STATS_COUNT_SUPPORT */
+
+ /* Add FCS error count to private counters*/
+ pRalinkCounters->OneSecRxFcsErrCnt += RxStaCnt0.field.CrcErr;
+ OldValue = pRalinkCounters->RealFcsErrCount.u.LowPart;
+ pRalinkCounters->RealFcsErrCount.u.LowPart += RxStaCnt0.field.CrcErr;
+ if (pRalinkCounters->RealFcsErrCount.u.LowPart < OldValue)
+ pRalinkCounters->RealFcsErrCount.u.HighPart++;
+
+ /* Update Duplicate Rcv check*/
+ pRalinkCounters->DuplicateRcv += RxStaCnt2.field.RxDupliCount;
+#ifdef STATS_COUNT_SUPPORT
+ pAd->WlanCounters.FrameDuplicateCount.u.LowPart += RxStaCnt2.field.RxDupliCount;
+#endif /* STATS_COUNT_SUPPORT */
+ /* Update RX Overflow counter*/
+ pAd->Counters8023.RxNoBuffer += (RxStaCnt2.field.RxFifoOverflowCount);
+
+ /*pAd->RalinkCounters.RxCount = 0;*/
+#ifdef RTMP_MAC_USB
+ if (pRalinkCounters->RxCount != pAd->watchDogRxCnt)
+ {
+ pAd->watchDogRxCnt = pRalinkCounters->RxCount;
+ pAd->watchDogRxOverFlowCnt = 0;
+ }
+ else
+ {
+ if (RxStaCnt2.field.RxFifoOverflowCount)
+ pAd->watchDogRxOverFlowCnt++;
+ else
+ pAd->watchDogRxOverFlowCnt = 0;
+ }
+#endif /* RTMP_MAC_USB */
+
+
+ /*if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) || */
+ /* (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) && (pAd->MacTab.Size != 1)))*/
+ if (!pAd->bUpdateBcnCntDone)
+ {
+ /* Update BEACON sent count*/
+ NicGetTxRawCounters(pAd, &TxStaCnt0, &StaTx1);
+ RTMP_IO_READ32(pAd, TX_STA_CNT2, &StaTx2.word);
+ }
+
+
+ /*if (pAd->bStaFifoTest == TRUE)*/
+#ifdef STATS_COUNT_SUPPORT
+ {
+ RTMP_IO_READ32(pAd, TX_AGG_CNT, &TxAggCnt.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT0, &TxAggCnt0.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT1, &TxAggCnt1.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT2, &TxAggCnt2.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT3, &TxAggCnt3.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT4, &TxAggCnt4.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT5, &TxAggCnt5.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT6, &TxAggCnt6.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT7, &TxAggCnt7.word);
+ pRalinkCounters->TxAggCount += TxAggCnt.field.AggTxCount;
+ pRalinkCounters->TxNonAggCount += TxAggCnt.field.NonAggTxCount;
+ pRalinkCounters->TxAgg1MPDUCount += TxAggCnt0.field.AggSize1Count;
+ pRalinkCounters->TxAgg2MPDUCount += TxAggCnt0.field.AggSize2Count;
+
+ pRalinkCounters->TxAgg3MPDUCount += TxAggCnt1.field.AggSize3Count;
+ pRalinkCounters->TxAgg4MPDUCount += TxAggCnt1.field.AggSize4Count;
+ pRalinkCounters->TxAgg5MPDUCount += TxAggCnt2.field.AggSize5Count;
+ pRalinkCounters->TxAgg6MPDUCount += TxAggCnt2.field.AggSize6Count;
+
+ pRalinkCounters->TxAgg7MPDUCount += TxAggCnt3.field.AggSize7Count;
+ pRalinkCounters->TxAgg8MPDUCount += TxAggCnt3.field.AggSize8Count;
+ pRalinkCounters->TxAgg9MPDUCount += TxAggCnt4.field.AggSize9Count;
+ pRalinkCounters->TxAgg10MPDUCount += TxAggCnt4.field.AggSize10Count;
+
+ pRalinkCounters->TxAgg11MPDUCount += TxAggCnt5.field.AggSize11Count;
+ pRalinkCounters->TxAgg12MPDUCount += TxAggCnt5.field.AggSize12Count;
+ pRalinkCounters->TxAgg13MPDUCount += TxAggCnt6.field.AggSize13Count;
+ pRalinkCounters->TxAgg14MPDUCount += TxAggCnt6.field.AggSize14Count;
+
+ pRalinkCounters->TxAgg15MPDUCount += TxAggCnt7.field.AggSize15Count;
+ pRalinkCounters->TxAgg16MPDUCount += TxAggCnt7.field.AggSize16Count;
+
+ /* Calculate the transmitted A-MPDU count*/
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += TxAggCnt0.field.AggSize1Count;
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt0.field.AggSize2Count >> 1);
+
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize3Count / 3);
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize4Count >> 2);
+
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize5Count / 5);
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize6Count / 6);
+
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize7Count / 7);
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize8Count >> 3);
+
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize9Count / 9);
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize10Count / 10);
+
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize11Count / 11);
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize12Count / 12);
+
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize13Count / 13);
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize14Count / 14);
+
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize15Count / 15);
+ pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize16Count >> 4);
+ }
+#endif /* STATS_COUNT_SUPPORT */
+
+#ifdef DBG_DIAGNOSE
+ {
+ RtmpDiagStruct *pDiag;
+ UCHAR ArrayCurIdx, i;
+
+ pDiag = &pAd->DiagStruct;
+ ArrayCurIdx = pDiag->ArrayCurIdx;
+
+ if (pDiag->inited == 0)
+ {
+ NdisZeroMemory(pDiag, sizeof(struct _RtmpDiagStrcut_));
+ pDiag->ArrayStartIdx = pDiag->ArrayCurIdx = 0;
+ pDiag->inited = 1;
+ }
+ else
+ {
+ /* Tx*/
+ pDiag->TxFailCnt[ArrayCurIdx] = TxStaCnt0.field.TxFailCount;
+ pDiag->TxAggCnt[ArrayCurIdx] = TxAggCnt.field.AggTxCount;
+ pDiag->TxNonAggCnt[ArrayCurIdx] = TxAggCnt.field.NonAggTxCount;
+
+ pDiag->TxAMPDUCnt[ArrayCurIdx][0] = TxAggCnt0.field.AggSize1Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][1] = TxAggCnt0.field.AggSize2Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][2] = TxAggCnt1.field.AggSize3Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][3] = TxAggCnt1.field.AggSize4Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][4] = TxAggCnt2.field.AggSize5Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][5] = TxAggCnt2.field.AggSize6Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][6] = TxAggCnt3.field.AggSize7Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][7] = TxAggCnt3.field.AggSize8Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][8] = TxAggCnt4.field.AggSize9Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][9] = TxAggCnt4.field.AggSize10Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][10] = TxAggCnt5.field.AggSize11Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][11] = TxAggCnt5.field.AggSize12Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][12] = TxAggCnt6.field.AggSize13Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][13] = TxAggCnt6.field.AggSize14Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][14] = TxAggCnt7.field.AggSize15Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][15] = TxAggCnt7.field.AggSize16Count;
+
+ pDiag->RxCrcErrCnt[ArrayCurIdx] = RxStaCnt0.field.CrcErr;
+
+ INC_RING_INDEX(pDiag->ArrayCurIdx, DIAGNOSE_TIME);
+ ArrayCurIdx = pDiag->ArrayCurIdx;
+ for (i =0; i < 9; i++)
+ {
+ pDiag->TxDescCnt[ArrayCurIdx][i]= 0;
+ pDiag->TxSWQueCnt[ArrayCurIdx][i] =0;
+ pDiag->TxMcsCnt[ArrayCurIdx][i] = 0;
+ pDiag->RxMcsCnt[ArrayCurIdx][i] = 0;
+ }
+ pDiag->TxDataCnt[ArrayCurIdx] = 0;
+ pDiag->TxFailCnt[ArrayCurIdx] = 0;
+ pDiag->RxDataCnt[ArrayCurIdx] = 0;
+ pDiag->RxCrcErrCnt[ArrayCurIdx] = 0;
+/* for (i = 9; i < 16; i++)*/
+ for (i = 9; i < 24; i++) /* 3*3*/
+ {
+ pDiag->TxDescCnt[ArrayCurIdx][i] = 0;
+ pDiag->TxMcsCnt[ArrayCurIdx][i] = 0;
+ pDiag->RxMcsCnt[ArrayCurIdx][i] = 0;
+}
+
+ if (pDiag->ArrayCurIdx == pDiag->ArrayStartIdx)
+ INC_RING_INDEX(pDiag->ArrayStartIdx, DIAGNOSE_TIME);
+ }
+
+ }
+#endif /* DBG_DIAGNOSE */
+
+
+}
+
+NDIS_STATUS NICLoadFirmware(
+ IN PRTMP_ADAPTER pAd)
+{
+ NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+
+ if (pAd->chipOps.loadFirmware)
+ status = pAd->chipOps.loadFirmware(pAd);
+ return status;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ erase 8051 firmware image in MAC ASIC
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ IRQL = PASSIVE_LEVEL
+
+ ========================================================================
+*/
+VOID NICEraseFirmware(
+ IN PRTMP_ADAPTER pAd)
+{
+ if (pAd->chipOps.eraseFirmware)
+ pAd->chipOps.eraseFirmware(pAd);
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Compare two memory block
+
+ Arguments:
+ pSrc1 Pointer to first memory address
+ pSrc2 Pointer to second memory address
+
+ Return Value:
+ 0: memory is equal
+ 1: pSrc1 memory is larger
+ 2: pSrc2 memory is larger
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+ULONG RTMPCompareMemory(
+ IN PVOID pSrc1,
+ IN PVOID pSrc2,
+ IN ULONG Length)
+{
+ PUCHAR pMem1;
+ PUCHAR pMem2;
+ ULONG Index = 0;
+
+ pMem1 = (PUCHAR) pSrc1;
+ pMem2 = (PUCHAR) pSrc2;
+
+ for (Index = 0; Index < Length; Index++)
+ {
+ if (pMem1[Index] > pMem2[Index])
+ return (1);
+ else if (pMem1[Index] < pMem2[Index])
+ return (2);
+ }
+
+ /* Equal*/
+ return (0);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Zero out memory block
+
+ Arguments:
+ pSrc1 Pointer to memory address
+ Length Size
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPZeroMemory(
+ IN PVOID pSrc,
+ IN ULONG Length)
+{
+ PUCHAR pMem;
+ ULONG Index = 0;
+
+ pMem = (PUCHAR) pSrc;
+
+ for (Index = 0; Index < Length; Index++)
+ {
+ pMem[Index] = 0x00;
+ }
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Copy data from memory block 1 to memory block 2
+
+ Arguments:
+ pDest Pointer to destination memory address
+ pSrc Pointer to source memory address
+ Length Copy size
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPMoveMemory(
+ OUT PVOID pDest,
+ IN PVOID pSrc,
+ IN ULONG Length)
+{
+ PUCHAR pMem1;
+ PUCHAR pMem2;
+ UINT Index;
+
+ ASSERT((Length==0) || (pDest && pSrc));
+
+ pMem1 = (PUCHAR) pDest;
+ pMem2 = (PUCHAR) pSrc;
+
+ for (Index = 0; Index < Length; Index++)
+ {
+ pMem1[Index] = pMem2[Index];
+ }
+}
+
+VOID UserCfgExit(
+ IN RTMP_ADAPTER *pAd)
+{
+#ifdef DOT11_N_SUPPORT
+ BATableExit(pAd);
+#endif /* DOT11_N_SUPPORT */
+
+
+ NdisFreeSpinLock(&pAd->MacTabLock);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Initialize port configuration structure
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID UserCfgInit(RTMP_ADAPTER *pAd)
+{
+ UINT i;
+#ifdef CONFIG_AP_SUPPORT
+ UINT j;
+#endif /* CONFIG_AP_SUPPORT */
+/* EDCA_PARM DefaultEdcaParm;*/
+ UINT key_index, bss_index;
+ UINT8 TXWISize = pAd->chipCap.TXWISize;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit\n"));
+
+ pAd->IndicateMediaState = NdisMediaStateDisconnected;
+
+ /* part I. intialize common configuration*/
+ pAd->CommonCfg.BasicRateBitmap = 0xF;
+ pAd->CommonCfg.BasicRateBitmapOld = 0xF;
+#ifdef CONFIG_MULTI_CHANNEL
+ pAd->Multi_Channel_Enable = FALSE;
+#endif /* CONFIG_MULTI_CHANNEL */
+
+#ifdef RTMP_MAC_USB
+ pAd->BulkOutReq = 0;
+
+ pAd->BulkOutComplete = 0;
+ pAd->BulkOutCompleteOther = 0;
+ pAd->BulkOutCompleteCancel = 0;
+ pAd->BulkInReq = 0;
+ pAd->BulkInComplete = 0;
+ pAd->BulkInCompleteFail = 0;
+
+ /*pAd->QuickTimerP = 100;*/
+ /*pAd->TurnAggrBulkInCount = 0;*/
+ pAd->bUsbTxBulkAggre = 0;
+
+#ifdef LED_CONTROL_SUPPORT
+ /* init as unsed value to ensure driver will set to MCU once.*/
+ pAd->LedCntl.LedIndicatorStrength = 0xFF;
+#endif /* LED_CONTROL_SUPPORT */
+
+ pAd->CommonCfg.MaxPktOneTxBulk = 2;
+ pAd->CommonCfg.TxBulkFactor = 1;
+ pAd->CommonCfg.RxBulkFactor =1;
+
+ pAd->CommonCfg.TxPower = 100; /*mW*/
+
+ NdisZeroMemory(&pAd->CommonCfg.IOTestParm, sizeof(pAd->CommonCfg.IOTestParm));
+
+#endif /* RTMP_MAC_USB */
+
+ for(key_index=0; key_index<SHARE_KEY_NUM; key_index++)
+ {
+ for(bss_index = 0; bss_index < MAX_MBSSID_NUM(pAd) + MAX_P2P_NUM; bss_index++)
+ {
+ pAd->SharedKey[bss_index][key_index].KeyLen = 0;
+ pAd->SharedKey[bss_index][key_index].CipherAlg = CIPHER_NONE;
+ }
+ }
+
+ pAd->bLocalAdminMAC = FALSE;
+ pAd->EepromAccess = FALSE;
+
+ pAd->Antenna.word = 0;
+ pAd->CommonCfg.BBPCurrentBW = BW_20;
+
+
+ pAd->bAutoTxAgcA = FALSE; /* Default is OFF*/
+ pAd->bAutoTxAgcG = FALSE; /* Default is OFF*/
+
+#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION)
+ pAd->TxPowerCtrl.bInternalTxALC = FALSE; /* Off by default */
+ pAd->TxPowerCtrl.idxTxPowerTable = 0;
+ pAd->TxPowerCtrl.idxTxPowerTable2 = 0;
+#ifdef RTMP_TEMPERATURE_COMPENSATION
+ pAd->TxPowerCtrl.LookupTableIndex = 0;
+#endif /* RTMP_TEMPERATURE_COMPENSATION */
+#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */
+
+ pAd->RfIcType = RFIC_2820;
+
+ /* Init timer for reset complete event*/
+ pAd->CommonCfg.CentralChannel = 1;
+ pAd->bForcePrintTX = FALSE;
+ pAd->bForcePrintRX = FALSE;
+ pAd->bStaFifoTest = FALSE;
+ pAd->bProtectionTest = FALSE;
+ pAd->bHCCATest = FALSE;
+ pAd->bGenOneHCCA = FALSE;
+ pAd->CommonCfg.Dsifs = 10; /* in units of usec */
+ pAd->CommonCfg.TxPower = 100; /* mW*/
+ pAd->CommonCfg.TxPowerPercentage = 0xffffffff; /* AUTO*/
+ pAd->CommonCfg.TxPowerDefault = 0xffffffff; /* AUTO*/
+ pAd->CommonCfg.TxPreamble = Rt802_11PreambleAuto; /* use Long preamble on TX by defaut*/
+ pAd->CommonCfg.bUseZeroToDisableFragment = FALSE;
+ pAd->CommonCfg.RtsThreshold = 2347;
+ pAd->CommonCfg.FragmentThreshold = 2346;
+ pAd->CommonCfg.UseBGProtection = 0; /* 0: AUTO*/
+ pAd->CommonCfg.bEnableTxBurst = TRUE; /* 0; */
+ pAd->CommonCfg.PhyMode = 0xff; /* unknown*/
+ pAd->CommonCfg.SavedPhyMode = pAd->CommonCfg.PhyMode;
+
+
+#ifdef CONFIG_AP_SUPPORT
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CARRIER_DETECTION_SUPPORT
+ pAd->CommonCfg.CarrierDetect.delta = CARRIER_DETECT_DELTA;
+ pAd->CommonCfg.CarrierDetect.div_flag = CARRIER_DETECT_DIV_FLAG;
+ pAd->CommonCfg.CarrierDetect.criteria = CARRIER_DETECT_CRITIRIA;
+ pAd->CommonCfg.CarrierDetect.threshold = CARRIER_DETECT_THRESHOLD;
+ pAd->CommonCfg.CarrierDetect.recheck1 = CARRIER_DETECT_RECHECK_TIME;
+ pAd->CommonCfg.CarrierDetect.CarrierGoneThreshold = CARRIER_GONE_TRESHOLD;
+ pAd->CommonCfg.CarrierDetect.VGA_Mask = CARRIER_DETECT_DEFAULT_MASK;
+ pAd->CommonCfg.CarrierDetect.Packet_End_Mask = CARRIER_DETECT_DEFAULT_MASK;
+ pAd->CommonCfg.CarrierDetect.Rx_PE_Mask = CARRIER_DETECT_DEFAULT_MASK;
+#endif /* CARRIER_DETECTION_SUPPORT */
+
+#ifdef DFS_SUPPORT
+ pAd->CommonCfg.RadarDetect.bDfsInit = FALSE;
+#endif /* DFS_SUPPORT */
+
+ pAd->Dot11_H.ChMovingTime = 65;
+
+#ifdef UAPSD_SUPPORT
+#ifdef CONFIG_AP_SUPPORT
+{
+ UINT32 IdMbss;
+
+ for(IdMbss=0; IdMbss<HW_BEACON_MAX_NUM; IdMbss++)
+ UAPSD_INFO_INIT(&pAd->ApCfg.MBSSID[IdMbss].UapsdInfo);
+}
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* UAPSD_SUPPORT */
+ pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
+ pAd->CommonCfg.TriggerTimerCount = 0;
+ pAd->CommonCfg.bAPSDForcePowerSave = FALSE;
+ /*pAd->CommonCfg.bCountryFlag = FALSE;*/
+ pAd->CommonCfg.TxStream = 0;
+ pAd->CommonCfg.RxStream = 0;
+
+ NdisZeroMemory(&pAd->BeaconTxWI, TXWISize);
+
+#ifdef DOT11_N_SUPPORT
+ NdisZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability));
+ pAd->HTCEnable = FALSE;
+ pAd->bBroadComHT = FALSE;
+ pAd->CommonCfg.bRdg = FALSE;
+
+#ifdef DOT11N_DRAFT3
+ pAd->CommonCfg.Dot11OBssScanPassiveDwell = dot11OBSSScanPassiveDwell; /* Unit : TU. 5~1000*/
+ pAd->CommonCfg.Dot11OBssScanActiveDwell = dot11OBSSScanActiveDwell; /* Unit : TU. 10~1000*/
+ pAd->CommonCfg.Dot11BssWidthTriggerScanInt = dot11BSSWidthTriggerScanInterval; /* Unit : Second */
+ pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = dot11OBSSScanPassiveTotalPerChannel; /* Unit : TU. 200~10000*/
+ pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = dot11OBSSScanActiveTotalPerChannel; /* Unit : TU. 20~10000*/
+ pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = dot11BSSWidthChannelTransactionDelayFactor;
+ pAd->CommonCfg.Dot11OBssScanActivityThre = dot11BSSScanActivityThreshold; /* Unit : percentage*/
+ pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor);
+
+ pAd->CommonCfg.bBssCoexEnable = TRUE; /* by default, we enable this feature, you can disable it via the profile or ioctl command*/
+ pAd->CommonCfg.BssCoexApCntThr = 0;
+ pAd->CommonCfg.Bss2040NeedFallBack = 0;
+#endif /* DOT11N_DRAFT3 */
+
+ NdisZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo));
+ pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE;
+ pAd->CommonCfg.BACapability.field.MpduDensity = 0;
+ pAd->CommonCfg.BACapability.field.Policy = IMMED_BA;
+ pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; /*32;*/
+ pAd->CommonCfg.BACapability.field.TxBAWinLimit = 64; /*32;*/
+ DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit. BACapability = 0x%x\n", pAd->CommonCfg.BACapability.word));
+
+ pAd->CommonCfg.BACapability.field.AutoBA = FALSE;
+ BATableInit(pAd, &pAd->BATable);
+
+ pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1;
+ pAd->CommonCfg.bHTProtect = 1;
+ pAd->CommonCfg.bMIMOPSEnable = TRUE;
+#ifdef GREENAP_SUPPORT
+ pAd->ApCfg.bGreenAPEnable=FALSE;
+ pAd->ApCfg.bGreenAPActive = FALSE;
+ pAd->ApCfg.GreenAPLevel= GREENAP_WITHOUT_ANY_STAS_CONNECT;
+#endif /* GREENAP_SUPPORT */
+ pAd->CommonCfg.bBADecline = FALSE;
+ pAd->CommonCfg.bDisableReordering = FALSE;
+
+ if (pAd->MACVersion == 0x28720200)
+ pAd->CommonCfg.TxBASize = 13; /*by Jerry recommend*/
+ else
+ pAd->CommonCfg.TxBASize = 7;
+
+ pAd->CommonCfg.REGBACapability.word = pAd->CommonCfg.BACapability.word;
+#endif /* DOT11_N_SUPPORT */
+
+ /*pAd->CommonCfg.HTPhyMode.field.BW = BW_20;*/
+ /*pAd->CommonCfg.HTPhyMode.field.MCS = MCS_AUTO;*/
+ /*pAd->CommonCfg.HTPhyMode.field.ShortGI = GI_800;*/
+ /*pAd->CommonCfg.HTPhyMode.field.STBC = STBC_NONE;*/
+ pAd->CommonCfg.TxRate = RATE_6;
+
+ pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6;
+ pAd->CommonCfg.MlmeTransmit.field.BW = BW_20;
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+
+ pAd->CommonCfg.BeaconPeriod = 100; /* in mSec*/
+
+#ifdef STREAM_MODE_SUPPORT
+ if (pAd->chipCap.FlgHwStreamMode)
+ {
+ pAd->CommonCfg.StreamMode = 3;
+ pAd->CommonCfg.StreamModeMCS = 0x0B0B;
+ }
+#endif /* STREAM_MODE_SUPPORT */
+
+#ifdef TXBF_SUPPORT
+ pAd->CommonCfg.ETxBfNoncompress = 0;
+ pAd->CommonCfg.ETxBfIncapable = 0;
+#endif /* TXBF_SUPPORT */
+
+#ifdef NEW_RATE_ADAPT_SUPPORT
+ pAd->CommonCfg.lowTrafficThrd = 2;
+ pAd->CommonCfg.TrainUpRule = 2; // 1;
+ pAd->CommonCfg.TrainUpRuleRSSI = -70; // 0;
+ pAd->CommonCfg.TrainUpLowThrd = 90;
+ pAd->CommonCfg.TrainUpHighThrd = 110;
+#endif /* NEW_RATE_ADAPT_SUPPORT */
+
+
+
+#ifdef CFO_TRACK
+#endif /* CFO_TRACK */
+
+#ifdef DBG_CTRL_SUPPORT
+ pAd->CommonCfg.DebugFlags = 0;
+#endif /* DBG_CTRL_SUPPORT */
+
+#ifdef WAPI_SUPPORT
+ pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_DISABLE;
+ pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_DISABLE;
+ pAd->CommonCfg.wapi_msk_rekey_cnt = 0;
+#endif /* WAPI_SUPPORT */
+
+#ifdef MCAST_RATE_SPECIFIC
+ pAd->CommonCfg.MCastPhyMode.word
+ = pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word;
+#endif /* MCAST_RATE_SPECIFIC */
+
+ /* WFA policy - disallow TH rate in WEP or TKIP cipher */
+ pAd->CommonCfg.HT_DisallowTKIP = TRUE;
+
+ /* Frequency for rate adaptation */
+ pAd->ra_interval = DEF_RA_TIME_INTRVAL;
+ pAd->ra_fast_interval = DEF_QUICK_RA_TIME_INTERVAL;
+
+#ifdef AGS_SUPPORT
+ if (pAd->rateAlg == RATE_ALG_AGS)
+ pAd->ra_fast_interval = AGS_QUICK_RA_TIME_INTERVAL;
+#endif /* AGS_SUPPORT */
+
+ /* Tx Sw queue length setting */
+ pAd->TxSwQMaxLen = MAX_PACKETS_IN_QUEUE;
+
+ pAd->CommonCfg.bRalinkBurstMode = FALSE;
+
+
+ /* global variables mXXXX used in MAC protocol state machines*/
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON);
+
+ /* PHY specification*/
+ pAd->CommonCfg.PhyMode = (WMODE_B | WMODE_G); /* default PHY mode*/
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); /* CCK use LONG preamble*/
+
+
+ /* Default for extra information is not valid*/
+ pAd->ExtraInfo = EXTRA_INFO_CLEAR;
+
+ /* Default Config change flag*/
+ pAd->bConfigChanged = FALSE;
+
+ /* */
+ /* part III. AP configurations*/
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* Set MBSS Default Configurations*/
+ pAd->ApCfg.BssidNum = MAX_MBSSID_NUM(pAd);
+ for(j = BSS0; j < pAd->ApCfg.BssidNum; j++)
+ {
+ pAd->ApCfg.MBSSID[j].AuthMode = Ndis802_11AuthModeOpen;
+ pAd->ApCfg.MBSSID[j].WepStatus = Ndis802_11EncryptionDisabled;
+ pAd->ApCfg.MBSSID[j].GroupKeyWepStatus = Ndis802_11EncryptionDisabled;
+ pAd->ApCfg.MBSSID[j].DefaultKeyId = 0;
+ pAd->ApCfg.MBSSID[j].WpaMixPairCipher = MIX_CIPHER_NOTUSE;
+ pAd->ApCfg.MBSSID[j].RekeyCountDown = 0; /* it's used for WPA rekey */
+
+#ifdef DOT1X_SUPPORT
+ pAd->ApCfg.MBSSID[j].IEEE8021X = FALSE;
+ pAd->ApCfg.MBSSID[j].PreAuth = FALSE;
+
+ /* PMK cache setting*/
+ pAd->ApCfg.MBSSID[j].PMKCachePeriod = (10 * 60 * OS_HZ); /* unit : tick(default: 10 minute)*/
+ NdisZeroMemory(&pAd->ApCfg.MBSSID[j].PMKIDCache, sizeof(NDIS_AP_802_11_PMKID));
+
+ /* dot1x related per BSS */
+ pAd->ApCfg.MBSSID[j].radius_srv_num = 0;
+ pAd->ApCfg.MBSSID[j].NasIdLen = 0;
+#endif /* DOT1X_SUPPORT */
+
+ /* VLAN related */
+ pAd->ApCfg.MBSSID[j].VLAN_VID = 0;
+
+ /* Default MCS as AUTO*/
+ pAd->ApCfg.MBSSID[j].bAutoTxRateSwitch = TRUE;
+ pAd->ApCfg.MBSSID[j].DesiredTransmitSetting.field.MCS = MCS_AUTO;
+
+ /* Default is zero. It means no limit.*/
+ pAd->ApCfg.MBSSID[j].MaxStaNum = 0;
+ pAd->ApCfg.MBSSID[j].StaCount = 0;
+
+#ifdef WSC_AP_SUPPORT
+ pAd->ApCfg.MBSSID[j].WscSecurityMode = 0xff;
+ {
+ PWSC_CTRL pWscControl;
+ INT idx;
+#ifdef WSC_V2_SUPPORT
+ PWSC_V2_INFO pWscV2Info;
+#endif /* WSC_V2_SUPPORT */
+ /*
+ WscControl cannot be zero here, because WscControl timers are initial in MLME Initialize
+ and MLME Initialize is called before UserCfgInit.
+
+ */
+ pWscControl = &pAd->ApCfg.MBSSID[j].WscControl;
+ NdisZeroMemory(&pWscControl->RegData, sizeof(WSC_REG_DATA));
+ NdisZeroMemory(&pAd->CommonCfg.WscStaPbcProbeInfo, sizeof(WSC_STA_PBC_PROBE_INFO));
+ pWscControl->WscMode = 1;
+ pWscControl->WscConfStatus = 1;
+#ifdef WSC_V2_SUPPORT
+ pWscControl->WscConfigMethods= 0x238C;
+#else
+ pWscControl->WscConfigMethods= 0x0084;
+#endif /* WSC_V2_SUPPORT */
+ pWscControl->RegData.ReComputePke = 1;
+ pWscControl->lastId = 1;
+ /* pWscControl->EntryIfIdx = (MIN_NET_DEVICE_FOR_MBSSID | j); */
+ pWscControl->pAd = pAd;
+ pWscControl->WscRejectSamePinFromEnrollee = FALSE;
+ pAd->CommonCfg.WscPBCOverlap = FALSE;
+ pWscControl->WscConfMode = 0;
+ pWscControl->WscStatus = 0;
+ pWscControl->WscState = 0;
+ pWscControl->WscPinCode = 0;
+ pWscControl->WscLastPinFromEnrollee = 0;
+ pWscControl->WscEnrollee4digitPinCode = FALSE;
+ pWscControl->WscEnrolleePinCode = 0;
+ pWscControl->WscSelReg = 0;
+ pWscControl->WscUseUPnP = 0;
+ pWscControl->bWCNTest = FALSE;
+ pWscControl->WscKeyASCII = 0; /* default, 0 (64 Hex) */
+
+ /*
+ Enrollee 192 random bytes for DH key generation
+ */
+ for (idx = 0; idx < 192; idx++)
+ pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAd);
+
+ /* Enrollee Nonce, first generate and save to Wsc Control Block*/
+ for (idx = 0; idx < 16; idx++)
+ {
+ pWscControl->RegData.SelfNonce[idx] = RandomByte(pAd);
+ }
+ NdisZeroMemory(&pWscControl->WscDefaultSsid, sizeof(NDIS_802_11_SSID));
+ NdisZeroMemory(&pWscControl->Wsc_Uuid_Str[0], UUID_LEN_STR);
+ NdisZeroMemory(&pWscControl->Wsc_Uuid_E[0], UUID_LEN_HEX);
+ pWscControl->bCheckMultiByte = FALSE;
+ pWscControl->bWscAutoTigeer = FALSE;
+ pWscControl->bWscFragment = FALSE;
+ pWscControl->WscFragSize = 128;
+ pWscControl->WscRxBufLen = 0;
+ pWscControl->pWscRxBuf = NULL;
+ os_alloc_mem(pAd, &pWscControl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE);
+ if (pWscControl->pWscRxBuf)
+ NdisZeroMemory(pWscControl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE);
+ pWscControl->WscTxBufLen = 0;
+ pWscControl->pWscTxBuf = NULL;
+ os_alloc_mem(pAd, &pWscControl->pWscTxBuf, MGMT_DMA_BUFFER_SIZE);
+ if (pWscControl->pWscTxBuf)
+ NdisZeroMemory(pWscControl->pWscTxBuf, MGMT_DMA_BUFFER_SIZE);
+ initList(&pWscControl->WscPeerList);
+ NdisAllocateSpinLock(pAd, &pWscControl->WscPeerListSemLock);
+ pWscControl->PinAttackCount = 0;
+ pWscControl->bSetupLock = FALSE;
+#ifdef WSC_V2_SUPPORT
+ pWscV2Info = &pWscControl->WscV2Info;
+ pWscV2Info->bWpsEnable = TRUE;
+ pWscV2Info->ExtraTlv.TlvLen = 0;
+ pWscV2Info->ExtraTlv.TlvTag = 0;
+ pWscV2Info->ExtraTlv.pTlvData = NULL;
+ pWscV2Info->ExtraTlv.TlvType = TLV_ASCII;
+ pWscV2Info->bEnableWpsV2 = TRUE;
+ pWscControl->SetupLockTime = WSC_WPS_AP_SETUP_LOCK_TIME;
+ pWscControl->MaxPinAttack = WSC_WPS_AP_MAX_PIN_ATTACK;
+#endif /* WSC_V2_SUPPORT */
+
+ }
+#endif /* WSC_AP_SUPPORT */
+
+
+ for(i = 0; i < WLAN_MAX_NUM_OF_TIM; i++)
+ pAd->ApCfg.MBSSID[j].TimBitmaps[i] = 0;
+ }
+ pAd->ApCfg.DtimCount = 0;
+ pAd->ApCfg.DtimPeriod = DEFAULT_DTIM_PERIOD;
+
+ pAd->ApCfg.ErpIeContent = 0;
+
+ pAd->ApCfg.StaIdleTimeout = MAC_TABLE_AGEOUT_TIME;
+
+#ifdef IDS_SUPPORT
+ /* Default disable IDS threshold and reset all IDS counters*/
+ pAd->ApCfg.IdsEnable = FALSE;
+ pAd->ApCfg.AuthFloodThreshold = 0;
+ pAd->ApCfg.AssocReqFloodThreshold = 0;
+ pAd->ApCfg.ReassocReqFloodThreshold = 0;
+ pAd->ApCfg.ProbeReqFloodThreshold = 0;
+ pAd->ApCfg.DisassocFloodThreshold = 0;
+ pAd->ApCfg.DeauthFloodThreshold = 0;
+ pAd->ApCfg.EapReqFloodThreshold = 0;
+ RTMPClearAllIdsCounter(pAd);
+#endif /* IDS_SUPPORT */
+
+#ifdef WDS_SUPPORT
+ APWdsInitialize(pAd);
+#endif /* WDS_SUPPORT*/
+
+#ifdef WSC_INCLUDED
+ pAd->WriteWscCfgToDatFile = 0xFF;
+ pAd->WriteWscCfgToAr9DatFile = FALSE;
+#ifdef CONFIG_AP_SUPPORT
+ pAd->bWscDriverAutoUpdateCfg = TRUE;
+#endif /* CONFIG_AP_SUPPORT */
+#endif /* WSC_INCLUDED */
+
+#ifdef APCLI_SUPPORT
+ pAd->ApCfg.FlgApCliIsUapsdInfoUpdated = FALSE;
+
+ for(j = 0; j < MAX_APCLI_NUM; j++)
+ {
+ pAd->ApCfg.ApCliTab[j].AuthMode = Ndis802_11AuthModeOpen;
+ pAd->ApCfg.ApCliTab[j].WepStatus = Ndis802_11WEPDisabled;
+ pAd->ApCfg.ApCliTab[j].bAutoTxRateSwitch = TRUE;
+ pAd->ApCfg.ApCliTab[j].DesiredTransmitSetting.field.MCS = MCS_AUTO;
+ pAd->ApCfg.ApCliTab[j].UapsdInfo.bAPSDCapable = FALSE;
+
+#ifdef APCLI_WPA_SUPPLICANT_SUPPORT
+ pAd->ApCfg.ApCliTab[j].IEEE8021X=FALSE;
+ pAd->ApCfg.ApCliTab[j].IEEE8021x_required_keys=FALSE;
+ pAd->ApCfg.ApCliTab[j].bRSN_IE_FromWpaSupplicant=FALSE;
+ pAd->ApCfg.ApCliTab[j].bLostAp=FALSE;
+ pAd->ApCfg.ApCliTab[j].bScanReqIsFromWebUI=FALSE;
+ pAd->ApCfg.ApCliTab[j].bConfigChanged=FALSE;
+ pAd->ApCfg.ApCliTab[j].DesireSharedKeyId=0;
+ pAd->ApCfg.ApCliTab[j].WpaSupplicantUP=WPA_SUPPLICANT_DISABLE;
+ pAd->ApCfg.ApCliTab[j].WpaSupplicantScanCount=0;
+ pAd->ApCfg.ApCliTab[j].pWpsProbeReqIe=NULL;
+ pAd->ApCfg.ApCliTab[j].WpsProbeReqIeLen=0;
+ pAd->ApCfg.ApCliTab[j].pWpaAssocIe=NULL;
+ pAd->ApCfg.ApCliTab[j].WpaAssocIeLen=0;
+ pAd->ApCfg.ApCliTab[j].SavedPMKNum=0;
+ RTMPZeroMemory(pAd->ApCfg.ApCliTab[j].SavedPMK, (PMKID_NO * sizeof(BSSID_INFO)));
+#endif/*APCLI_WPA_SUPPLICANT_SUPPORT*/
+
+ }
+#endif /* APCLI_SUPPORT */
+ pAd->ApCfg.EntryClientCount = 0;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef IP_ASSEMBLY
+ if (pAd->OpMode == OPMODE_STA)
+ {
+ pAd->StaCfg.bFragFlag = TRUE;
+ }
+#endif /* IP_ASSEMBLY */
+
+ /* part IV. others*/
+
+ /* dynamic BBP R66:sensibity tuning to overcome background noise*/
+ pAd->BbpTuning.bEnable = TRUE;
+ pAd->BbpTuning.FalseCcaLowerThreshold = 100;
+ pAd->BbpTuning.FalseCcaUpperThreshold = 512;
+ pAd->BbpTuning.R66Delta = 4;
+ pAd->Mlme.bEnableAutoAntennaCheck = TRUE;
+
+
+ /* Also initial R66CurrentValue, RTUSBResumeMsduTransmission might use this value.*/
+ /* if not initial this value, the default value will be 0.*/
+
+ pAd->BbpTuning.R66CurrentValue = 0x38;
+
+ pAd->Bbp94 = BBPR94_DEFAULT;
+ pAd->BbpForCCK = FALSE;
+
+ /* Default is FALSE for test bit 1*/
+ /*pAd->bTest1 = FALSE;*/
+
+ /* initialize MAC table and allocate spin lock*/
+ NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE));
+ InitializeQueueHeader(&pAd->MacTab.McastPsQueue);
+ NdisAllocateSpinLock(pAd, &pAd->MacTabLock);
+
+ /*RTMPInitTimer(pAd, &pAd->RECBATimer, RECBATimerTimeout, pAd, TRUE);*/
+ /*RTMPSetTimer(&pAd->RECBATimer, REORDER_EXEC_INTV);*/
+
+
+ pAd->CommonCfg.bWiFiTest = FALSE;
+
+#ifdef CONFIG_AP_SUPPORT
+ pAd->ApCfg.EntryLifeCheck = MAC_ENTRY_LIFE_CHECK_CNT;
+
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ pAd->RxAnt.Pair1PrimaryRxAnt = 0;
+ pAd->RxAnt.Pair1SecondaryRxAnt = 1;
+
+ pAd->RxAnt.EvaluatePeriod = 0;
+ pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
+#ifdef CONFIG_AP_SUPPORT
+ pAd->RxAnt.Pair1AvgRssiGroup1[0] = pAd->RxAnt.Pair1AvgRssiGroup1[1] = 0;
+ pAd->RxAnt.Pair1AvgRssiGroup2[0] = pAd->RxAnt.Pair1AvgRssiGroup2[1] = 0;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef TXRX_SW_ANTDIV_SUPPORT
+ pAd->chipCap.bTxRxSwAntDiv = FALSE;
+#endif /* TXRX_SW_ANTDIV_SUPPORT */
+
+
+#if defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT)
+ for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
+ {
+ PBSS_ENTRY pBssEntry = &pAd->ScanTab.BssEntry[i];
+
+ if (pAd->ProbeRespIE[i].pIe)
+ pBssEntry->pVarIeFromProbRsp = pAd->ProbeRespIE[i].pIe;
+ else
+ pBssEntry->pVarIeFromProbRsp = NULL;
+ }
+#endif /* defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) */
+
+
+#ifdef WSC_INCLUDED
+ NdisZeroMemory(&pAd->CommonCfg.WscStaPbcProbeInfo, sizeof(WSC_STA_PBC_PROBE_INFO));
+ pAd->CommonCfg.WscPBCOverlap = FALSE;
+#endif /* WSC_INCLUDED */
+
+
+
+#ifdef WFD_SUPPORT
+ WfdCfgInit(pAd);
+#endif /* WFD_SUPPORT */
+
+
+#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT)
+ pAd->WOW_Cfg.bEnable = FALSE;
+ pAd->WOW_Cfg.bWOWFirmware = FALSE; /* load normal firmware */
+ pAd->WOW_Cfg.bInBand = TRUE; /* use in-band signal */
+ pAd->WOW_Cfg.nSelectedGPIO = 1;
+ pAd->WOW_Cfg.nDelay = 3; /* (3+1)*3 = 12 sec */
+ pAd->WOW_Cfg.nHoldTime = 1; /* 1*10 = 10 ms */
+ DBGPRINT(RT_DEBUG_OFF, ("WOW Enable %d, WOWFirmware %d\n", pAd->WOW_Cfg.bEnable, pAd->WOW_Cfg.bWOWFirmware));
+#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */
+
+ /* 802.11H and DFS related params*/
+ pAd->Dot11_H.CSCount = 0;
+ pAd->Dot11_H.CSPeriod = 10;
+ pAd->Dot11_H.RDMode = RD_NORMAL_MODE;
+ pAd->Dot11_H.bDFSIndoor = 1;
+
+
+#ifdef FPGA_MODE
+ pAd->fpga_on = 0x0;
+ pAd->tx_kick_cnt = 0;
+ pAd->data_phy = 0;
+ pAd->data_mcs = 0;
+ pAd->data_bw = 0;
+ pAd->data_gi = 0;
+#endif /* FPGA_MODE */
+
+#ifdef MICROWAVE_OVEN_SUPPORT
+ if (pAd->OpMode == OPMODE_AP)
+ pAd->CommonCfg.MO_Cfg.bEnable = TRUE;
+ else
+ pAd->CommonCfg.MO_Cfg.bEnable = FALSE;
+ pAd->CommonCfg.MO_Cfg.nFalseCCATh = MO_FALSE_CCA_TH;
+#endif /* MICROWAVE_OVEN_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- UserCfgInit\n"));
+}
+
+/* IRQL = PASSIVE_LEVEL*/
+UCHAR BtoH(STRING ch)
+{
+ if (ch >= '0' && ch <= '9') return (ch - '0'); /* Handle numerals*/
+ if (ch >= 'A' && ch <= 'F') return (ch - 'A' + 0xA); /* Handle capitol hex digits*/
+ if (ch >= 'a' && ch <= 'f') return (ch - 'a' + 0xA); /* Handle small hex digits*/
+ return(255);
+}
+
+
+/* FUNCTION: AtoH(char *, UCHAR *, int)*/
+
+/* PURPOSE: Converts ascii string to network order hex*/
+
+/* PARAMETERS:*/
+/* src - pointer to input ascii string*/
+/* dest - pointer to output hex*/
+/* destlen - size of dest*/
+
+/* COMMENTS:*/
+
+/* 2 ascii bytes make a hex byte so must put 1st ascii byte of pair*/
+/* into upper nibble and 2nd ascii byte of pair into lower nibble.*/
+
+/* IRQL = PASSIVE_LEVEL*/
+
+void AtoH(PSTRING src, PUCHAR dest, int destlen)
+{
+ PSTRING srcptr;
+ PUCHAR destTemp;
+
+ srcptr = src;
+ destTemp = (PUCHAR) dest;
+
+ while(destlen--)
+ {
+ *destTemp = BtoH(*srcptr++) << 4; /* Put 1st ascii byte in upper nibble.*/
+ *destTemp += BtoH(*srcptr++); /* Add 2nd ascii byte to above.*/
+ destTemp++;
+ }
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Add a timer to the timer list.
+
+Arguments:
+ pAd - WLAN control block pointer
+ pRsc - the OS resource
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID RTMP_TimerListAdd(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pRsc)
+{
+ LIST_HEADER *pRscList = &pAd->RscTimerCreateList;
+ LIST_RESOURCE_OBJ_ENTRY *pObj;
+
+
+ /* try to find old entry */
+ pObj = (LIST_RESOURCE_OBJ_ENTRY *)(pRscList->pHead);
+ while(1)
+ {
+ if (pObj == NULL)
+ break;
+ if ((ULONG)(pObj->pRscObj) == (ULONG)pRsc)
+ return; /* exists */
+ pObj = pObj->pNext;
+ }
+
+ /* allocate a timer record entry */
+ os_alloc_mem(NULL, (UCHAR **)&(pObj), sizeof(LIST_RESOURCE_OBJ_ENTRY));
+ if (pObj == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc timer obj fail!\n", __FUNCTION__));
+ return;
+ }
+ else
+ {
+ pObj->pRscObj = pRsc;
+ insertTailList(pRscList, (LIST_ENTRY *)pObj);
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: add timer obj %lx!\n", __FUNCTION__, (ULONG)pRsc));
+ }
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Cancel all timers in the timer list.
+
+Arguments:
+ pAd - WLAN control block pointer
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID RTMP_TimerListRelease(
+ IN PRTMP_ADAPTER pAd)
+{
+ LIST_HEADER *pRscList = &pAd->RscTimerCreateList;
+ LIST_RESOURCE_OBJ_ENTRY *pObj, *pObjOld;
+ BOOLEAN Cancel;
+
+
+ /* try to find old entry */
+ pObj = (LIST_RESOURCE_OBJ_ENTRY *)(pRscList->pHead);
+ while(1)
+ {
+ if (pObj == NULL)
+ break;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Cancel timer obj %lx!\n", __FUNCTION__, (ULONG)(pObj->pRscObj)));
+ RTMPReleaseTimer(pObj->pRscObj, &Cancel);
+ pObjOld = pObj;
+ pObj = pObj->pNext;
+ os_free_mem(NULL, pObjOld);
+ }
+
+ /* reset TimerList */
+ initList(&pAd->RscTimerCreateList);
+}
+
+
+VOID RTMP_AllTimerListRelease(RTMP_ADAPTER *pAd)
+{
+ LIST_HEADER *pRscList = &pAd->RscTimerCreateList;
+ LIST_RESOURCE_OBJ_ENTRY *pObj, *pObjOld;
+ BOOLEAN Cancel;
+
+ /* try to find old entry */
+ pObj = (LIST_RESOURCE_OBJ_ENTRY *)(pRscList->pHead);
+ while(1)
+ {
+ if (pObj == NULL)
+ break;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Cancel timer obj %lx!\n", __FUNCTION__, (ULONG)(pObj->pRscObj)));
+ pObjOld = pObj;
+ pObj = pObj->pNext;
+ RTMPReleaseTimer(pObjOld->pRscObj, &Cancel);
+ os_free_mem(NULL, pObjOld);
+ }
+
+ /* reset TimerList */
+ initList(&pAd->RscTimerCreateList);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Init timer objects
+
+ Arguments:
+ pAd Pointer to our adapter
+ pTimer Timer structure
+ pTimerFunc Function to execute when timer expired
+ Repeat Ture for period timer
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPInitTimer(
+ IN PRTMP_ADAPTER pAd,
+ IN PRALINK_TIMER_STRUCT pTimer,
+ IN PVOID pTimerFunc,
+ IN PVOID pData,
+ IN BOOLEAN Repeat)
+{
+ RTMP_SEM_LOCK(&TimerSemLock);
+
+ RTMP_TimerListAdd(pAd, pTimer);
+
+
+ /* Set Valid to TRUE for later used.*/
+ /* It will crash if we cancel a timer or set a timer */
+ /* that we haven't initialize before.*/
+ /* */
+ pTimer->Valid = TRUE;
+
+ pTimer->PeriodicType = Repeat;
+ pTimer->State = FALSE;
+ pTimer->cookie = (ULONG) pData;
+ pTimer->pAd = pAd;
+
+ RTMP_OS_Init_Timer(pAd, &pTimer->TimerObj, pTimerFunc, (PVOID) pTimer, &pAd->RscTimerMemList);
+ DBGPRINT(RT_DEBUG_TRACE,("%s: %lx\n",__FUNCTION__, (ULONG)pTimer));
+
+ RTMP_SEM_UNLOCK(&TimerSemLock);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Init timer objects
+
+ Arguments:
+ pTimer Timer structure
+ Value Timer value in milliseconds
+
+ Return Value:
+ None
+
+ Note:
+ To use this routine, must call RTMPInitTimer before.
+
+ ========================================================================
+*/
+VOID RTMPSetTimer(
+ IN PRALINK_TIMER_STRUCT pTimer,
+ IN ULONG Value)
+{
+ RTMP_SEM_LOCK(&TimerSemLock);
+
+ if (pTimer->Valid)
+ {
+ RTMP_ADAPTER *pAd;
+
+ pAd = (RTMP_ADAPTER *)pTimer->pAd;
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ {
+ DBGPRINT_ERR(("RTMPSetTimer failed, Halt in Progress!\n"));
+ RTMP_SEM_UNLOCK(&TimerSemLock);
+ return;
+ }
+
+ pTimer->TimerValue = Value;
+ pTimer->State = FALSE;
+ if (pTimer->PeriodicType == TRUE)
+ {
+ pTimer->Repeat = TRUE;
+ RTMP_SetPeriodicTimer(&pTimer->TimerObj, Value);
+ }
+ else
+ {
+ pTimer->Repeat = FALSE;
+ RTMP_OS_Add_Timer(&pTimer->TimerObj, Value);
+ }
+
+ DBGPRINT(RT_DEBUG_INFO,("%s: %lx\n",__FUNCTION__, (ULONG)pTimer));
+ }
+ else
+ {
+ DBGPRINT_ERR(("RTMPSetTimer failed, Timer hasn't been initialize!\n"));
+ }
+ RTMP_SEM_UNLOCK(&TimerSemLock);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Init timer objects
+
+ Arguments:
+ pTimer Timer structure
+ Value Timer value in milliseconds
+
+ Return Value:
+ None
+
+ Note:
+ To use this routine, must call RTMPInitTimer before.
+
+ ========================================================================
+*/
+VOID RTMPModTimer(
+ IN PRALINK_TIMER_STRUCT pTimer,
+ IN ULONG Value)
+{
+ BOOLEAN Cancel;
+
+
+ RTMP_SEM_LOCK(&TimerSemLock);
+
+ if (pTimer->Valid)
+ {
+ pTimer->TimerValue = Value;
+ pTimer->State = FALSE;
+ if (pTimer->PeriodicType == TRUE)
+ {
+ RTMP_SEM_UNLOCK(&TimerSemLock);
+ RTMPCancelTimer(pTimer, &Cancel);
+ RTMPSetTimer(pTimer, Value);
+ }
+ else
+ {
+ RTMP_OS_Mod_Timer(&pTimer->TimerObj, Value);
+ RTMP_SEM_UNLOCK(&TimerSemLock);
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("%s: %lx\n",__FUNCTION__, (ULONG)pTimer));
+ }
+ else
+ {
+ DBGPRINT_ERR(("RTMPModTimer failed, Timer hasn't been initialize!\n"));
+ RTMP_SEM_UNLOCK(&TimerSemLock);
+ }
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Cancel timer objects
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ 1.) To use this routine, must call RTMPInitTimer before.
+ 2.) Reset NIC to initial state AS IS system boot up time.
+
+ ========================================================================
+*/
+VOID RTMPCancelTimer(
+ IN PRALINK_TIMER_STRUCT pTimer,
+ OUT BOOLEAN *pCancelled)
+{
+ RTMP_SEM_LOCK(&TimerSemLock);
+
+ if (pTimer->Valid)
+ {
+ if (pTimer->State == FALSE)
+ pTimer->Repeat = FALSE;
+
+ RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled);
+
+ if (*pCancelled == TRUE)
+ pTimer->State = TRUE;
+
+#ifdef RTMP_TIMER_TASK_SUPPORT
+ /* We need to go-through the TimerQ to findout this timer handler and remove it if */
+ /* it's still waiting for execution.*/
+ RtmpTimerQRemove(pTimer->pAd, pTimer);
+#endif /* RTMP_TIMER_TASK_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_INFO,("%s: %lx\n",__FUNCTION__, (ULONG)pTimer));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_INFO,("RTMPCancelTimer failed, Timer hasn't been initialize!\n"));
+ }
+
+ RTMP_SEM_UNLOCK(&TimerSemLock);
+}
+
+
+VOID RTMPReleaseTimer(
+ IN PRALINK_TIMER_STRUCT pTimer,
+ OUT BOOLEAN *pCancelled)
+{
+ RTMP_SEM_LOCK(&TimerSemLock);
+
+ if (pTimer->Valid)
+ {
+ if (pTimer->State == FALSE)
+ pTimer->Repeat = FALSE;
+
+ RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled);
+
+ if (*pCancelled == TRUE)
+ pTimer->State = TRUE;
+
+#ifdef RTMP_TIMER_TASK_SUPPORT
+ /* We need to go-through the TimerQ to findout this timer handler and remove it if */
+ /* it's still waiting for execution.*/
+ RtmpTimerQRemove(pTimer->pAd, pTimer);
+#endif /* RTMP_TIMER_TASK_SUPPORT */
+
+ /* release timer */
+ RTMP_OS_Release_Timer(&pTimer->TimerObj);
+
+ pTimer->Valid = FALSE;
+
+ DBGPRINT(RT_DEBUG_INFO,("%s: %lx\n",__FUNCTION__, (ULONG)pTimer));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_INFO,("RTMPReleasefailed, Timer hasn't been initialize!\n"));
+ }
+
+ RTMP_SEM_UNLOCK(&TimerSemLock);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Enable RX
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL <= DISPATCH_LEVEL
+
+ Note:
+ Before Enable RX, make sure you have enabled Interrupt.
+ ========================================================================
+*/
+VOID RTMPEnableRxTx(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 rx_filter_flag;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPEnableRxTx\n"));
+
+ RT28XXDMAEnable(pAd);
+
+ /* enable RX of MAC block*/
+ if (pAd->OpMode == OPMODE_AP)
+ {
+ rx_filter_flag = APNORMAL;
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef IDS_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if (pAd->ApCfg.IdsEnable)
+ rx_filter_flag &= (~0x4); /* Don't drop those not-U2M frames*/
+ }
+#endif /* IDS_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); /* enable RX of DMA block*/
+ }
+
+ {
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
+//+++Add by shiang for debug for pbf_loopback
+ //RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2c);
+//---Add by shiang for debug
+//+++Add by shiang for debug invalid RxWI->WCID
+#ifdef RT8592
+#endif /* RT8592 */
+//---Add by shiang for debug invalid RxWI->WCID
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPEnableRxTx\n"));
+}
+
+
+void CfgInitHook(PRTMP_ADAPTER pAd)
+{
+ /*pAd->bBroadComHT = TRUE;*/
+}
+
+
+static INT RtmpChipOpsRegister(
+ IN RTMP_ADAPTER *pAd,
+ IN INT infType)
+{
+ RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
+ int status;
+
+ memset(pChipOps, 0, sizeof(RTMP_CHIP_OP));
+
+ RtmpChipOpsHook(pAd);
+
+ /* MCU related */
+ ChipOpsMCUHook(pAd, pAd->chipCap.MCUType);
+
+ /* set eeprom related hook functions */
+ status = RtmpChipOpsEepromHook(pAd, infType);
+
+ return status;
+}
+
+
+#ifdef RTMP_MAC_USB
+BOOLEAN PairEP(RTMP_ADAPTER *pAd, UINT8 EP, UINT8 Index, UINT8 InOut)
+{
+ RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
+
+ if (Index == 0 && InOut == 0)
+ {
+ pChipCap->CommandBulkOutAddr = EP;
+ DBGPRINT(RT_DEBUG_OFF, ("Endpoint(%x) is for In-band Command\n", EP));
+ return TRUE;
+ }
+
+ if (Index > 0 && Index < 5 && InOut == 0)
+ {
+ pChipCap->WMM0ACBulkOutAddr[Index - 1] = EP;
+ DBGPRINT(RT_DEBUG_OFF, ("Endpoint(%x) is for WMM0 AC%d\n", EP, Index - 1));
+ return TRUE;
+ }
+
+ if (Index == 5 && InOut == 0)
+ {
+ pChipCap->WMM1ACBulkOutAddr = EP;
+ DBGPRINT(RT_DEBUG_OFF, ("Endpoint(%x) is for WMM1 AC0\n", EP));
+ return TRUE;
+ }
+
+ if (Index == 0 && InOut == 1)
+ {
+ pChipCap->DataBulkInAddr = EP;
+ DBGPRINT(RT_DEBUG_OFF, ("Endpoint(%x) is for Data-In\n", EP));
+ return TRUE;
+ }
+
+
+ if (Index == 1 && InOut == 1)
+ {
+ pChipCap->CommandRspBulkInAddr = EP;
+ DBGPRINT(RT_DEBUG_OFF, ("Endpoint(%x) is for Command Rsp\n", EP));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+#endif /* RTMP_MAC_USB */
+
+
+INT RtmpRaDevCtrlInit(VOID *pAdSrc, RTMP_INF_TYPE infType)
+{
+ RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)pAdSrc;
+ UINT8 i;
+
+ /* Assign the interface type. We need use it when do register/EEPROM access.*/
+ pAd->infType = infType;
+
+
+#ifdef CONFIG_AP_SUPPORT
+ pAd->OpMode = OPMODE_AP;
+ DBGPRINT(RT_DEBUG_TRACE, ("AP Driver version-%s\n", AP_DRIVER_VERSION));
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef RTMP_MAC_USB
+ RTMP_SEM_EVENT_INIT(&(pAd->UsbVendorReq_semaphore), &pAd->RscSemMemList);
+ RTMP_SEM_EVENT_INIT(&(pAd->reg_atomic), &pAd->RscSemMemList);
+ RTMP_SEM_EVENT_INIT(&(pAd->hw_atomic), &pAd->RscSemMemList);
+ os_alloc_mem(pAd, (PUCHAR *)&pAd->UsbVendorReqBuf, MAX_PARAM_BUFFER_SIZE - 1);
+ if (pAd->UsbVendorReqBuf == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Allocate vendor request temp buffer failed!\n"));
+ return FALSE;
+ }
+
+
+#endif /* RTMP_MAC_USB */
+
+ RtmpChipOpsRegister(pAd, infType);
+
+#ifdef RTMP_MAC_USB
+ for (i = 0; i < 6; i++)
+ {
+ if (!PairEP(pAd, pAd->BulkOutEpAddr[i], i, 0))
+ DBGPRINT(RT_DEBUG_ERROR, ("Invalid bulk out ep(%x)\n", pAd->BulkOutEpAddr[i]));
+ }
+
+ for (i = 0; i < 2; i++)
+ {
+ if (!PairEP(pAd, pAd->BulkInEpAddr[i], i, 1))
+ DBGPRINT(RT_DEBUG_ERROR, ("Invalid bulk in ep(%x)\n", pAd->BulkInEpAddr[i]));
+ }
+
+#endif
+
+#ifdef MULTIPLE_CARD_SUPPORT
+{
+ extern BOOLEAN RTMP_CardInfoRead(PRTMP_ADAPTER pAd);
+
+ /* find its profile path*/
+ pAd->MC_RowID = -1; /* use default profile path*/
+ RTMP_CardInfoRead(pAd);
+
+ if (pAd->MC_RowID == -1)
+#ifdef CONFIG_AP_SUPPORT
+ strcpy(pAd->MC_FileName, AP_PROFILE_PATH);
+#endif /* CONFIG_AP_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MC> ROW = %d, PATH = %s\n", pAd->MC_RowID, pAd->MC_FileName));
+}
+#endif /* MULTIPLE_CARD_SUPPORT */
+
+#if defined(CONFIG_CSO_SUPPORT) || defined(CONFIG_RX_CSO_SUPPORT)
+ if (pAd->chipCap.asic_caps | fASIC_CAP_CSO)
+ RTMP_SET_MORE_FLAG(pAd, fASIC_CAP_CSO);
+#endif /* defined(CONFIG_CSO_SUPPORT) || defined(CONFIG_RX_CSO_SUPPORT) */
+ return 0;
+}
+
+
+BOOLEAN RtmpRaDevCtrlExit(IN VOID *pAdSrc)
+{
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc;
+ INT index;
+
+#ifdef MULTIPLE_CARD_SUPPORT
+extern UINT8 MC_CardUsed[MAX_NUM_OF_MULTIPLE_CARD];
+
+ if ((pAd->MC_RowID >= 0) && (pAd->MC_RowID <= MAX_NUM_OF_MULTIPLE_CARD))
+ MC_CardUsed[pAd->MC_RowID] = 0; /* not clear MAC address*/
+#endif /* MULTIPLE_CARD_SUPPORT */
+
+
+
+
+#ifdef RTMP_MAC_USB
+ RTMP_SEM_EVENT_DESTORY(&(pAd->UsbVendorReq_semaphore));
+ RTMP_SEM_EVENT_DESTORY(&(pAd->reg_atomic));
+ RTMP_SEM_EVENT_DESTORY(&(pAd->hw_atomic));
+
+
+ if (pAd->UsbVendorReqBuf)
+ os_free_mem(pAd, pAd->UsbVendorReqBuf);
+#endif /* RTMP_MAC_USB */
+
+ /*
+ Free ProbeRespIE Table
+ */
+ for (index = 0; index < MAX_LEN_OF_BSS_TABLE; index++)
+ {
+ if (pAd->ProbeRespIE[index].pIe)
+ os_free_mem(pAd, pAd->ProbeRespIE[index].pIe);
+ }
+
+#ifdef RESOURCE_PRE_ALLOC
+ RTMPFreeTxRxRingMemory(pAd);
+#endif /* RESOURCE_PRE_ALLOC */
+
+#ifdef RT65xx
+ if (IS_RT6590(pAd) && (pAd->WlanFunCtrl.field.WLAN_EN == 1))
+ {
+ ral_wlan_chip_onoff(pAd, FALSE, FALSE);
+ }
+#endif /* RT65xx */
+
+#ifdef MT7601
+ if (IS_MT7601(pAd) && (pAd->WlanFunCtrl.field.WLAN_EN == 1) )
+ {
+ MT7601_WLAN_ChipOnOff(pAd, FALSE, FALSE);
+ }
+#endif /* MT7601 */
+
+ RTMPFreeAdapter(pAd);
+
+ return TRUE;
+}
+
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+VOID RTMP_11N_D3_TimerInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ RTMPInitTimer(pAd, &pAd->CommonCfg.Bss2040CoexistTimer, GET_TIMER_FUNCTION(Bss2040CoexistTimeOut), pAd, FALSE);
+}
+#endif /* DOT11N_DRAFT3 */
+#endif /* DOT11_N_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef VENDOR_FEATURE3_SUPPORT
+VOID RTMP_IO_WRITE32(
+ PRTMP_ADAPTER pAd,
+ UINT32 Offset,
+ UINT32 Value)
+{
+ _RTMP_IO_WRITE32(pAd, Offset, Value);
+}
+
+VOID RTMP_BBP_IO_READ8_BY_REG_ID(
+ PRTMP_ADAPTER pAd,
+ UINT32 Offset,
+ UINT8 *pValue)
+{
+#ifdef RT8592
+ if (IS_RT8592(pAd))
+ return;
+#endif /* RT8592 */
+
+#ifdef RT65xx
+ if (IS_RT65XX(pAd))
+ return;
+#endif /* RT65xx */
+
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ return;
+#endif /* MT7601 */
+ _RTMP_BBP_IO_READ8_BY_REG_ID(pAd, Offset, pValue);
+}
+
+VOID RTMP_BBP_IO_READ8(
+ PRTMP_ADAPTER pAd,
+ UCHAR Offset,
+ UINT8 *pValue,
+ BOOLEAN FlgValidMCR)
+{
+#ifdef RT8592
+ if (IS_RT8592(pAd))
+ return;
+#endif /* RT8592 */
+
+#ifdef RT65xx
+ if (IS_RT65XX(pAd))
+ return;
+#endif /* RT65xx */
+
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ return;
+#endif /* MT7601 */
+
+ _RTMP_BBP_IO_READ8(pAd, Offset, pValue, FlgValidMCR);
+}
+
+VOID RTMP_BBP_IO_WRITE8_BY_REG_ID(
+ PRTMP_ADAPTER pAd,
+ UINT32 Offset,
+ UINT8 Value)
+{
+#ifdef RT8592
+ if (IS_RT8592(pAd))
+ return;
+#endif /* RT8592 */
+
+#ifdef RT65xx
+ if (IS_RT65XX(pAd))
+ return;
+#endif /* RT65xx */
+
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ return;
+#endif /* MT7601 */
+
+ _RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, Offset, Value);
+}
+
+VOID RTMP_BBP_IO_WRITE8(
+ PRTMP_ADAPTER pAd,
+ UCHAR Offset,
+ UINT8 Value,
+ BOOLEAN FlgValidMCR)
+{
+#ifdef RT8592
+ if (IS_RT8592(pAd))
+ return;
+#endif /* RT8592 */
+
+#ifdef RT65xx
+ if (IS_RT65XX(pAd))
+ return;
+#endif /* RT65xx */
+
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ return;
+#endif /* MT7601 */
+
+ _RTMP_BBP_IO_WRITE8(pAd, Offset, Value, FlgValidMCR);
+}
+#endif /* VENDOR_FEATURE3_SUPPORT */
+
+
+
+VOID AntCfgInit(
+IN PRTMP_ADAPTER pAd)
+{
+
+
+#ifdef TXRX_SW_ANTDIV_SUPPORT
+ /* EEPROM 0x34[15:12] = 0xF is invalid, 0x2~0x3 is TX/RX SW AntDiv */
+ DBGPRINT(RT_DEBUG_OFF, ("%s: bTxRxSwAntDiv %d\n", __FUNCTION__, pAd->chipCap.bTxRxSwAntDiv));
+ if (pAd->chipCap.bTxRxSwAntDiv)
+ {
+ DBGPRINT(RT_DEBUG_OFF, ("Antenna word %X/%d, AntDiv %d\n",
+ pAd->Antenna.word, pAd->Antenna.field.BoardType, pAd->NicConfig2.field.AntDiversity));
+ }
+#endif /* TXRX_SW_ANTDIV_SUPPORT */
+
+ {
+ if (pAd->NicConfig2.field.AntOpt== 1) /* ant selected by efuse */
+ {
+ if (pAd->NicConfig2.field.AntDiversity == 0) /* main */
+ {
+ pAd->RxAnt.Pair1PrimaryRxAnt = 0;
+ pAd->RxAnt.Pair1SecondaryRxAnt = 1;
+ }
+ else/* aux */
+ {
+ pAd->RxAnt.Pair1PrimaryRxAnt = 1;
+ pAd->RxAnt.Pair1SecondaryRxAnt = 0;
+ }
+ }
+ else if (pAd->NicConfig2.field.AntDiversity == 0) /* Ant div off: default ant is main */
+ {
+ pAd->RxAnt.Pair1PrimaryRxAnt = 0;
+ pAd->RxAnt.Pair1SecondaryRxAnt = 1;
+ }
+ else if (pAd->NicConfig2.field.AntDiversity == 1)/* Ant div on */
+ {/* eeprom on, but sw ant div support is not enabled: default ant is main */
+ pAd->RxAnt.Pair1PrimaryRxAnt = 0;
+ pAd->RxAnt.Pair1SecondaryRxAnt = 1;
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_OFF, ("%s: primary/secondary ant %d/%d\n",
+ __FUNCTION__,
+ pAd->RxAnt.Pair1PrimaryRxAnt,
+ pAd->RxAnt.Pair1SecondaryRxAnt));
+}
+
+#ifdef MICROWAVE_OVEN_SUPPORT
+VOID NICUpdateRxStatusCnt1(
+IN PRTMP_ADAPTER pAd,
+IN UCHAR Idx)
+{
+ RX_STA_CNT1_STRUC RxStaCnt1;
+
+ RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word);
+
+ if (Idx < MLME_TASK_EXEC_MULTIPLE)
+ {
+ pAd->RalinkCounters.FalseCCACnt_100MS[Idx] = RxStaCnt1.field.FalseCca;
+ pAd->RalinkCounters.PLCPErrCnt_100MS[Idx] = RxStaCnt1.field.PlcpErr;
+ }
+}
+
+UINT32 NICSumFalseCCACnt(
+IN PRTMP_ADAPTER pAd)
+{
+ UCHAR Idx;
+ UINT32 FalseCCACnt = 0;
+
+ for (Idx = 0; Idx < MLME_TASK_EXEC_MULTIPLE; Idx++)
+ FalseCCACnt += pAd->RalinkCounters.FalseCCACnt_100MS[Idx];
+
+ return FalseCCACnt;
+}
+
+UINT32 NICSumPLCPErrCnt(
+IN PRTMP_ADAPTER pAd)
+{
+ UCHAR Idx;
+ UINT32 PLCPErrCnt = 0;
+
+ for (Idx = 0; Idx < MLME_TASK_EXEC_MULTIPLE; Idx++)
+ PLCPErrCnt += pAd->RalinkCounters.PLCPErrCnt_100MS[Idx];
+
+ return PLCPErrCnt;
+}
+#endif /* MICROWAVE_OVEN_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/rtmp_init_inf.c b/cleopatre/devkit/mt7601udrv/common/rtmp_init_inf.c
new file mode 100644
index 0000000000..b33bab78e2
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rtmp_init_inf.c
@@ -0,0 +1,1094 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2004, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ rtmp_init_inf.c
+
+ Abstract:
+ Miniport generic portion header file
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+*/
+#include "rt_config.h"
+
+
+
+
+#ifdef LINUX
+#ifdef OS_ABL_FUNC_SUPPORT
+/* Utilities provided from NET module */
+RTMP_NET_ABL_OPS RtmpDrvNetOps, *pRtmpDrvNetOps = &RtmpDrvNetOps;
+RTMP_PCI_CONFIG RtmpPciConfig, *pRtmpPciConfig = &RtmpPciConfig;
+RTMP_USB_CONFIG RtmpUsbConfig, *pRtmpUsbConfig = &RtmpUsbConfig;
+
+VOID RtmpDrvOpsInit(
+ OUT VOID *pDrvOpsOrg,
+ INOUT VOID *pDrvNetOpsOrg,
+ IN RTMP_PCI_CONFIG *pPciConfig,
+ IN RTMP_USB_CONFIG *pUsbConfig)
+{
+ RTMP_DRV_ABL_OPS *pDrvOps = (RTMP_DRV_ABL_OPS *)pDrvOpsOrg;
+#ifdef RTMP_USB_SUPPORT
+ RTMP_NET_ABL_OPS *pDrvNetOps = (RTMP_NET_ABL_OPS *)pDrvNetOpsOrg;
+#endif /* RTMP_USB_SUPPORT */
+
+
+ /* init PCI/USB configuration in different OS */
+ if (pPciConfig != NULL)
+ RtmpPciConfig = *pPciConfig;
+
+ if (pUsbConfig != NULL)
+ RtmpUsbConfig = *pUsbConfig;
+
+ /* init operators provided from us (DRIVER module) */
+ pDrvOps->RTMPAllocAdapterBlock = RTMPAllocAdapterBlock;
+ pDrvOps->RTMPFreeAdapter = RTMPFreeAdapter;
+
+ pDrvOps->RtmpRaDevCtrlExit = RtmpRaDevCtrlExit;
+ pDrvOps->RtmpRaDevCtrlInit = RtmpRaDevCtrlInit;
+
+ pDrvOps->RTMPSendPackets = RTMPSendPackets;
+#ifdef MBSS_SUPPORT
+ pDrvOps->MBSS_PacketSend = MBSS_PacketSend;
+#endif /* MBSS_SUPPORT */
+#ifdef WDS_SUPPORT
+ pDrvOps->WDS_PacketSend = WDS_PacketSend;
+#endif /* WDS_SUPPORT */
+#ifdef APCLI_SUPPORT
+ pDrvOps->APC_PacketSend = APC_PacketSend;
+#endif /* APCLI_SUPPORT */
+
+ pDrvOps->RTMP_COM_IoctlHandle = RTMP_COM_IoctlHandle;
+#ifdef CONFIG_AP_SUPPORT
+ pDrvOps->RTMP_AP_IoctlHandle = RTMP_AP_IoctlHandle;
+#endif /* CONFIG_AP_SUPPORT */
+
+ pDrvOps->RTMPDrvOpen = RTMPDrvOpen;
+ pDrvOps->RTMPDrvClose = RTMPDrvClose;
+ pDrvOps->RTMPInfClose = RTMPInfClose;
+ pDrvOps->rt28xx_init = rt28xx_init;
+
+ /* init operators provided from us and netif module */
+#ifdef RTMP_USB_SUPPORT
+ *pRtmpDrvNetOps = *pDrvNetOps;
+ pRtmpDrvNetOps->RtmpDrvUsbBulkOutDataPacketComplete = RTUSBBulkOutDataPacketComplete;
+ pRtmpDrvNetOps->RtmpDrvUsbBulkOutMLMEPacketComplete = RTUSBBulkOutMLMEPacketComplete;
+ pRtmpDrvNetOps->RtmpDrvUsbBulkOutNullFrameComplete = RTUSBBulkOutNullFrameComplete;
+#ifdef CONFIG_MULTI_CHANNEL
+ pRtmpDrvNetOps->RtmpDrvUsbBulkOutHCCANullFrameComplete = RTUSBBulkOutHCCANullFrameComplete;
+#endif /* CONFIG_MULTI_CHANNEL */
+
+/* pRtmpDrvNetOps->RtmpDrvUsbBulkOutRTSFrameComplete = RTUSBBulkOutRTSFrameComplete;*/
+ pRtmpDrvNetOps->RtmpDrvUsbBulkOutPsPollComplete = RTUSBBulkOutPsPollComplete;
+ pRtmpDrvNetOps->RtmpDrvUsbBulkRxComplete = RTUSBBulkRxComplete;
+ pRtmpDrvNetOps->RtmpDrvUsbBulkCmdRspEventComplete = RTUSBBulkCmdRspEventComplete;
+ *pDrvNetOps = *pRtmpDrvNetOps;
+#endif /* RTMP_USB_SUPPORT */
+}
+
+RTMP_BUILD_DRV_OPS_FUNCTION_BODY
+
+#endif /* OS_ABL_FUNC_SUPPORT */
+#endif /* LINUX */
+
+
+int rt28xx_init(VOID *pAdSrc, PSTRING pDefaultMac, PSTRING pHostName)
+{
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc;
+ UINT index;
+ NDIS_STATUS Status;
+
+ if (pAd == NULL)
+ return FALSE;
+
+// TODO: shiang-6590, fix me, we need a better place for this function call
+#ifdef RT6570
+ if (pAd->WlanFunCtrl.field.WLAN_EN == 0)
+ ral_wlan_chip_onoff(pAd, TRUE, FALSE);
+#endif /* RT6570 */
+
+#ifdef MT7601
+ if (IS_MT7601(pAd) && (pAd->WlanFunCtrl.field.WLAN_EN == 0))
+ MT7601_WLAN_ChipOnOff(pAd, TRUE, FALSE);
+#endif /* MT7601U */
+//---
+
+#ifdef RT3290
+ DBGPRINT(RT_DEBUG_OFF, ("MACVersion=0x%x\n", pAd->MACVersion));
+ if (IS_RT3290(pAd))
+ {
+ UINT32 MacRegValue;
+ OSCCTL_STRUC osCtrl = {.word = 0};
+ CMB_CTRL_STRUC cmbCtrl = {.word = 0};
+ WLAN_FUN_CTRL_STRUC WlanFunCtrl = {.word = 0};
+
+ RTMPEnableWlan(pAd, TRUE, TRUE);
+
+ RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &WlanFunCtrl.word);
+ if (WlanFunCtrl.field.WLAN_EN == TRUE)
+ {
+ WlanFunCtrl.field.PCIE_APP0_CLK_REQ = TRUE;
+ RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, WlanFunCtrl.word);
+ }
+
+ //Enable ROSC_EN first then CAL_REQ
+ RTMP_IO_READ32(pAd, OSCCTL, &osCtrl.word);
+ osCtrl.field.ROSC_EN = TRUE; /* HW force */
+ RTMP_IO_WRITE32(pAd, OSCCTL, osCtrl.word);
+
+ osCtrl.field.ROSC_EN = TRUE; /* HW force */
+ osCtrl.field.CAL_REQ = TRUE;
+ osCtrl.field.REF_CYCLE = 0x27;
+ RTMP_IO_WRITE32(pAd, OSCCTL, osCtrl.word);
+
+ RTMP_IO_READ32(pAd, CMB_CTRL, &cmbCtrl.word);
+ pAd->CmbCtrl.word = cmbCtrl.word;
+
+ /* Overwrite default Coex Parameter */
+ RTMP_IO_READ32(pAd, COEXCFG0, &MacRegValue);
+ MacRegValue &= ~(0xFF000000);
+ MacRegValue |= 0x5E000000;
+ RTMP_IO_WRITE32(pAd, COEXCFG0, MacRegValue);
+ }
+
+ if (IS_RT3290LE(pAd))
+ {
+ PLL_CTRL_STRUC PllCtrl;
+ RTMP_IO_READ32(pAd, PLL_CTRL, &PllCtrl.word);
+ PllCtrl.field.VCO_FIXED_CURRENT_CONTROL = 0x1;
+ RTMP_IO_WRITE32(pAd, PLL_CTRL, PllCtrl.word);
+ }
+#endif /* RT3290 */
+
+
+ /* reset Adapter flags*/
+ RTMP_CLEAR_FLAGS(pAd);
+
+ /* Init BssTab & ChannelInfo tabbles for auto channel select.*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ AutoChBssTableInit(pAd);
+ ChannelInfoInit(pAd);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef DOT11_N_SUPPORT
+ /* Allocate BA Reordering memory*/
+ if (ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM) != TRUE)
+ goto err1;
+#endif /* DOT11_N_SUPPORT */
+
+ /* Make sure MAC gets ready.*/
+ index = 0;
+ if (WaitForAsicReady(pAd) != TRUE)
+ goto err1;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MAC[Ver:Rev=0x%08x]\n", pAd->MACVersion));
+
+
+ if (MAX_LEN_OF_MAC_TABLE > MAX_AVAILABLE_CLIENT_WCID(pAd))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MAX_LEN_OF_MAC_TABLE can not be larger than MAX_AVAILABLE_CLIENT_WCID!!!!\n"));
+ goto err1;
+ }
+
+
+ /* Disable DMA*/
+ RT28XXDMADisable(pAd);
+
+#ifdef RLT_MAC
+ /* Initialze MCU control before load fw */
+ MCUCtrlInit(pAd);
+#endif /* RLT_MAC */
+
+ /* Load MCU firmware*/
+ Status = NICLoadFirmware(pAd);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", Status));
+ goto err1;
+ }
+
+ /* Disable interrupts here which is as soon as possible*/
+ /* This statement should never be true. We might consider to remove it later*/
+
+#ifdef RESOURCE_PRE_ALLOC
+ Status = RTMPInitTxRxRingMemory(pAd);
+#else
+ Status = RTMPAllocTxRxRingMemory(pAd);
+#endif /* RESOURCE_PRE_ALLOC */
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("RTMPAllocTxRxMemory failed, Status[=0x%08x]\n", Status));
+ goto err2;
+ }
+
+#ifdef WLAN_SKB_RECYCLE
+ skb_queue_head_init(&pAd->rx0_recycle);
+#endif /* WLAN_SKB_RECYCLE */
+
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
+
+ /* initialize MLME*/
+ Status = RtmpMgmtTaskInit(pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err3;
+
+ Status = MlmeInit(pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("MlmeInit failed, Status[=0x%08x]\n", Status));
+ goto err4;
+ }
+
+#ifdef RMTP_RBUS_SUPPORT
+#ifdef VIDEO_TURBINE_SUPPORT
+ VideoConfigInit(pAd);
+#endif /* VIDEO_TURBINE_SUPPORT */
+#endif /* RMTP_RBUS_SUPPORT */
+
+ /* Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default*/
+ UserCfgInit(pAd);
+
+
+ Status = RtmpNetTaskInit(pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err5;
+
+ CfgInitHook(pAd);
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ APInitialize(pAd);
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef BLOCK_NET_IF
+ initblockQueueTab(pAd);
+#endif /* BLOCK_NET_IF */
+
+ Status = MeasureReqTabInit(pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("MeasureReqTabInit failed, Status[=0x%08x]\n",Status));
+ goto err6;
+ }
+ Status = TpcReqTabInit(pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("TpcReqTabInit failed, Status[=0x%08x]\n",Status));
+ goto err6;
+ }
+
+ /* Init the hardware, we need to init asic before read registry, otherwise mac register will be reset*/
+
+ Status = NICInitializeAdapter(pAd, TRUE);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("NICInitializeAdapter failed, Status[=0x%08x]\n", Status));
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err6;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Read parameters from Config File */
+ /* unknown, it will be updated in NICReadEEPROMParameters */
+ pAd->RfIcType = RFIC_UNKNOWN;
+ Status = RTMPReadParametersHook(pAd);
+
+
+ DBGPRINT(RT_DEBUG_OFF, ("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode));
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("RTMPReadParametersHook failed, Status[=0x%08x]\n",Status));
+ goto err6;
+ }
+
+#ifdef RTMP_MAC_USB
+ pAd->CommonCfg.bMultipleIRP = FALSE;
+
+ if (pAd->CommonCfg.bMultipleIRP)
+ pAd->CommonCfg.NumOfBulkInIRP = RX_RING_SIZE;
+ else
+ pAd->CommonCfg.NumOfBulkInIRP = 1;
+#endif /* RTMP_MAC_USB */
+
+#ifdef DOT11_N_SUPPORT
+ /*Init Ba Capability parameters.*/
+/* RT28XX_BA_INIT(pAd);*/
+ pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity;
+ pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable;
+ pAd->CommonCfg.DesiredHtPhy.AmsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize;
+ pAd->CommonCfg.DesiredHtPhy.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode;
+ /* UPdata to HT IE*/
+ pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode;
+ pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize;
+ pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity;
+#endif /* DOT11_N_SUPPORT */
+
+ /* after reading Registry, we now know if in AP mode or STA mode*/
+
+ DBGPRINT(RT_DEBUG_OFF, ("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode));
+
+ /* We should read EEPROM for all cases. rt2860b*/
+ NICReadEEPROMParameters(pAd, (PSTRING)pDefaultMac);
+
+ DBGPRINT(RT_DEBUG_OFF, ("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode));
+
+#ifdef LED_CONTROL_SUPPORT
+ /* Send LED Setting to MCU */
+ RTMPInitLEDMode(pAd);
+#endif /* LED_CONTROL_SUPPORT */
+
+ NICInitAsicFromEEPROM(pAd); /* rt2860b */
+
+#ifdef RALINK_ATE
+ if (ATEInit(pAd) != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s(): ATE initialization failed !\n", __FUNCTION__));
+ goto err6;
+ }
+#endif /* RALINK_ATE */
+
+
+#ifdef RTMP_INTERNAL_TX_ALC
+ /* Initialize the desired TSSI table*/
+ RTMP_CHIP_ASIC_TSSI_TABLE_INIT(pAd);
+#endif /* RTMP_INTERNAL_TX_ALC */
+
+#ifdef RTMP_TEMPERATURE_COMPENSATION
+ /* Temperature compensation, initialize the lookup table */
+ DBGPRINT(RT_DEBUG_OFF, ("bAutoTxAgcG = %d\n", pAd->bAutoTxAgcG));
+
+ if (pAd->chipCap.bTempCompTxALC && pAd->bAutoTxAgcG)
+ InitLookupTable(pAd);
+#endif /* RTMP_TEMPERATURE_COMPENSATION */
+
+
+ /* Set PHY to appropriate mode*/
+ RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode);
+
+ /* No valid channels.*/
+ if (pAd->ChannelListNum == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n"));
+ goto err6;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ DBGPRINT(RT_DEBUG_OFF, ("MCS Set = %02x %02x %02x %02x %02x\n", pAd->CommonCfg.HtCapability.MCSSet[0],
+ pAd->CommonCfg.HtCapability.MCSSet[1], pAd->CommonCfg.HtCapability.MCSSet[2],
+ pAd->CommonCfg.HtCapability.MCSSet[3], pAd->CommonCfg.HtCapability.MCSSet[4]));
+#endif /* DOT11_N_SUPPORT */
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef AP_QLOAD_SUPPORT
+ QBSS_LoadInit(pAd);
+#endif /* AP_QLOAD_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* APInitialize(pAd);*/
+
+#ifdef IKANOS_VX_1X0
+ VR_IKANOS_FP_Init(pAd->ApCfg.BssidNum, pAd->PermanentAddress);
+#endif /* IKANOS_VX_1X0 */
+
+#ifdef RTMP_MAC_USB
+ AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x02, FALSE);
+ RTMPusecDelay(10000);
+#endif /* RTMP_MAC_USB */
+
+#ifdef RALINK_ATE
+#endif /* RALINK_ATE */
+
+#ifdef CONFIG_AP_SUPPORT
+
+ /* Initialize RF register to default value*/
+
+ if (pAd->OpMode == OPMODE_AP)
+ {
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /*
+ Some modules init must be called before APStartUp().
+ Or APStartUp() will make up beacon content and call
+ other modules API to get some information to fill.
+ */
+
+
+
+ if (pAd && (Status != NDIS_STATUS_SUCCESS))
+ {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+ {
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
+ }
+ }
+ else if (pAd)
+ {
+ /* Microsoft HCT require driver send a disconnect event after driver initialization.*/
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED);
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if (pAd->ApCfg.bAutoChannelAtBootup || (pAd->CommonCfg.Channel == 0))
+ {
+ /* Enable Interrupt first due to we need to scan channel to receive beacons.*/
+ RTMP_IRQ_ENABLE(pAd);
+#ifdef RTMP_MAC_USB
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS);
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
+
+
+ /* Support multiple BulkIn IRP,*/
+ /* the value on pAd->CommonCfg.NumOfBulkInIRP may be large than 1.*/
+
+ for(index=0; index<pAd->CommonCfg.NumOfBulkInIRP; index++)
+ {
+ RTUSBBulkReceive(pAd);
+ DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkReceive!\n" ));
+ }
+
+#endif /* RTMP_MAC_USB */
+ /* Now Enable RxTx*/
+ RTMPEnableRxTx(pAd);
+ //RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP);
+
+ /* Let BBP register at 20MHz to do scan */
+ rtmp_bbp_set_bw(pAd, BW_20);
+ DBGPRINT(RT_DEBUG_ERROR, ("SYNC - BBP R4 to 20MHz.l\n"));
+
+ /* Now we can receive the beacon and do the listen beacon*/
+ /* use default BW to select channel*/
+ pAd->CommonCfg.Channel = AP_AUTO_CH_SEL(pAd, pAd->ApCfg.AutoChannelAlg);
+ pAd->ApCfg.bAutoChannelAtBootup = FALSE;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ /* If WMODE_CAP_N(phymode) and BW=40 check extension channel, after select channel */
+ N_ChannelCheck(pAd);
+
+#ifdef DOT11N_DRAFT3
+ /*
+ We only do this Overlapping BSS Scan when system up, for the
+ other situation of channel changing, we depends on station's
+ report to adjust ourself.
+ */
+ if (pAd->CommonCfg.bForty_Mhz_Intolerant == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Disable 20/40 BSSCoex Channel Scan(BssCoex=%d, 40MHzIntolerant=%d)\n",
+ pAd->CommonCfg.bBssCoexEnable,
+ pAd->CommonCfg.bForty_Mhz_Intolerant));
+ }
+ else if(pAd->CommonCfg.bBssCoexEnable == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Enable 20/40 BSSCoex Channel Scan(BssCoex=%d)\n",
+ pAd->CommonCfg.bBssCoexEnable));
+ APOverlappingBSSScan(pAd);
+ }
+
+ RTMP_11N_D3_TimerInit(pAd);
+/* RTMPInitTimer(pAd, &pAd->CommonCfg.Bss2040CoexistTimer, GET_TIMER_FUNCTION(Bss2040CoexistTimeOut), pAd, FALSE);*/
+#endif /* DOT11N_DRAFT3 */
+#endif /* DOT11_N_SUPPORT */
+
+ APStartUp(pAd);
+ DBGPRINT(RT_DEBUG_OFF, ("Main bssid = %02x:%02x:%02x:%02x:%02x:%02x\n",
+ PRINT_MAC(pAd->ApCfg.MBSSID[BSS0].Bssid)));
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef RTMP_MAC_USB
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS);
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
+
+
+ /* Support multiple BulkIn IRP,*/
+ /* the value on pAd->CommonCfg.NumOfBulkInIRP may be large than 1.*/
+ for(index=0; index<pAd->CommonCfg.NumOfBulkInIRP; index++)
+ {
+ RTUSBBulkReceive(pAd);
+ DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkReceive!\n" ));
+ }
+#endif /* RTMP_MAC_USB */
+ }/* end of else*/
+
+ /* Set up the Mac address*/
+#ifdef CONFIG_AP_SUPPORT
+ RtmpOSNetDevAddrSet(pAd->OpMode, pAd->net_dev, &pAd->CurrentAddress[0], NULL);
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Various AP function init*/
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef MBSS_SUPPORT
+ /* the function can not be moved to RT2860_probe() even register_netdev()
+ is changed as register_netdevice().
+ Or in some PC, kernel will panic (Fedora 4) */
+/* RT28xx_MBSS_Init(pAd, pAd->net_dev); os abl move to rt_main_dev.c*/
+#endif /* MBSS_SUPPORT */
+
+#ifdef WDS_SUPPORT
+/* RT28xx_WDS_Init(pAd, pAd->net_dev);*/
+#endif /* WDS_SUPPORT */
+
+#ifdef APCLI_SUPPORT
+/* RT28xx_ApCli_Init(pAd, pAd->net_dev);*/
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef UAPSD_SUPPORT
+ UAPSD_Init(pAd);
+#endif /* UAPSD_SUPPORT */
+
+ /* assign function pointers*/
+#ifdef MAT_SUPPORT
+ /* init function pointers, used in OS_ABL */
+ RTMP_MATOpsInit(pAd);
+#endif /* MAT_SUPPORT */
+
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef MAT_SUPPORT
+ MATEngineInit(pAd);
+#endif /* MAT_SUPPORT */
+
+#ifdef CLIENT_WDS
+ CliWds_ProxyTabInit(pAd);
+#endif /* CLIENT_WDS */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /* auto-fall back settings */
+#ifdef RANGE_EXTEND
+ RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, 0xedcba980);
+#endif // RANGE_EXTEND //
+#ifdef DOT11N_SS3_SUPPORT
+ if (pAd->CommonCfg.TxStream >= 3)
+ {
+ RTMP_IO_WRITE32(pAd, TX_FBK_CFG_3S_0, 0x12111008);
+ RTMP_IO_WRITE32(pAd, TX_FBK_CFG_3S_1, 0x16151413);
+ }
+#endif /* DOT11N_SS3_SUPPORT */
+
+#ifdef STREAM_MODE_SUPPORT
+ RtmpStreamModeInit(pAd);
+#endif /* STREAM_MODE_SUPPORT */
+
+
+#ifdef DOT11_N_SUPPORT
+#ifdef TXBF_SUPPORT
+ if (pAd->CommonCfg.ITxBfTimeout)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R179, 0x02);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R180, 0);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R182, pAd->CommonCfg.ITxBfTimeout & 0xFF);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R180, 1);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R182, (pAd->CommonCfg.ITxBfTimeout>>8) & 0xFF);
+ }
+
+ if (pAd->CommonCfg.ETxBfTimeout)
+ {
+ RTMP_IO_WRITE32(pAd, TX_TXBF_CFG_3, pAd->CommonCfg.ETxBfTimeout);
+ }
+#endif /* TXBF_SUPPORT */
+#endif /* DOT11_N_SUPPORT */
+
+
+
+#ifdef RT3290
+ if (IS_RT3290(pAd))
+ {
+ WLAN_FUN_CTRL_STRUC WlanFunCtrl = {.word = 0};
+ RTMP_MAC_PWRSV_EN(pAd, TRUE, TRUE);
+ //
+ // Too much time for reading efuse(enter/exit L1), and our device will hang up
+ // Enable L1
+ //
+ RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &WlanFunCtrl.word);
+ if (WlanFunCtrl.field.WLAN_EN == TRUE)
+ {
+ WlanFunCtrl.field.PCIE_APP0_CLK_REQ = FALSE;
+ RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, WlanFunCtrl.word);
+ }
+ }
+#endif /* RT3290 */
+
+ DBGPRINT_S(Status, ("<==== rt28xx_init, Status=%x\n", Status));
+
+ return TRUE;
+
+/*err7:
+ APStop(pAd);*/
+err6:
+
+#ifdef IGMP_SNOOP_SUPPORT
+ MultiCastFilterTableReset(&pAd->pMulticastFilterTable);
+#endif /* IGMP_SNOOP_SUPPORT */
+
+ MeasureReqTabExit(pAd);
+ TpcReqTabExit(pAd);
+err5:
+ RtmpNetTaskExit(pAd);
+ UserCfgExit(pAd);
+err4:
+ MlmeHalt(pAd);
+ //RTMP_TimerListRelease(pAd);
+ RTMP_AllTimerListRelease(pAd);
+err3:
+ RtmpMgmtTaskExit(pAd);
+#ifdef RTMP_TIMER_TASK_SUPPORT
+ NdisFreeSpinLock(&pAd->TimerQLock);
+#endif /* RTMP_TIMER_TASK_SUPPORT */
+err2:
+#ifdef RESOURCE_PRE_ALLOC
+ RTMPResetTxRxRingMemory(pAd);
+#else
+ RTMPFreeTxRxRingMemory(pAd);
+#endif /* RESOURCE_PRE_ALLOC */
+
+err1:
+
+#ifdef RLT_MAC
+ MCUCtrlExit(pAd);
+#endif /* RLT_MAC */
+
+#ifdef CONFIG_AP_SUPPORT
+ /* Free BssTab & ChannelInfo tabbles.*/
+ AutoChBssTableDestroy(pAd);
+ ChannelInfoDestroy(pAd);
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef RT3290
+ if (IS_RT3290(pAd))
+ RTMPEnableWlan(pAd, FALSE, FALSE);
+#endif /* RT3290 */
+
+#ifdef DOT11_N_SUPPORT
+ if(pAd->mpdu_blk_pool.mem)
+ os_free_mem(pAd, pAd->mpdu_blk_pool.mem); /* free BA pool*/
+#endif /* DOT11_N_SUPPORT */
+
+ /* shall not set priv to NULL here because the priv didn't been free yet.*/
+ /*net_dev->priv = 0;*/
+#ifdef INF_AMAZON_SE
+err0:
+#endif /* INF_AMAZON_SE */
+#ifdef ST
+err0:
+#endif /* ST */
+
+ DBGPRINT(RT_DEBUG_ERROR, ("!!! rt28xx init fail !!!\n"));
+ return FALSE;
+}
+
+
+VOID RTMPDrvOpen(
+ IN VOID *pAdSrc)
+{
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc;
+
+ RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_MCU_SLEEP);
+
+
+#ifdef FPGA_MODE
+#ifdef CUSTOMER_DEMO
+ set_fpga_mode(pAd, "6");
+#endif /* CUSTOMER_DEMO */
+#endif /* FPGA_MODE */
+
+ /* Enable Interrupt*/
+ RTMP_IRQ_ENABLE(pAd);
+
+ /* Now Enable RxTx*/
+ RTMPEnableRxTx(pAd);
+
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP);
+
+ {
+ UINT32 reg = 0;
+ RTMP_IO_READ32(pAd, 0x1300, &reg); /* clear garbage interrupts*/
+ printk("0x1300 = %08x\n", reg);
+ }
+
+ {
+/* u32 reg;*/
+/* UINT8 byte;*/
+/* u16 tmp;*/
+
+/* RTMP_IO_READ32(pAd, XIFS_TIME_CFG, &reg);*/
+
+/* tmp = 0x0805;*/
+/* reg = (reg & 0xffff0000) | tmp;*/
+/* RTMP_IO_WRITE32(pAd, XIFS_TIME_CFG, reg);*/
+
+ }
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef BG_FT_SUPPORT
+ BG_FTPH_Init();
+#endif /* BG_FT_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+//+++Add by shiang for debug
+ DBGPRINT(RT_DEBUG_OFF, ("%s(1):Check if PDMA is idle!\n", __FUNCTION__));
+ AsicWaitPDMAIdle(pAd, 5, 10);
+//---Add by shiang for debug
+
+//+++Add by shiang for debug
+ DBGPRINT(RT_DEBUG_OFF, ("%s(2):Check if PDMA is idle!\n", __FUNCTION__));
+ AsicWaitPDMAIdle(pAd, 5, 10);
+//---Add by shiang for debug
+
+
+#ifdef WSC_INCLUDED
+#ifdef CONFIG_AP_SUPPORT
+ if ((pAd->OpMode == OPMODE_AP)
+ )
+ {
+ INT index;
+ for (index = 0; index < pAd->ApCfg.BssidNum; index++)
+ {
+#ifdef HOSTAPD_SUPPORT
+ if (pAd->ApCfg.MBSSID[index].Hostapd == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n"));
+ }
+ else
+#endif /*HOSTAPD_SUPPORT*/
+ {
+ PWSC_CTRL pWscControl;
+ UCHAR zeros16[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+ pWscControl = &pAd->ApCfg.MBSSID[index].WscControl;
+ DBGPRINT(RT_DEBUG_TRACE, ("Generate UUID for apidx(%d)\n", index));
+ if (NdisEqualMemory(&pWscControl->Wsc_Uuid_E[0], zeros16, UUID_LEN_HEX))
+ WscGenerateUUID(pAd, &pWscControl->Wsc_Uuid_E[0], &pWscControl->Wsc_Uuid_Str[0], index, FALSE);
+ WscInit(pAd, FALSE, index);
+ }
+ }
+
+#ifdef APCLI_SUPPORT
+ for(index = 0; index < MAX_APCLI_NUM; index++)
+ {
+ PWSC_CTRL pWpsCtrl = &pAd->ApCfg.ApCliTab[index].WscControl;
+
+ pWpsCtrl->pAd = pAd;
+ NdisZeroMemory(pWpsCtrl->EntryAddr, MAC_ADDR_LEN);
+ pWpsCtrl->WscConfigMethods= 0x018C;
+ RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_WSC_INIT, 0, (VOID *)&pAd->ApCfg.ApCliTab[index], index);
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /* WSC hardware push button function 0811 */
+ WSC_HDR_BTN_Init(pAd);
+#endif /* WSC_INCLUDED */
+
+#ifdef CONFIG_MULTI_CHANNEL
+ MultiChannelThreadInit(pAd);
+#endif /* CONFIG_MULTI_CHANNEL */
+
+
+}
+
+
+VOID RTMPDrvClose(
+ IN VOID *pAdSrc,
+ IN VOID *net_dev)
+{
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc;
+ BOOLEAN Cancelled;
+ UINT32 i = 0;
+
+
+ Cancelled = FALSE;
+
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef BG_FT_SUPPORT
+ BG_FTPH_Remove();
+#endif /* BG_FT_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+#if ((defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT)) && defined(WOW_IFDOWN_SUPPORT)
+ if (pAd->WOW_Cfg.bEnable == FALSE)
+#endif /* ((defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT)) && defined(WOW_IFDOWN_SUPPORT) */
+ {
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD);
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+ }
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+ if (pAd->CommonCfg.pChDesp != NULL)
+ os_free_mem(NULL, pAd->CommonCfg.pChDesp);
+ pAd->CommonCfg.pChDesp = NULL;
+ pAd->CommonCfg.DfsType = MAX_RD_REGION;
+#endif /* EXT_BUILD_CHANNEL_LIST */
+ pAd->CommonCfg.bCountryFlag = FALSE;
+
+
+
+#ifdef WDS_SUPPORT
+ WdsDown(pAd);
+#endif /* WDS_SUPPORT */
+
+ for (i = 0 ; i < NUM_OF_TX_RING; i++)
+ {
+ while (pAd->DeQueueRunning[i] == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Waiting for TxQueue[%d] done..........\n", i));
+ RTMPusecDelay(1000);
+ }
+ }
+
+#ifdef RTMP_MAC_USB
+ RtmpOsUsbEmptyUrbCheck(&pAd->wait, &pAd->BulkInLock, &pAd->PendingRx);
+
+#endif /* RTMP_MAC_USB */
+
+#ifdef CONFIG_AP_SUPPORT
+
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef RTMP_MAC_USB
+ RTMPCancelTimer(&pAd->CommonCfg.BeaconUpdateTimer, &Cancelled);
+#endif /* RTMP_MAC_USB */
+
+#ifdef DOT11N_DRAFT3
+ if (pAd->CommonCfg.Bss2040CoexistFlag & BSS_2040_COEXIST_TIMER_FIRED)
+ {
+ RTMPCancelTimer(&pAd->CommonCfg.Bss2040CoexistTimer, &Cancelled);
+ pAd->CommonCfg.Bss2040CoexistFlag = 0;
+ }
+#endif /* DOT11N_DRAFT3 */
+
+ /* PeriodicTimer already been canceled by MlmeHalt() API.*/
+ /*RTMPCancelTimer(&pAd->PeriodicTimer, &Cancelled);*/
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Stop Mlme state machine*/
+ MlmeHalt(pAd);
+
+ /* Close net tasklets*/
+ RtmpNetTaskExit(pAd);
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef MAT_SUPPORT
+ MATEngineExit(pAd);
+#endif /* MAT_SUPPORT */
+
+#ifdef CLIENT_WDS
+ CliWds_ProxyTabDestory(pAd);
+#endif /* CLIENT_WDS */
+ /* Shutdown Access Point function, release all related resources */
+ APShutdown(pAd);
+
+/*#ifdef AUTO_CH_SELECT_ENHANCE*/
+ /* Free BssTab & ChannelInfo tabbles.*/
+/* AutoChBssTableDestroy(pAd); */
+/* ChannelInfoDestroy(pAd); */
+/*#endif AUTO_CH_SELECT_ENHANCE */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ MeasureReqTabExit(pAd);
+ TpcReqTabExit(pAd);
+
+#ifdef LED_CONTROL_SUPPORT
+ RTMPExitLEDMode(pAd);
+#endif // LED_CONTROL_SUPPORT
+
+ /* Close kernel threads*/
+ RtmpMgmtTaskExit(pAd);
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* must after RtmpMgmtTaskExit(); Or pAd->pChannelInfo will be NULL */
+ /* Free BssTab & ChannelInfo tabbles.*/
+ AutoChBssTableDestroy(pAd);
+ ChannelInfoDestroy(pAd);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef RLT_MAC
+ MCUCtrlExit(pAd);
+#endif /* RLT_MAC */
+
+ /* Free IRQ*/
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+ {
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
+ }
+
+#ifdef SINGLE_SKU_V2
+ {
+ CH_POWER *ch, *ch_temp;
+ ch = pAd->SingleSkuPwrList.pHead;
+ while (ch )
+ {
+ ch_temp = ch->pNext;
+ delEntryList(&pAd->SingleSkuPwrList, (PLIST_ENTRY)ch);
+ os_free_mem(NULL, ch->Channel);
+ os_free_mem(NULL, ch);
+ ch = ch_temp;
+ }
+ }
+#endif /* SINGLE_SKU_V2 */
+
+ /* Free Ring or USB buffers*/
+#ifdef RESOURCE_PRE_ALLOC
+ RTMPResetTxRxRingMemory(pAd);
+#else
+ /* Free Ring or USB buffers*/
+ RTMPFreeTxRxRingMemory(pAd);
+#endif /* RESOURCE_PRE_ALLOC */
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+
+#ifdef WLAN_SKB_RECYCLE
+ skb_queue_purge(&pAd->rx0_recycle);
+#endif /* WLAN_SKB_RECYCLE */
+
+#ifdef DOT11_N_SUPPORT
+ /* Free BA reorder resource*/
+ ba_reordering_resource_release(pAd);
+#endif /* DOT11_N_SUPPORT */
+
+ UserCfgExit(pAd); /* must after ba_reordering_resource_release */
+
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP);
+
+/*+++Modify by woody to solve the bulk fail+++*/
+
+ /* clear MAC table */
+ /* TODO: do not clear spin lock, such as fLastChangeAccordingMfbLock */
+ NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE));
+
+ /* release all timers */
+ RTMPusecDelay(2000);
+ //RTMP_TimerListRelease(pAd);
+ RTMP_AllTimerListRelease(pAd);
+
+#ifdef CONFIG_MULTI_CHANNEL
+ MultiChannelThreadExit(pAd);
+#endif /* CONFIG_MULTI_CHANNEL */
+
+#ifdef RTMP_TIMER_TASK_SUPPORT
+ NdisFreeSpinLock(&pAd->TimerQLock);
+#endif /* RTMP_TIMER_TASK_SUPPORT */
+}
+
+
+VOID RTMPInfClose(
+ IN VOID *pAdSrc)
+{
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc;
+
+
+#ifdef CONFIG_AP_SUPPORT
+ pAd->ApCfg.MBSSID[MAIN_MBSSID].bBcnSntReq = FALSE;
+
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* kick out all STAs behind the bss.*/
+ MbssKickOutStas(pAd, MAIN_MBSSID, REASON_DISASSOC_INACTIVE);
+ }
+
+ APMakeAllBssBeacon(pAd);
+ APUpdateAllBeaconFrame(pAd);
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+}
+
+
+
+
+PNET_DEV RtmpPhyNetDevMainCreate(
+ IN VOID *pAdSrc)
+{
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc;
+ PNET_DEV pDevNew;
+ UINT32 MC_RowID = 0, IoctlIF = 0;
+
+
+ pAd = pAd;
+
+#ifdef MULTIPLE_CARD_SUPPORT
+ MC_RowID = pAd->MC_RowID;
+#endif /* MULTIPLE_CARD_SUPPORT */
+#ifdef HOSTAPD_SUPPORT
+ IoctlIF = pAd->IoctlIF;
+#endif /* HOSTAPD_SUPPORT */
+
+ pDevNew = RtmpOSNetDevCreate((INT32)MC_RowID, (UINT32 *)&IoctlIF,
+ INT_MAIN, 0, sizeof(PRTMP_ADAPTER), INF_MAIN_DEV_NAME);
+
+#ifdef HOSTAPD_SUPPORT
+ pAd->IoctlIF = IoctlIF;
+#endif /* HOSTAPD_SUPPORT */
+
+ return pDevNew;
+}
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/rtmp_timer.c b/cleopatre/devkit/mt7601udrv/common/rtmp_timer.c
new file mode 100644
index 0000000000..b3ece739e0
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rtmp_timer.c
@@ -0,0 +1,358 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2008, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ rtmp_timer.c
+
+ Abstract:
+ task for timer handling
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+ Shiang Tu 08-28-2008 init version
+
+*/
+
+#include "rt_config.h"
+
+
+BUILD_TIMER_FUNCTION(MlmePeriodicExec);
+/*BUILD_TIMER_FUNCTION(MlmeRssiReportExec);*/
+BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout);
+BUILD_TIMER_FUNCTION(APSDPeriodicExec);
+BUILD_TIMER_FUNCTION(EnqueueStartForPSKExec);
+
+
+
+#ifdef CONFIG_MULTI_CHANNEL
+BUILD_TIMER_FUNCTION(MCC_ChangeAction);
+BUILD_TIMER_FUNCTION(ConcurrentP2PConnectTimeout);
+#endif /* CONFIG_MULTI_CHANNEL */
+
+
+#ifdef RTMP_MAC_USB
+BUILD_TIMER_FUNCTION(BeaconUpdateExec);
+#endif /* RTMP_MAC_USB */
+
+#ifdef CONFIG_AP_SUPPORT
+extern VOID APDetectOverlappingExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+BUILD_TIMER_FUNCTION(APDetectOverlappingExec);
+
+#ifdef DOT11N_DRAFT3
+BUILD_TIMER_FUNCTION(Bss2040CoexistTimeOut);
+#endif /* DOT11N_DRAFT3 */
+
+BUILD_TIMER_FUNCTION(GREKEYPeriodicExec);
+BUILD_TIMER_FUNCTION(CMTimerExec);
+BUILD_TIMER_FUNCTION(WPARetryExec);
+#ifdef AP_SCAN_SUPPORT
+BUILD_TIMER_FUNCTION(APScanTimeout);
+#endif /* AP_SCAN_SUPPORT */
+BUILD_TIMER_FUNCTION(APQuickResponeForRateUpExec);
+#ifdef IDS_SUPPORT
+BUILD_TIMER_FUNCTION(RTMPIdsPeriodicExec);
+#endif /* IDS_SUPPORT */
+
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef WSC_INCLUDED
+BUILD_TIMER_FUNCTION(WscEAPOLTimeOutAction);
+BUILD_TIMER_FUNCTION(Wsc2MinsTimeOutAction);
+BUILD_TIMER_FUNCTION(WscUPnPMsgTimeOutAction);
+BUILD_TIMER_FUNCTION(WscM2DTimeOutAction);
+
+BUILD_TIMER_FUNCTION(WscPBCTimeOutAction);
+BUILD_TIMER_FUNCTION(WscScanTimeOutAction);
+BUILD_TIMER_FUNCTION(WscProfileRetryTimeout);
+#ifdef WSC_LED_SUPPORT
+BUILD_TIMER_FUNCTION(WscLEDTimer);
+BUILD_TIMER_FUNCTION(WscSkipTurnOffLEDTimer);
+#endif /* WSC_LED_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+BUILD_TIMER_FUNCTION(WscUpdatePortCfgTimeout);
+#ifdef WSC_V2_SUPPORT
+BUILD_TIMER_FUNCTION(WscSetupLockTimeout);
+#endif /* WSC_V2_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#endif /* WSC_INCLUDED */
+
+
+
+#ifdef TXBF_SUPPORT
+BUILD_TIMER_FUNCTION(eTxBfProbeTimerExec);
+#endif /* TXBF_SUPPORT */
+
+
+#ifdef RALINK_ATE
+BUILD_TIMER_FUNCTION(ATEPeriodicExec);
+#endif /* RALINK_ATE */
+
+#ifdef RTMP_TIMER_TASK_SUPPORT
+static void RtmpTimerQHandle(RTMP_ADAPTER *pAd)
+{
+/*#ifndef KTHREAD_SUPPORT*/
+ int status;
+/*#endif*/
+ RALINK_TIMER_STRUCT *pTimer;
+ RTMP_TIMER_TASK_ENTRY *pEntry;
+ unsigned long irqFlag;
+ RTMP_OS_TASK *pTask;
+
+
+ pTask = &pAd->timerTask;
+ while(!RTMP_OS_TASK_IS_KILLED(pTask))
+ {
+ pTimer = NULL;
+
+ if (RtmpOSTaskWait(pAd, pTask, &status) == FALSE)
+ {
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+ break;
+ }
+
+ if (pAd->TimerQ.status == RTMP_TASK_STAT_STOPED)
+ break;
+
+ /* event happened.*/
+ while(pAd->TimerQ.pQHead)
+ {
+ RTMP_INT_LOCK(&pAd->TimerQLock, irqFlag);
+ pEntry = pAd->TimerQ.pQHead;
+ if (pEntry)
+ {
+ pTimer = pEntry->pRaTimer;
+
+ /* update pQHead*/
+ pAd->TimerQ.pQHead = pEntry->pNext;
+ if (pEntry == pAd->TimerQ.pQTail)
+ pAd->TimerQ.pQTail = NULL;
+
+ /* return this queue entry to timerQFreeList.*/
+ pEntry->pNext = pAd->TimerQ.pQPollFreeList;
+ pAd->TimerQ.pQPollFreeList = pEntry;
+ }
+ RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlag);
+
+ if (pTimer)
+ {
+ if ((pTimer->handle != NULL) && (!pAd->PM_FlgSuspend))
+ pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer);
+ if ((pTimer->Repeat) && (pTimer->State == FALSE))
+ RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue);
+ }
+ }
+
+/*#ifndef KTHREAD_SUPPORT*/
+ if (status != 0)
+ {
+ pAd->TimerQ.status = RTMP_TASK_STAT_STOPED;
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+ break;
+ }
+/*#endif*/
+ }
+}
+
+
+INT RtmpTimerQThread(
+ IN ULONG Context)
+{
+ RTMP_OS_TASK *pTask;
+ PRTMP_ADAPTER pAd = NULL;
+
+
+ pTask = (RTMP_OS_TASK *)Context;
+ pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask);
+
+ if (pAd == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,( "%s:: pAd is NULL!\n",__FUNCTION__));
+ return 0;
+ }
+
+ RtmpOSTaskCustomize(pTask);
+
+ RtmpTimerQHandle(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__));
+ /* notify the exit routine that we're actually exiting now
+ *
+ * complete()/wait_for_completion() is similar to up()/down(),
+ * except that complete() is safe in the case where the structure
+ * is getting deleted in a parallel mode of execution (i.e. just
+ * after the down() -- that's necessary for the thread-shutdown
+ * case.
+ *
+ * complete_and_exit() goes even further than this -- it is safe in
+ * the case that the thread of the caller is going away (not just
+ * the structure) -- this is necessary for the module-remove case.
+ * This is important in preemption kernels, which transfer the flow
+ * of execution immediately upon a complete().
+ */
+ RtmpOSTaskNotifyToExit(pTask);
+
+ return 0;
+
+}
+
+
+RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert(
+ IN RTMP_ADAPTER *pAd,
+ IN RALINK_TIMER_STRUCT *pTimer)
+{
+ RTMP_TIMER_TASK_ENTRY *pQNode = NULL, *pQTail;
+ unsigned long irqFlags;
+ RTMP_OS_TASK *pTask = &pAd->timerTask;
+
+ RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
+ if (pAd->TimerQ.status & RTMP_TASK_CAN_DO_INSERT)
+ {
+ if(pAd->TimerQ.pQPollFreeList)
+ {
+ pQNode = pAd->TimerQ.pQPollFreeList;
+ pAd->TimerQ.pQPollFreeList = pQNode->pNext;
+
+ pQNode->pRaTimer = pTimer;
+ pQNode->pNext = NULL;
+
+ pQTail = pAd->TimerQ.pQTail;
+ if (pAd->TimerQ.pQTail != NULL)
+ pQTail->pNext = pQNode;
+ pAd->TimerQ.pQTail = pQNode;
+ if (pAd->TimerQ.pQHead == NULL)
+ pAd->TimerQ.pQHead = pQNode;
+ }
+ }
+ RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags);
+
+ if (pQNode)
+ {
+ RTMP_OS_TASK_WAKE_UP(pTask);
+ }
+
+ return pQNode;
+}
+
+
+BOOLEAN RtmpTimerQRemove(
+ IN RTMP_ADAPTER *pAd,
+ IN RALINK_TIMER_STRUCT *pTimer)
+{
+ RTMP_TIMER_TASK_ENTRY *pNode, *pPrev = NULL;
+ unsigned long irqFlags;
+
+ RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
+ if (pAd->TimerQ.status >= RTMP_TASK_STAT_INITED)
+ {
+ pNode = pAd->TimerQ.pQHead;
+ while (pNode)
+ {
+ if (pNode->pRaTimer == pTimer)
+ break;
+ pPrev = pNode;
+ pNode = pNode->pNext;
+ }
+
+ /* Now move it to freeList queue.*/
+ if (pNode)
+ {
+ if (pNode == pAd->TimerQ.pQHead)
+ pAd->TimerQ.pQHead = pNode->pNext;
+ if (pNode == pAd->TimerQ.pQTail)
+ pAd->TimerQ.pQTail = pPrev;
+ if (pPrev != NULL)
+ pPrev->pNext = pNode->pNext;
+
+ /* return this queue entry to timerQFreeList.*/
+ pNode->pNext = pAd->TimerQ.pQPollFreeList;
+ pAd->TimerQ.pQPollFreeList = pNode;
+ }
+ }
+ RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags);
+
+ return TRUE;
+}
+
+
+void RtmpTimerQExit(RTMP_ADAPTER *pAd)
+{
+ RTMP_TIMER_TASK_ENTRY *pTimerQ;
+ unsigned long irqFlags;
+
+ RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
+ while (pAd->TimerQ.pQHead)
+ {
+ pTimerQ = pAd->TimerQ.pQHead;
+ pAd->TimerQ.pQHead = pTimerQ->pNext;
+ /* remove the timeQ*/
+ }
+ pAd->TimerQ.pQPollFreeList = NULL;
+ os_free_mem(pAd, pAd->TimerQ.pTimerQPoll);
+ pAd->TimerQ.pQTail = NULL;
+ pAd->TimerQ.pQHead = NULL;
+/*#ifndef KTHREAD_SUPPORT*/
+ pAd->TimerQ.status = RTMP_TASK_STAT_STOPED;
+/*#endif*/
+ RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags);
+/* NdisFreeSpinLock(&pAd->TimerQLock); */
+}
+
+
+void RtmpTimerQInit(RTMP_ADAPTER *pAd)
+{
+ int i;
+ RTMP_TIMER_TASK_ENTRY *pQNode, *pEntry;
+ unsigned long irqFlags;
+
+ NdisAllocateSpinLock(pAd, &pAd->TimerQLock);
+
+ NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ));
+
+ os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX);
+ if (pAd->TimerQ.pTimerQPoll)
+ {
+ pEntry = NULL;
+ pQNode = (RTMP_TIMER_TASK_ENTRY *)pAd->TimerQ.pTimerQPoll;
+ NdisZeroMemory(pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX);
+
+ RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags);
+ for (i = 0 ;i <TIMER_QUEUE_SIZE_MAX; i++)
+ {
+ pQNode->pNext = pEntry;
+ pEntry = pQNode;
+ pQNode++;
+ }
+ pAd->TimerQ.pQPollFreeList = pEntry;
+ pAd->TimerQ.pQHead = NULL;
+ pAd->TimerQ.pQTail = NULL;
+ pAd->TimerQ.status = RTMP_TASK_STAT_INITED;
+ RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags);
+ }
+}
+#endif /* RTMP_TIMER_TASK_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/rtusb_bulk.c b/cleopatre/devkit/mt7601udrv/common/rtusb_bulk.c
new file mode 100644
index 0000000000..31a2b2f6d5
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rtusb_bulk.c
@@ -0,0 +1,1693 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2006, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ rtusb_bulk.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+ Paul Lin 06-25-2004 created
+
+*/
+
+#ifdef RTMP_MAC_USB
+
+
+#include "rt_config.h"
+/* Match total 6 bulkout endpoint to corresponding queue.*/
+
+#ifdef CONFIG_MULTI_CHANNEL
+UCHAR EpToQueue[6]={FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_HCCA, FIFO_MGMT};
+#else
+UCHAR EpToQueue[6]={FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_EDCA, FIFO_MGMT};
+#endif /* CONFIG_MULTI_CHANNEL */
+
+
+
+
+#ifdef INF_AMAZON_SE
+UINT16 MaxBulkOutsSizeLimit[5][4] =
+{
+ /* Priority high -> low*/
+ { 24576, 2048, 2048, 2048 }, /* 0 AC */
+ { 24576, 2048, 2048, 2048 }, /* 1 AC */
+ { 24576, 2048, 2048, 2048 }, /* 2 ACs*/
+ { 24576, 6144, 2048, 2048 }, /* 3 ACs*/
+ { 24576, 6144, 4096, 2048 } /* 4 ACs*/
+};
+
+
+VOID SoftwareFlowControl(
+ IN PRTMP_ADAPTER pAd)
+{
+ BOOLEAN ResetBulkOutSize=FALSE;
+ UCHAR i=0,RunningQueueNo=0,QueIdx=0,HighWorkingAcCount=0;
+ UINT PacketsInQueueSize=0;
+ UCHAR Priority[]={1,0,2,3};
+
+ for (i=0;i<NUM_OF_TX_RING;i++)
+ {
+
+ if (pAd->TxContext[i].CurWritePosition>=pAd->TxContext[i].ENextBulkOutPosition)
+ {
+ PacketsInQueueSize=pAd->TxContext[i].CurWritePosition-pAd->TxContext[i].ENextBulkOutPosition;
+ }
+ else
+ {
+ PacketsInQueueSize=MAX_TXBULK_SIZE-pAd->TxContext[i].ENextBulkOutPosition+pAd->TxContext[i].CurWritePosition;
+ }
+
+ if (pAd->BulkOutDataSizeCount[i]>20480 || PacketsInQueueSize>6144)
+ {
+ RunningQueueNo++;
+ pAd->BulkOutDataFlag[i]=TRUE;
+ }
+ else
+ pAd->BulkOutDataFlag[i]=FALSE;
+
+ pAd->BulkOutDataSizeCount[i]=0;
+ }
+
+ if (RunningQueueNo>pAd->LastRunningQueueNo)
+ {
+ DBGPRINT(RT_DEBUG_INFO,("SoftwareFlowControl reset %d > %d \n",RunningQueueNo,pAd->LastRunningQueueNo));
+
+ ResetBulkOutSize=TRUE;
+ pAd->RunningQueueNoCount=0;
+ pAd->LastRunningQueueNo=RunningQueueNo;
+ }
+ else if (RunningQueueNo==pAd->LastRunningQueueNo)
+ {
+pAd->RunningQueueNoCount=0;
+ }
+ else if (RunningQueueNo<pAd->LastRunningQueueNo)
+ {
+ DBGPRINT(RT_DEBUG_INFO,("SoftwareFlowControl reset %d < %d \n",RunningQueueNo,pAd->LastRunningQueueNo));
+ pAd->RunningQueueNoCount++;
+ if (pAd->RunningQueueNoCount>=6)
+ {
+ ResetBulkOutSize=TRUE;
+ pAd->RunningQueueNoCount=0;
+ pAd->LastRunningQueueNo=RunningQueueNo;
+ }
+ }
+
+ if (ResetBulkOutSize==TRUE)
+ {
+ for (QueIdx=0;QueIdx<NUM_OF_TX_RING;QueIdx++)
+ {
+ HighWorkingAcCount=0;
+ for (i=0;i<NUM_OF_TX_RING;i++)
+ {
+ if (QueIdx==i)
+ continue;
+
+ if (pAd->BulkOutDataFlag[i]==TRUE && Priority[i]>Priority[QueIdx])
+ HighWorkingAcCount++;
+
+ }
+ pAd->BulkOutDataSizeLimit[QueIdx]=MaxBulkOutsSizeLimit[RunningQueueNo][HighWorkingAcCount];
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Reset bulkout size AC0(BE):%7d AC1(BK):%7d AC2(VI):%7d AC3(VO):%7d %d\n",pAd->BulkOutDataSizeLimit[0]
+ ,pAd->BulkOutDataSizeLimit[1]
+ ,pAd->BulkOutDataSizeLimit[2]
+ ,pAd->BulkOutDataSizeLimit[3]
+ ,RunningQueueNo));
+ }
+}
+#endif /* INF_AMAZON_SE */
+
+
+VOID RTUSBInitTxDesc(
+ IN PRTMP_ADAPTER pAd,
+ IN PTX_CONTEXT pTxContext,
+ IN UCHAR BulkOutPipeId,
+ IN usb_complete_t Func)
+{
+ PURB pUrb;
+ PUCHAR pSrc = NULL;
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+ RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
+
+ pUrb = pTxContext->pUrb;
+ ASSERT(pUrb);
+
+ /* Store BulkOut PipeId*/
+ pTxContext->BulkOutPipeId = BulkOutPipeId;
+
+ if (pTxContext->bAggregatible)
+ {
+ pSrc = &pTxContext->TransferBuffer->Aggregation[2];
+
+ /*Initialize a tx bulk urb*/
+ RTUSB_FILL_TX_BULK_URB(pUrb,
+ pObj->pUsb_Dev,
+ pChipCap->WMM0ACBulkOutAddr[BulkOutPipeId],
+ pSrc,
+ pTxContext->BulkOutSize,
+ Func,
+ pTxContext,
+ (pTxContext->data_dma + TX_BUFFER_NORMSIZE + 2));
+ }
+ else
+ {
+ pSrc = (PUCHAR) pTxContext->TransferBuffer->field.WirelessPacket;
+
+ /*Initialize a tx bulk urb*/
+ if (BulkOutPipeId == MGMTPIPEIDX) //Use EP9
+ {
+ RTUSB_FILL_TX_BULK_URB(pUrb,
+ pObj->pUsb_Dev,
+ pChipCap->CommandBulkOutAddr,
+ pSrc,
+ pTxContext->BulkOutSize,
+ Func,
+ pTxContext,
+ pTxContext->data_dma);
+
+ }
+ else
+ {
+ RTUSB_FILL_TX_BULK_URB(pUrb,
+ pObj->pUsb_Dev,
+ pChipCap->WMM0ACBulkOutAddr[BulkOutPipeId],
+ pSrc,
+ pTxContext->BulkOutSize,
+ Func,
+ pTxContext,
+ pTxContext->data_dma);
+ }
+ }
+}
+
+VOID RTUSBInitHTTxDesc(
+ IN PRTMP_ADAPTER pAd,
+ IN PHT_TX_CONTEXT pTxContext,
+ IN UCHAR BulkOutPipeId,
+ IN ULONG BulkOutSize,
+ IN usb_complete_t Func)
+{
+ PURB pUrb;
+ PUCHAR pSrc = NULL;
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+ RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
+
+ pUrb = pTxContext->pUrb;
+ ASSERT(pUrb);
+
+ /* Store BulkOut PipeId*/
+ pTxContext->BulkOutPipeId = BulkOutPipeId;
+
+ pSrc = &pTxContext->TransferBuffer->field.WirelessPacket[pTxContext->NextBulkOutPosition];
+
+ /*Initialize a tx bulk urb*/
+ if (BulkOutPipeId == 4) //Use EP9
+ {
+
+ RTUSB_FILL_HTTX_BULK_URB(pUrb,
+ pObj->pUsb_Dev,
+ pChipCap->WMM1ACBulkOutAddr,
+ pSrc,
+ BulkOutSize,
+ Func,
+ pTxContext,
+ (pTxContext->data_dma + pTxContext->NextBulkOutPosition));
+ }
+ else
+ {
+ RTUSB_FILL_HTTX_BULK_URB(pUrb,
+ pObj->pUsb_Dev,
+ pChipCap->WMM0ACBulkOutAddr[BulkOutPipeId],
+ pSrc,
+ BulkOutSize,
+ Func,
+ pTxContext,
+ (pTxContext->data_dma + pTxContext->NextBulkOutPosition));
+ }
+}
+
+VOID RTUSBInitRxDesc(
+ IN PRTMP_ADAPTER pAd,
+ IN PRX_CONTEXT pRxContext)
+{
+ PURB pUrb;
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+ ULONG RX_bulk_size;
+ RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
+
+ pUrb = pRxContext->pUrb;
+ ASSERT(pUrb);
+
+ if ( pAd->BulkInMaxPacketSize == 64)
+ RX_bulk_size = 4096;
+ else
+ RX_bulk_size = MAX_RXBULK_SIZE;
+
+
+ /*Initialize a rx bulk urb*/
+ RTUSB_FILL_RX_BULK_URB(pUrb,
+ pObj->pUsb_Dev,
+ pChipCap->DataBulkInAddr,
+ &(pRxContext->TransferBuffer[pAd->NextRxBulkInPosition]),
+ RX_bulk_size - (pAd->NextRxBulkInPosition),
+ RtmpUsbBulkRxComplete,
+ (void *)pRxContext,
+ (pRxContext->data_dma + pAd->NextRxBulkInPosition));
+}
+
+
+VOID RTUSBInitCmdRspEventDesc(
+ PRTMP_ADAPTER pAd,
+ PCMD_RSP_CONTEXT pCmdRspEventContext)
+{
+ PURB pUrb = pCmdRspEventContext->pUrb;
+ POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
+ RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
+
+ //printk("%s, Bulk In add = 0x%x\n", __FUNCTION__, pAd->BulkInEpAddr[1]);
+ /* Initialize command response event URB */
+ RTUSB_FILL_RX_BULK_URB(pUrb,
+ pObj->pUsb_Dev,
+ pChipCap->CommandRspBulkInAddr,
+ pCmdRspEventContext->CmdRspBuffer,
+ CMD_RSP_BULK_SIZE,
+ RTUSBBulkCmdRspEventComplete,
+ (void *)pCmdRspEventContext,
+ pCmdRspEventContext->data_dma);
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+
+#define BULK_OUT_LOCK(pLock, IrqFlags) \
+ if(1 /*!(in_interrupt() & 0xffff0000)*/) \
+ RTMP_IRQ_LOCK((pLock), IrqFlags);
+
+#define BULK_OUT_UNLOCK(pLock, IrqFlags) \
+ if(1 /*!(in_interrupt() & 0xffff0000)*/) \
+ RTMP_IRQ_UNLOCK((pLock), IrqFlags);
+
+
+VOID RTUSBBulkOutDataPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BulkOutPipeId,
+ IN UCHAR Index)
+{
+
+ PHT_TX_CONTEXT pHTTXContext;
+ PURB pUrb;
+ int ret = 0;
+ TXINFO_STRUC *pTxInfo, *pLastTxInfo = NULL;
+ TXWI_STRUC *pTxWI;
+ ULONG TmpBulkEndPos, ThisBulkSize;
+ unsigned long IrqFlags = 0, IrqFlags2 = 0;
+ PUCHAR pWirelessPkt, pAppendant;
+
+#ifdef USB_BULK_BUF_ALIGMENT
+ BOOLEAN bLasAlignmentsectiontRound = FALSE;
+#else
+ BOOLEAN bTxQLastRound = FALSE;
+ UCHAR allzero[4]= {0x0,0x0,0x0,0x0};
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+
+
+ BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+ if ((pAd->BulkOutPending[BulkOutPipeId] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX))
+ {
+ BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+ return;
+ }
+ pAd->BulkOutPending[BulkOutPipeId] = TRUE;
+
+ if (((!OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) &&
+ ( !OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)))
+ )
+ {
+ pAd->BulkOutPending[BulkOutPipeId] = FALSE;
+ BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+ return;
+ }
+ BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+
+
+ pHTTXContext = &(pAd->TxContext[BulkOutPipeId]);
+
+ BULK_OUT_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2);
+ if ((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition)
+#ifdef USB_BULK_BUF_ALIGMENT
+ || ((pHTTXContext->CurWriteRealPos > pHTTXContext->CurWritePosition) &&(pHTTXContext->NextBulkIdx == pHTTXContext->CurWriteIdx) )
+#else
+ || ((pHTTXContext->ENextBulkOutPosition-8) == pHTTXContext->CurWritePosition)
+#endif /* USB_BULK_BUF_ALIGMENT */
+ ) /* druing writing. */
+ {
+ BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2);
+
+ BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+ pAd->BulkOutPending[BulkOutPipeId] = FALSE;
+
+ /* Clear Data flag*/
+ RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId));
+ RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+
+ BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+ return;
+ }
+
+ /* Clear Data flag*/
+ RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_FRAG << BulkOutPipeId));
+ RTUSB_CLEAR_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << BulkOutPipeId));
+
+ /*DBGPRINT(RT_DEBUG_TRACE,("BulkOut-B:I=0x%lx, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", in_interrupt(), */
+ /* pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, */
+ /* pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad));*/
+ pHTTXContext->NextBulkOutPosition = pHTTXContext->ENextBulkOutPosition;
+ ThisBulkSize = 0;
+ TmpBulkEndPos = pHTTXContext->NextBulkOutPosition;
+ pWirelessPkt = &pHTTXContext->TransferBuffer->field.WirelessPacket[0];
+
+#ifndef USB_BULK_BUF_ALIGMENT
+ if ((pHTTXContext->bCopySavePad == TRUE))
+ {
+ if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero,4))
+ {
+ DBGPRINT_RAW(RT_DEBUG_ERROR,("e1, allzero : %x %x %x %x %x %x %x %x \n",
+ pHTTXContext->SavedPad[0], pHTTXContext->SavedPad[1], pHTTXContext->SavedPad[2],pHTTXContext->SavedPad[3]
+ ,pHTTXContext->SavedPad[4], pHTTXContext->SavedPad[5], pHTTXContext->SavedPad[6],pHTTXContext->SavedPad[7]));
+ }
+ NdisMoveMemory(&pWirelessPkt[TmpBulkEndPos], pHTTXContext->SavedPad, 8);
+ pHTTXContext->bCopySavePad = FALSE;
+ if (pAd->bForcePrintTX == TRUE)
+ DBGPRINT(RT_DEBUG_TRACE,("RTUSBBulkOutDataPacket --> COPY PAD. CurWrite = %ld, NextBulk = %ld. ENextBulk = %ld.\n", pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition));
+ }
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+
+ do
+ {
+ pTxInfo = (TXINFO_STRUC *)&pWirelessPkt[TmpBulkEndPos];
+ pTxWI = (TXWI_STRUC *)&pWirelessPkt[TmpBulkEndPos + TXINFO_SIZE];
+
+ if (pAd->bForcePrintTX == TRUE)
+ DBGPRINT(RT_DEBUG_TRACE, ("RTUSBBulkOutDataPacket AMPDU = %d.\n", pTxWI->TxWIAMPDU));
+
+ /* add by Iverson, limit BulkOut size to 4k to pass WMM b mode 2T1R test items*/
+ /*if ((ThisBulkSize != 0) && (pTxWI->AMPDU == 0))*/
+ if ((ThisBulkSize != 0) && (pTxWI->TxWIPHYMODE == MODE_CCK))
+ {
+#ifdef INF_AMAZON_SE
+ /*Iverson Add for AMAZON USB (RT2070 && RT3070) to pass WMM A2-T4 ~ A2-T10*/
+ if(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
+ {
+ /*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate*/
+ if(pTxWI->PacketId == 6)
+ {
+ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+ break;
+ }
+ else if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&pAd->BulkOutDataSizeLimit[BulkOutPipeId]) == pAd->BulkOutDataSizeLimit[BulkOutPipeId]))
+ {
+ /*printk("===Bulkout size limit :%d ===\n",MaxBulkOutSize);*/
+ /*DBGPRINT(RT_DEBUG_TRACE,("b mode BulkOutPipeId %d pAd->BulkOutDataSizeLimit[BulkOutPipeId] %d \n",BulkOutPipeId,pAd->BulkOutDataSizeLimit[BulkOutPipeId]));*/
+ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+ break;
+ }
+
+ }
+ else if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x1000) == 0x1000))
+ {
+ /* Limit BulkOut size to about 4k bytes.*/
+ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+ break;
+ }
+#endif /* INF_AMAZON_SE */
+#ifndef INF_AMAZON_SE
+#ifndef USB_BULK_BUF_ALIGMENT
+ if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x1000) == 0x1000))
+ {
+ /* Limit BulkOut size to about 4k bytes.*/
+ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+ break;
+ }
+#else
+ if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x6000) == 0x6000))
+ {
+ /* Limit BulkOut size to about 24k bytes.*/
+ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+
+ /*
+ when bulk size is > 6000, it mean that this is the lasttround at this alignmnet section.
+ */
+ bLasAlignmentsectiontRound = TRUE;
+ break;
+ }
+
+#endif /* USB_BULK_BUF_ALIGMENT */
+#endif /* INF_AMAZON_SE */
+#ifndef USB_BULK_BUF_ALIGMENT
+ else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize&0xfffff800) != 0) ) /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0))*/)
+ {
+ /* For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. */
+ /* For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04.*/
+ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+ break;
+ }
+#else
+ else if (((pAd->BulkOutMaxPacketSize < 512) && (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x6000) == 0x6000)) ))
+ {
+ /* Limit BulkOut size to about 24k bytes.*/
+ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+
+ /*
+ when bulk size is > 6000, it mean that this is the lasttround at this alignmnet section.
+ */
+ bLasAlignmentsectiontRound = TRUE;
+ break;
+ }
+
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+ }
+ /* end Iverson*/
+ else
+ {
+
+
+#ifdef RT65xx
+ if (((ThisBulkSize&0xfffe0000) != 0) || ((ThisBulkSize&0x10000) == 0x10000))
+#else
+ if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x6000) == 0x6000))
+#endif /* RT65xx */
+ { /* Limit BulkOut size to about 24k bytes.*/
+ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+#ifdef USB_BULK_BUF_ALIGMENT
+ /*
+ when bulk size is > 0x6000, it mean that this is the lasttround at this alignmnet section.
+ */
+ bLasAlignmentsectiontRound = TRUE;
+/* printk("data bulk out bLasAlignmentsectiontRound \n");*/
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+ break;
+ }
+#ifdef INF_AMAZON_SE
+ else if (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&pAd->BulkOutDataSizeLimit[BulkOutPipeId]) == pAd->BulkOutDataSizeLimit[BulkOutPipeId]))
+ {
+ /*printk("===Bulkout size limit :%d ===\n",ThisBulkSize);*/
+ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+ break;
+ }
+#endif /* INF_AMAZON_SE */
+#ifndef USB_BULK_BUF_ALIGMENT
+ else if (((pAd->BulkOutMaxPacketSize < 512) && ((ThisBulkSize&0xfffff800) != 0) ) /*|| ( (ThisBulkSize != 0) && (pTxWI->AMPDU == 0))*/)
+ { /* For USB 1.1 or peer which didn't support AMPDU, limit the BulkOut size. */
+ /* For performence in b/g mode, now just check for USB 1.1 and didn't care about the APMDU or not! 2008/06/04.*/
+ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+ break;
+ }
+#else
+ else if (((pAd->BulkOutMaxPacketSize < 512) && (((ThisBulkSize&0xffff8000) != 0) || ((ThisBulkSize&0x6000) == 0x6000)) ))
+ {
+ /* Limit BulkOut size to about 24k bytes.*/
+ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+
+ /*
+ when bulk size is > 6000, it mean that this is the lasttround at this alignmnet section.
+ */
+ bLasAlignmentsectiontRound = TRUE;
+ break;
+ }
+
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+
+
+ }
+
+ if (TmpBulkEndPos == pHTTXContext->CurWritePosition)
+ {
+ pHTTXContext->ENextBulkOutPosition = TmpBulkEndPos;
+ break;
+ }
+
+#ifndef CONFIG_MULTI_CHANNEL
+ if (pTxInfo->TxInfoQSEL != FIFO_EDCA)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s(): ====> pTxInfo->QueueSel(%d)!= FIFO_EDCA!!!!\n",
+ __FUNCTION__, pTxInfo->TxInfoQSEL));
+ DBGPRINT(RT_DEBUG_ERROR, ("\tCWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n",
+ pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition,
+ pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad));
+ hex_dump("Wrong QSel Pkt:", (PUCHAR)&pWirelessPkt[TmpBulkEndPos], (pHTTXContext->CurWritePosition - pHTTXContext->NextBulkOutPosition));
+ }
+#endif /* !CONFIG_MULTI_CHANNEL */
+
+ if (pTxInfo->TxInfoPktLen <= 8)
+ {
+ BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2);
+ DBGPRINT(RT_DEBUG_ERROR /*RT_DEBUG_TRACE*/,("e2, TxInfoPktLen==0, Size=%ld, bCSPad=%d, CWPos=%ld, NBPos=%ld, CWRPos=%ld!\n",
+ pHTTXContext->BulkOutSize, pHTTXContext->bCopySavePad, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->CurWriteRealPos));
+ {
+ DBGPRINT_RAW(RT_DEBUG_ERROR /*RT_DEBUG_TRACE*/,("%x %x %x %x %x %x %x %x \n",
+ pHTTXContext->SavedPad[0], pHTTXContext->SavedPad[1], pHTTXContext->SavedPad[2],pHTTXContext->SavedPad[3]
+ ,pHTTXContext->SavedPad[4], pHTTXContext->SavedPad[5], pHTTXContext->SavedPad[6],pHTTXContext->SavedPad[7]));
+ }
+ pAd->bForcePrintTX = TRUE;
+ BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+ pAd->BulkOutPending[BulkOutPipeId] = FALSE;
+ BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+ /*DBGPRINT(RT_DEBUG_LOUD,("Out:pTxInfo->TxInfoPktLen=%d!\n", pTxInfo->TxInfoPktLen));*/
+ return;
+ }
+
+ /* Increase Total transmit byte counter*/
+ pAd->RalinkCounters.OneSecTransmittedByteCount += pTxWI->TxWIMPDUByteCnt;
+ pAd->RalinkCounters.TransmittedByteCount += pTxWI->TxWIMPDUByteCnt;
+
+ pLastTxInfo = pTxInfo;
+
+ /* Make sure we use EDCA QUEUE. */
+#ifndef CONFIG_MULTI_CHANNEL
+ pTxInfo->TxInfoQSEL = FIFO_EDCA;
+#endif /* !CONFIG_MULTI_CHANNEL */
+ ThisBulkSize += (pTxInfo->TxInfoPktLen+4);
+ TmpBulkEndPos += (pTxInfo->TxInfoPktLen+4);
+
+ if (TmpBulkEndPos != pHTTXContext->CurWritePosition)
+ pTxInfo->TxInfoUDMANextVld = 1;
+
+#ifdef USB_BULK_BUF_ALIGMENT
+/*
+ this is for frag packet , because it will finish this section
+ when ((((pHTTXContext->CurWritePosition + 3906)& 0x00007fff) & 0xffff6000) == 0x00006000)
+*/
+ if (pTxInfo->bFragLasAlignmentsectiontRound == 1)
+ {
+ bLasAlignmentsectiontRound = TRUE;
+ break;
+ }
+#else
+ if (pTxInfo->TxInfoSwLstRnd == 1)
+ {
+ if (pHTTXContext->CurWritePosition == 8)
+ pTxInfo->TxInfoUDMANextVld = 0;
+ pTxInfo->TxInfoSwLstRnd = 0;
+
+ bTxQLastRound = TRUE;
+ pHTTXContext->ENextBulkOutPosition = 8;
+
+ #ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxInfo, TYPE_TXINFO);
+ RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI);
+ #endif /* RT_BIG_ENDIAN */
+
+ break;
+ }
+#endif /* USB_BULK_BUF_ALIGMENT */
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxInfo, TYPE_TXINFO);
+ RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI);
+#endif /* RT_BIG_ENDIAN */
+
+ }while (TRUE);
+
+ /* adjust the pTxInfo->TxInfoUDMANextVld value of last pTxInfo.*/
+ if (pLastTxInfo)
+ {
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pLastTxInfo, TYPE_TXINFO);
+#endif /* RT_BIG_ENDIAN */
+ pLastTxInfo->TxInfoUDMANextVld = 0;
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pLastTxInfo, TYPE_TXINFO);
+#endif /* RT_BIG_ENDIAN */
+ }
+
+ /*
+ We need to copy SavedPad when following condition matched!
+ 1. Not the last round of the TxQueue and
+ 2. any match of following cases:
+ (1). The End Position of this bulk out is reach to the Currenct Write position and
+ the TxInfo and related header already write to the CurWritePosition.
+ =>(ENextBulkOutPosition == CurWritePosition) && (CurWriteRealPos > CurWritePosition)
+
+ (2). The EndPosition of the bulk out is not reach to the Current Write Position.
+ =>(ENextBulkOutPosition != CurWritePosition)
+ */
+#ifndef USB_BULK_BUF_ALIGMENT
+ if ((bTxQLastRound == FALSE) &&
+ (((pHTTXContext->ENextBulkOutPosition == pHTTXContext->CurWritePosition) && (pHTTXContext->CurWriteRealPos > pHTTXContext->CurWritePosition)) ||
+ (pHTTXContext->ENextBulkOutPosition != pHTTXContext->CurWritePosition))
+ )
+ {
+ NdisMoveMemory(pHTTXContext->SavedPad, &pWirelessPkt[pHTTXContext->ENextBulkOutPosition], 8);
+ pHTTXContext->bCopySavePad = TRUE;
+ if (RTMPEqualMemory(pHTTXContext->SavedPad, allzero,4))
+ {
+ PUCHAR pBuf = &pHTTXContext->SavedPad[0];
+ DBGPRINT_RAW(RT_DEBUG_ERROR,("WARNING-Zero-3:%02x%02x%02x%02x%02x%02x%02x%02x,CWPos=%ld, CWRPos=%ld, bCW=%d, NBPos=%ld, TBPos=%ld, TBSize=%ld\n",
+ pBuf[0], pBuf[1], pBuf[2],pBuf[3],pBuf[4], pBuf[5], pBuf[6],pBuf[7], pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos,
+ pHTTXContext->bCurWriting, pHTTXContext->NextBulkOutPosition, TmpBulkEndPos, ThisBulkSize));
+
+ pBuf = &pWirelessPkt[pHTTXContext->CurWritePosition];
+ DBGPRINT_RAW(RT_DEBUG_ERROR,("\tCWPos=%02x%02x%02x%02x%02x%02x%02x%02x\n", pBuf[0], pBuf[1], pBuf[2],pBuf[3],pBuf[4], pBuf[5], pBuf[6],pBuf[7]));
+ }
+ /*DBGPRINT(RT_DEBUG_LOUD,("ENPos==CWPos=%ld, CWRPos=%ld, bCSPad=%d!\n", pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->bCopySavePad));*/
+ }
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+ if (pAd->bForcePrintTX == TRUE)
+ DBGPRINT(RT_DEBUG_TRACE,("BulkOut-A:Size=%ld, CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d!\n", ThisBulkSize, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad));
+ /*DBGPRINT(RT_DEBUG_LOUD,("BulkOut-A:Size=%ld, CWPos=%ld, CWRPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, bLRound=%d!\n", ThisBulkSize, pHTTXContext->CurWritePosition, pHTTXContext->CurWriteRealPos, pHTTXContext->NextBulkOutPosition, pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, bTxQLastRound));*/
+
+ /* USB DMA engine requires to pad extra 4 bytes. This pad doesn't count into real bulkoutsize.*/
+ pAppendant = &pWirelessPkt[TmpBulkEndPos];
+ NdisZeroMemory(pAppendant, 8);
+ ThisBulkSize += 4;
+ pHTTXContext->LastOne = TRUE;
+
+ pHTTXContext->BulkOutSize = ThisBulkSize;
+#ifdef USB_BULK_BUF_ALIGMENT
+ /*
+ if it is the last alignment section round,that we just need to add nextbulkindex,
+ otherwise we both need to add nextbulkindex and CurWriteIdx
+ (because when alignment section round happened, the CurWriteIdx is added at function writing resource.)
+ */
+ if(bLasAlignmentsectiontRound == TRUE)
+ {
+ pHTTXContext->ENextBulkOutPosition = ((CUR_WRITE_IDX_INC(pHTTXContext->NextBulkIdx, BUF_ALIGMENT_RINGSIZE)) * 0x8000);
+ }
+ else
+ {
+ pHTTXContext->ENextBulkOutPosition = ((CUR_WRITE_IDX_INC(pHTTXContext->NextBulkIdx, BUF_ALIGMENT_RINGSIZE)) * 0x8000);
+ pHTTXContext->CurWritePosition = ((CUR_WRITE_IDX_INC(pHTTXContext->CurWriteIdx, BUF_ALIGMENT_RINGSIZE)) * 0x8000);
+ }
+
+#endif /* USB_BULK_BUF_ALIGMENT */
+
+
+ pAd->watchDogTxPendingCnt[BulkOutPipeId] = 1;
+ BULK_OUT_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags2);
+
+ /* Init Tx context descriptor*/
+ RTUSBInitHTTxDesc(pAd, pHTTXContext, BulkOutPipeId, ThisBulkSize, (usb_complete_t)RtmpUsbBulkOutDataPacketComplete);
+
+ pUrb = pHTTXContext->pUrb;
+ if((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutDataPacket: Submit Tx URB failed %d\n", ret));
+
+ BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+ pAd->BulkOutPending[BulkOutPipeId] = FALSE;
+ pAd->watchDogTxPendingCnt[BulkOutPipeId] = 0;
+ BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+
+ return;
+ }
+
+ BULK_OUT_LOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+ pHTTXContext->IRPPending = TRUE;
+ BULK_OUT_UNLOCK(&pAd->BulkOutLock[BulkOutPipeId], IrqFlags);
+ pAd->BulkOutReq++;
+
+}
+
+
+USBHST_STATUS RTUSBBulkOutDataPacketComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs)
+{
+ PHT_TX_CONTEXT pHTTXContext;
+ PRTMP_ADAPTER pAd;
+ POS_COOKIE pObj;
+ UCHAR BulkOutPipeId;
+
+
+ pHTTXContext = (PHT_TX_CONTEXT)RTMP_OS_USB_CONTEXT_GET(pURB);
+ pAd = pHTTXContext->pAd;
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ /* Store BulkOut PipeId*/
+ BulkOutPipeId = pHTTXContext->BulkOutPipeId;
+ pAd->BulkOutDataOneSecCount++;
+
+ switch (BulkOutPipeId)
+ {
+ case EDCA_AC0_PIPE:
+#ifdef RALINK_ATE
+ if (!ATE_ON(pAd))
+ {
+#endif /* RALINK_ATE */
+ RTMP_NET_TASK_DATA_ASSIGN(&pObj->ac0_dma_done_task, (unsigned long)pURB);
+ RTMP_OS_TASKLET_SCHE(&pObj->ac0_dma_done_task);
+#ifdef RALINK_ATE
+ }
+ else
+ {
+ RTMP_NET_TASK_DATA_ASSIGN(&pObj->ate_ac0_dma_done_task, (unsigned long)pURB);
+ RTMP_OS_TASKLET_SCHE(&pObj->ate_ac0_dma_done_task);
+ }
+#endif /* RALINK_ATE */
+
+ break;
+ case EDCA_AC1_PIPE:
+ RTMP_NET_TASK_DATA_ASSIGN(&pObj->ac1_dma_done_task, (unsigned long)pURB);
+ RTMP_OS_TASKLET_SCHE(&pObj->ac1_dma_done_task);
+ break;
+ case EDCA_AC2_PIPE:
+ RTMP_NET_TASK_DATA_ASSIGN(&pObj->ac2_dma_done_task, (unsigned long)pURB);
+ RTMP_OS_TASKLET_SCHE(&pObj->ac2_dma_done_task);
+ break;
+ case EDCA_AC3_PIPE:
+ RTMP_NET_TASK_DATA_ASSIGN(&pObj->ac3_dma_done_task, (unsigned long)pURB);
+ RTMP_OS_TASKLET_SCHE(&pObj->ac3_dma_done_task);
+ break;
+ case HCCA_PIPE:
+ RTMP_NET_TASK_DATA_ASSIGN(&pObj->hcca_dma_done_task, (unsigned long)pURB);
+ RTMP_OS_TASKLET_SCHE(&pObj->hcca_dma_done_task);
+ break;
+ }
+
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note: NULL frame use BulkOutPipeId = 0
+
+ ========================================================================
+*/
+VOID RTUSBBulkOutNullFrame(
+ IN PRTMP_ADAPTER pAd)
+{
+ PTX_CONTEXT pNullContext = &(pAd->NullContext[0]);
+ PURB pUrb;
+ int ret = 0;
+ unsigned long IrqFlags;
+
+ RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags);
+ if ((pAd->BulkOutPending[0] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX))
+ {
+ RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+ return;
+ }
+ pAd->BulkOutPending[0] = TRUE;
+ pAd->watchDogTxPendingCnt[0] = 1;
+ pNullContext->IRPPending = TRUE;
+ RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+
+ /* Increase Total transmit byte counter*/
+ pAd->RalinkCounters.TransmittedByteCount += pNullContext->BulkOutSize;
+
+
+ /* Clear Null frame bulk flag*/
+ RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL);
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pNullContext->TransferBuffer, TYPE_TXINFO);
+#endif /* RT_BIG_ENDIAN */
+
+ /* Init Tx context descriptor*/
+ RTUSBInitTxDesc(pAd, pNullContext, 0, (usb_complete_t)RtmpUsbBulkOutNullFrameComplete);
+
+ pUrb = pNullContext->pUrb;
+ if((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+ {
+ RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags);
+ pAd->BulkOutPending[0] = FALSE;
+ pAd->watchDogTxPendingCnt[0] = 0;
+ pNullContext->IRPPending = FALSE;
+ RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+
+ DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutNullFrame: Submit Tx URB failed %d\n", ret));
+ return;
+ }
+
+}
+
+/* NULL frame use BulkOutPipeId = 0*/
+USBHST_STATUS RTUSBBulkOutNullFrameComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs)
+{
+ PRTMP_ADAPTER pAd;
+ PTX_CONTEXT pNullContext;
+ NTSTATUS Status;
+ POS_COOKIE pObj;
+
+
+ pNullContext = (PTX_CONTEXT)RTMP_OS_USB_CONTEXT_GET(pURB);
+ pAd = pNullContext->pAd;
+ Status = RTMP_OS_USB_STATUS_GET(pURB); /*->rtusb_urb_status;*/
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+ RTMP_NET_TASK_DATA_ASSIGN(&pObj->null_frame_complete_task, (unsigned long)pURB);
+ RTMP_OS_TASKLET_SCHE(&pObj->null_frame_complete_task);
+
+}
+
+
+#ifdef CONFIG_MULTI_CHANNEL
+
+USBHST_STATUS RTUSBBulkOutHCCANullFrameComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs)
+{
+ PRTMP_ADAPTER pAd;
+ PTX_CONTEXT pNullContext;
+ NTSTATUS Status;
+ POS_COOKIE pObj;
+
+ pNullContext = (PTX_CONTEXT)RTMP_OS_USB_CONTEXT_GET(pURB);
+ pAd = pNullContext->pAd;
+ Status = RTMP_OS_USB_STATUS_GET(pURB); /*->rtusb_urb_status;*/
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+ RTMP_NET_TASK_DATA_ASSIGN(&pObj->hcca_null_frame_complete_task, (unsigned long)pURB);
+ RTMP_OS_TASKLET_SCHE(&pObj->hcca_null_frame_complete_task);
+
+}
+
+#endif /* CONFIG_MULTI_CHANNEL */
+
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note: MLME use BulkOutPipeId = 0
+
+ ========================================================================
+*/
+VOID RTUSBBulkOutMLMEPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index)
+{
+ PTX_CONTEXT pMLMEContext;
+ PURB pUrb;
+ int ret = 0;
+ unsigned long IrqFlags;
+
+ pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa;
+ pUrb = pMLMEContext->pUrb;
+
+ if ((pAd->MgmtRing.TxSwFreeIdx >= MGMT_RING_SIZE) ||
+ (pMLMEContext->InUse == FALSE) ||
+ (pMLMEContext->bWaitingBulkOut == FALSE))
+ {
+
+
+ /* Clear MLME bulk flag*/
+ RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
+
+ return;
+ }
+
+
+ RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+ if ((pAd->BulkOutPending[MGMTPIPEIDX] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX))
+ {
+ RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+ return;
+ }
+
+ pAd->BulkOutPending[MGMTPIPEIDX] = TRUE;
+ pAd->watchDogTxPendingCnt[MGMTPIPEIDX] = 1;
+ pMLMEContext->IRPPending = TRUE;
+ pMLMEContext->bWaitingBulkOut = FALSE;
+ RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+
+ /* Increase Total transmit byte counter*/
+ pAd->RalinkCounters.TransmittedByteCount += pMLMEContext->BulkOutSize;
+
+ /* Clear MLME bulk flag*/
+ RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pMLMEContext->TransferBuffer, TYPE_TXINFO);
+#endif /* RT_BIG_ENDIAN */
+
+ /* Init Tx context descriptor*/
+ RTUSBInitTxDesc(pAd, pMLMEContext, MGMTPIPEIDX, (usb_complete_t)RtmpUsbBulkOutMLMEPacketComplete);
+
+ RTUSB_URB_DMA_MAPPING(pUrb);
+
+ pUrb = pMLMEContext->pUrb;
+ if((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutMLMEPacket: Submit MLME URB failed %d\n", ret));
+ RTMP_IRQ_LOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+ pAd->BulkOutPending[MGMTPIPEIDX] = FALSE;
+ pAd->watchDogTxPendingCnt[MGMTPIPEIDX] = 0;
+ pMLMEContext->IRPPending = FALSE;
+ pMLMEContext->bWaitingBulkOut = TRUE;
+ RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[MGMTPIPEIDX], IrqFlags);
+
+ return;
+ }
+}
+
+
+USBHST_STATUS RTUSBBulkOutMLMEPacketComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs)
+{
+ PTX_CONTEXT pMLMEContext;
+ PRTMP_ADAPTER pAd;
+ NTSTATUS Status;
+ POS_COOKIE pObj;
+ int index;
+
+ pMLMEContext = (PTX_CONTEXT)RTMP_OS_USB_CONTEXT_GET(pURB);
+ pAd = pMLMEContext->pAd;
+ pObj = (POS_COOKIE)pAd->OS_Cookie;
+ Status = RTMP_OS_USB_STATUS_GET(pURB);
+ index = pMLMEContext->SelfIdx;
+
+ RTMP_NET_TASK_DATA_ASSIGN(&pObj->mgmt_dma_done_task, (unsigned long)pURB);
+ RTMP_OS_TASKLET_SCHE(&pObj->mgmt_dma_done_task);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note: PsPoll use BulkOutPipeId = 0
+
+ ========================================================================
+*/
+VOID RTUSBBulkOutPsPoll(
+ IN PRTMP_ADAPTER pAd)
+{
+ PTX_CONTEXT pPsPollContext = &(pAd->PsPollContext);
+ PURB pUrb;
+ int ret = 0;
+ unsigned long IrqFlags;
+
+ RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags);
+ if ((pAd->BulkOutPending[0] == TRUE) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_TX))
+ {
+ RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+ return;
+ }
+ pAd->BulkOutPending[0] = TRUE;
+ pAd->watchDogTxPendingCnt[0] = 1;
+ pPsPollContext->IRPPending = TRUE;
+ RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+
+
+ /* Clear PS-Poll bulk flag*/
+ RTUSB_CLEAR_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL);
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pPsPollContext->TransferBuffer, TYPE_TXINFO);
+#endif /* RT_BIG_ENDIAN */
+
+ /* Init Tx context descriptor*/
+#ifdef CONFIG_MULTI_CHANNEL
+ if (pAd->Multi_Channel_Enable == TRUE)
+ RTUSBInitTxDesc(pAd, pPsPollContext, 0, (usb_complete_t)RtmpUsbBulkOutPsPollComplete);
+ else
+#endif /* CONFIG_MULTI_CHANNEL */
+ RTUSBInitTxDesc(pAd, pPsPollContext, MGMTPIPEIDX, (usb_complete_t)RtmpUsbBulkOutPsPollComplete);
+
+ pUrb = pPsPollContext->pUrb;
+ if((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+ {
+ RTMP_IRQ_LOCK(&pAd->BulkOutLock[0], IrqFlags);
+ pAd->BulkOutPending[0] = FALSE;
+ pAd->watchDogTxPendingCnt[0] = 0;
+ pPsPollContext->IRPPending = FALSE;
+ RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[0], IrqFlags);
+
+ DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkOutPsPoll: Submit Tx URB failed %d\n", ret));
+ return;
+ }
+
+}
+
+/* PS-Poll frame use BulkOutPipeId = 0*/
+USBHST_STATUS RTUSBBulkOutPsPollComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs)
+{
+ PRTMP_ADAPTER pAd;
+ PTX_CONTEXT pPsPollContext;
+ NTSTATUS Status;
+ POS_COOKIE pObj;
+
+
+ pPsPollContext= (PTX_CONTEXT)RTMP_OS_USB_CONTEXT_GET(pURB);
+ pAd = pPsPollContext->pAd;
+ Status = RTMP_OS_USB_STATUS_GET(pURB);
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+ RTMP_NET_TASK_DATA_ASSIGN(&pObj->pspoll_frame_complete_task, (unsigned long)pURB);
+ RTMP_OS_TASKLET_SCHE(&pObj->pspoll_frame_complete_task);
+
+}
+
+
+VOID DoBulkIn(IN RTMP_ADAPTER *pAd)
+{
+ PRX_CONTEXT pRxContext;
+ PURB pUrb;
+ int ret = 0;
+ unsigned long IrqFlags;
+
+ RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+ pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]);
+ if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) || (pRxContext->InUse == TRUE))
+ {
+ RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+ return;
+ }
+ pRxContext->InUse = TRUE;
+ pRxContext->IRPPending = TRUE;
+ pAd->PendingRx++;
+ pAd->BulkInReq++;
+ RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+
+ /* Init Rx context descriptor*/
+ NdisZeroMemory(pRxContext->TransferBuffer, pRxContext->BulkInOffset);
+ RTUSBInitRxDesc(pAd, pRxContext);
+
+ pUrb = pRxContext->pUrb;
+ if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+ { /* fail*/
+
+ RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+ pRxContext->InUse = FALSE;
+ pRxContext->IRPPending = FALSE;
+ pAd->PendingRx--;
+ pAd->BulkInReq--;
+ RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+ DBGPRINT(RT_DEBUG_ERROR, ("RTUSBBulkReceive: Submit Rx URB failed %d\n", ret));
+ }
+ else
+ { /* success*/
+ ASSERT((pRxContext->InUse == pRxContext->IRPPending));
+ }
+}
+
+
+VOID BulkInCmdRspEvent(RTMP_ADAPTER *pAd)
+{
+ PCMD_RSP_CONTEXT pCmdRspEventContext = &pAd->CmdRspEventContext;
+ PURB pURB;
+ int ret = 0;
+ unsigned long IrqFlags;
+
+ RTMP_IRQ_LOCK(&pAd->CmdRspLock, IrqFlags);
+ if ( (pCmdRspEventContext->Readable == TRUE) || (pCmdRspEventContext->InUse == TRUE))
+ {
+ RTMP_IRQ_UNLOCK(&pAd->CmdRspLock, IrqFlags);
+ return;
+ }
+ pCmdRspEventContext->InUse = TRUE;
+ pCmdRspEventContext->IRPPending = TRUE;
+ RTMP_IRQ_UNLOCK(&pAd->CmdRspLock, IrqFlags);
+
+ RTUSBInitCmdRspEventDesc(pAd, pCmdRspEventContext);
+ pURB = pCmdRspEventContext->pUrb;
+
+ if ((ret = RTUSB_SUBMIT_URB(pURB)) != 0)
+ {
+ RTMP_IRQ_LOCK(&pAd->CmdRspLock, IrqFlags);
+ pCmdRspEventContext->InUse = FALSE;
+ pCmdRspEventContext->IRPPending = FALSE;
+ RTMP_IRQ_UNLOCK(&pAd->CmdRspLock, IrqFlags);
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_INFO, ("%s success\n", __FUNCTION__));
+ }
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ USB_RxPacket initializes a URB and uses the Rx IRP to submit it
+ to USB. It checks if an Rx Descriptor is available and passes the
+ the coresponding buffer to be filled. If no descriptor is available
+ fails the request. When setting the completion routine we pass our
+ Adapter Object as Context.
+
+ Arguments:
+
+ Return Value:
+ TRUE found matched tuple cache
+ FALSE no matched found
+
+ Note:
+
+ ========================================================================
+*/
+#define fRTMP_ADAPTER_NEED_STOP_RX \
+ (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \
+ fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_RESET_IN_PROGRESS | \
+ fRTMP_ADAPTER_REMOVE_IN_PROGRESS | fRTMP_ADAPTER_BULKIN_RESET)
+
+#define fRTMP_ADAPTER_NEED_STOP_HANDLE_RX \
+ (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \
+ fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_RESET_IN_PROGRESS | \
+ fRTMP_ADAPTER_REMOVE_IN_PROGRESS)
+
+VOID RTUSBBulkReceive(
+ IN PRTMP_ADAPTER pAd)
+{
+ PRX_CONTEXT pRxContext;
+ unsigned long IrqFlags;
+
+
+ /* sanity check */
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_HANDLE_RX)
+ && !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_POLL_IDLE))
+ return;
+
+ while(1)
+ {
+ RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+ pRxContext = &(pAd->RxContext[pAd->NextRxBulkInReadIndex]);
+ if (((pRxContext->InUse == FALSE) && (pRxContext->Readable == TRUE)) &&
+ (pRxContext->bRxHandling == FALSE))
+ {
+ pRxContext->bRxHandling = TRUE;
+ RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+
+ /* read RxContext, Since not */
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ APRxDoneInterruptHandle(pAd);
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Finish to handle this bulkIn buffer.*/
+ RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+ pRxContext->BulkInOffset = 0;
+ pRxContext->Readable = FALSE;
+ pRxContext->bRxHandling = FALSE;
+ pAd->ReadPosition = 0;
+ pAd->TransferBufferLength = 0;
+ INC_RING_INDEX(pAd->NextRxBulkInReadIndex, RX_RING_SIZE);
+ RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+
+ }
+ else
+ {
+ RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+ break;
+ }
+ }
+
+ if (!((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NEED_STOP_RX)
+ && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_POLL_IDLE)))))
+ {
+
+ DoBulkIn(pAd);
+ }
+
+}
+
+#ifdef RLT_MAC
+VOID RTUSBBulkCmdRspEventReceive(PRTMP_ADAPTER pAd)
+{
+ unsigned long IrqFlags;
+ PCMD_RSP_CONTEXT pCmdRspEventContext = &pAd->CmdRspEventContext;
+
+ RTMP_IRQ_LOCK(&pAd->CmdRspLock, IrqFlags);
+ if ((pCmdRspEventContext->InUse) == FALSE && (pCmdRspEventContext->Readable == TRUE))
+ {
+ RTMP_IRQ_UNLOCK(&pAd->CmdRspLock, IrqFlags);
+ CmdRspEventHandle(pAd);
+
+
+ RTMP_IRQ_LOCK(&pAd->CmdRspLock, IrqFlags);
+ pCmdRspEventContext->Readable = FALSE;
+ RTMP_IRQ_UNLOCK(&pAd->CmdRspLock, IrqFlags);
+ }
+ else
+ {
+ RTMP_IRQ_UNLOCK(&pAd->CmdRspLock, IrqFlags);
+ }
+
+ if ( !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF) )
+ BulkInCmdRspEvent(pAd);
+}
+#endif /* RTL_MAC */
+
+/*
+ ========================================================================
+
+ Routine Description:
+ This routine process Rx Irp and call rx complete function.
+
+ Arguments:
+ DeviceObject Pointer to the device object for next lower
+ device. DeviceObject passed in here belongs to
+ the next lower driver in the stack because we
+ were invoked via IoCallDriver in USB_RxPacket
+ AND it is not OUR device object
+ Irp Ptr to completed IRP
+ Context Ptr to our Adapter object (context specified
+ in IoSetCompletionRoutine
+
+ Return Value:
+ Always returns STATUS_MORE_PROCESSING_REQUIRED
+
+ Note:
+ Always returns STATUS_MORE_PROCESSING_REQUIRED
+ ========================================================================
+*/
+USBHST_STATUS RTUSBBulkRxComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs)
+{
+ /* use a receive tasklet to handle received packets;*/
+ /* or sometimes hardware IRQ will be disabled here, so we can not*/
+ /* use spin_lock_bh()/spin_unlock_bh() after IRQ is disabled. :<*/
+ PRX_CONTEXT pRxContext;
+ PRTMP_ADAPTER pAd;
+ POS_COOKIE pObj;
+
+ pRxContext = (PRX_CONTEXT)RTMP_OS_USB_CONTEXT_GET(pURB);
+ pAd = pRxContext->pAd;
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ RTMP_NET_TASK_DATA_ASSIGN(&pObj->rx_done_task, (unsigned long)pURB);
+ RTMP_OS_TASKLET_SCHE(&pObj->rx_done_task);
+
+}
+
+//void RTUSBBulkCmdRspEventComplete(purbb_t pURB)
+USBHST_STATUS RTUSBBulkCmdRspEventComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs)
+{
+
+ PRX_CONTEXT pCmdRspEventContext;
+ PRTMP_ADAPTER pAd;
+ POS_COOKIE pObj;
+
+ pCmdRspEventContext = (PRX_CONTEXT)RTMP_OS_USB_CONTEXT_GET(pURB);
+ pAd = pCmdRspEventContext->pAd;
+ pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+ RTMP_NET_TASK_DATA_ASSIGN(&pObj->cmd_rsp_event_task, (unsigned long)pURB);
+ RTMP_OS_TASKLET_SCHE(&pObj->cmd_rsp_event_task);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTUSBKickBulkOut(
+ IN PRTMP_ADAPTER pAd)
+{
+ /* BulkIn Reset will reset whole USB PHY. So we need to make sure fRTMP_ADAPTER_BULKIN_RESET not flaged.*/
+ if (!RTMP_TEST_FLAG(pAd ,fRTMP_ADAPTER_NEED_STOP_TX)
+#ifdef RALINK_ATE
+ && !(ATE_ON(pAd))
+#endif /* RALINK_ATE */
+ )
+ {
+
+ /* 2. PS-Poll frame is next*/
+ if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_PSPOLL))
+ {
+ RTUSBBulkOutPsPoll(pAd);
+ }
+
+ /* 5. Mlme frame is next*/
+ else if ((RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME)) ||
+ (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE))
+ {
+ RTUSBBulkOutMLMEPacket(pAd, pAd->MgmtRing.TxDmaIdx);
+ }
+
+ /* 6. Data frame normal is next*/
+ if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL))
+ {
+ if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+ (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ ))
+ {
+ RTUSBBulkOutDataPacket(pAd, EDCA_AC0_PIPE, pAd->NextBulkOutIndex[EDCA_AC0_PIPE]);
+ }
+ }
+ if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_2))
+ {
+ if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+ (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ ))
+ {
+ RTUSBBulkOutDataPacket(pAd, EDCA_AC1_PIPE, pAd->NextBulkOutIndex[EDCA_AC1_PIPE]);
+ }
+ }
+ if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_3))
+ {
+ if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+ (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ ))
+ {
+ RTUSBBulkOutDataPacket(pAd, EDCA_AC2_PIPE, pAd->NextBulkOutIndex[EDCA_AC2_PIPE]);
+ }
+ }
+ if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NORMAL_4))
+ {
+ if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+ (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ ))
+ {
+ RTUSBBulkOutDataPacket(pAd, EDCA_AC3_PIPE, pAd->NextBulkOutIndex[EDCA_AC3_PIPE]);
+ }
+ }
+#ifdef CONFIG_MULTI_CHANNEL
+ if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_HCCA))
+ {
+ if (((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
+ (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ || P2P_GO_ON(pAd) || P2P_CLI_ON(pAd)
+ ))
+ {
+ RTUSBBulkOutDataPacket(pAd, HCCA_PIPE, pAd->NextBulkOutIndex[HCCA_PIPE]);
+ }
+ }
+#endif /*CONFIG_MULTI_CHANNEL*/
+
+ /* 7. Null frame is the last*/
+ else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL))
+ {
+#ifdef CONFIG_MULTI_CHANNEL
+ if (INFRA_ON(pAd) && (pAd->CommonCfg.Channel == pAd->LatchRfRegs.Channel ||
+ pAd->CommonCfg.CentralChannel== pAd->LatchRfRegs.Channel ))
+#else
+ if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+#endif /* CONFIG_MULTI_CHANNEL */
+ {
+ RTUSBBulkOutNullFrame(pAd);
+ }
+ }
+#ifdef CONFIG_MULTI_CHANNEL
+ else if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_NULL_HCCA))
+ {
+ if (INFRA_ON(pAd) && (pAd->CommonCfg.Channel == pAd->LatchRfRegs.Channel ||
+ pAd->CommonCfg.CentralChannel== pAd->LatchRfRegs.Channel ))
+ RTUSBBulkOutNullFrame(pAd);
+ }
+#endif /*CONFIG_MULTI_CHANNEL*/
+
+
+
+ /* 8. No data avaliable*/
+ else
+ {
+
+ }
+ }
+#ifdef RALINK_ATE
+ else if((ATE_ON(pAd)) &&
+ !RTMP_TEST_FLAG(pAd , fRTMP_ADAPTER_NEED_STOP_TX))
+ {
+ if (RTUSB_TEST_BULK_FLAG(pAd, fRTUSB_BULK_OUT_DATA_ATE))
+ {
+ ATE_RTUSBBulkOutDataPacket(pAd, EDCA_AC0_PIPE);
+ }
+ }
+#endif /* RALINK_ATE */
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Call from Reset action after BulkOut failed.
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTUSBCleanUpDataBulkOutQueue(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR Idx;
+ PHT_TX_CONTEXT pTxContext;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--->CleanUpDataBulkOutQueue\n"));
+
+ for (Idx = 0; Idx < 4; Idx++)
+ {
+ pTxContext = &pAd->TxContext[Idx];
+
+ pTxContext->CurWritePosition = pTxContext->NextBulkOutPosition;
+ pTxContext->LastOne = FALSE;
+ NdisAcquireSpinLock(&pAd->BulkOutLock[Idx]);
+ pAd->BulkOutPending[Idx] = FALSE;
+ NdisReleaseSpinLock(&pAd->BulkOutLock[Idx]);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<---CleanUpDataBulkOutQueue\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTUSBCleanUpMLMEBulkOutQueue(
+ IN PRTMP_ADAPTER pAd)
+{
+ DBGPRINT(RT_DEBUG_TRACE, ("--->CleanUpMLMEBulkOutQueue\n"));
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<---CleanUpMLMEBulkOutQueue\n"));
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTUSBCancelPendingIRPs(
+ IN PRTMP_ADAPTER pAd)
+{
+ RTUSBCancelPendingBulkInIRP(pAd);
+ RTUSBCancelPendingBulkOutIRP(pAd);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTUSBCancelPendingBulkInIRP(
+ IN PRTMP_ADAPTER pAd)
+{
+ PRX_CONTEXT pRxContext;
+ PCMD_RSP_CONTEXT pCmdRspEventContext = &pAd->CmdRspEventContext;
+ UINT i;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("--->RTUSBCancelPendingBulkInIRP\n"));
+ for ( i = 0; i < (RX_RING_SIZE); i++)
+ {
+ pRxContext = &(pAd->RxContext[i]);
+ if(pRxContext->IRPPending == TRUE)
+ {
+ RTUSB_UNLINK_URB(pRxContext->pUrb);
+ pRxContext->IRPPending = FALSE;
+ pRxContext->InUse = FALSE;
+ /*NdisInterlockedDecrement(&pAd->PendingRx);*/
+ /*pAd->PendingRx--;*/
+ }
+ }
+
+ if (pCmdRspEventContext->IRPPending == TRUE)
+ {
+ printk("unlink cmd rsp urb\n");
+ RTUSB_UNLINK_URB(pCmdRspEventContext->pUrb);
+ pCmdRspEventContext->IRPPending = FALSE;
+ pCmdRspEventContext->InUse = FALSE;
+ }
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("<---RTUSBCancelPendingBulkInIRP\n"));
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTUSBCancelPendingBulkOutIRP(
+ IN PRTMP_ADAPTER pAd)
+{
+ PHT_TX_CONTEXT pHTTXContext;
+ PTX_CONTEXT pMLMEContext;
+ PTX_CONTEXT pNullContext;
+ PTX_CONTEXT pPsPollContext;
+ UINT i, Idx;
+/* unsigned int IrqFlags;*/
+/* NDIS_SPIN_LOCK *pLock;*/
+/* BOOLEAN *pPending;*/
+
+
+/* pLock = &pAd->BulkOutLock[MGMTPIPEIDX];*/
+/* pPending = &pAd->BulkOutPending[MGMTPIPEIDX];*/
+
+ for (Idx = 0; Idx < 4; Idx++)
+ {
+ pHTTXContext = &(pAd->TxContext[Idx]);
+
+ if (pHTTXContext->IRPPending == TRUE)
+ {
+
+ /* Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself*/
+ /* remove it from the HeadPendingSendList and NULL out HeadPendingSendList*/
+ /* when the last IRP on the list has been cancelled; that's how we exit this loop*/
+
+
+ RTUSB_UNLINK_URB(pHTTXContext->pUrb);
+
+ /* Sleep 200 microseconds to give cancellation time to work*/
+ RTMPusecDelay(200);
+ }
+
+#ifdef RALINK_ATE
+ pHTTXContext->bCopySavePad = 0;
+ pHTTXContext->CurWritePosition = 0;
+ pHTTXContext->CurWriteRealPos = 0;
+ pHTTXContext->bCurWriting = FALSE;
+ pHTTXContext->NextBulkOutPosition = 0;
+ pHTTXContext->ENextBulkOutPosition = 0;
+#endif /* RALINK_ATE */
+ pAd->BulkOutPending[Idx] = FALSE;
+ }
+
+ /*RTMP_IRQ_LOCK(pLock, IrqFlags);*/
+ for (i = 0; i < MGMT_RING_SIZE; i++)
+ {
+ pMLMEContext = (PTX_CONTEXT)pAd->MgmtRing.Cell[i].AllocVa;
+ if(pMLMEContext && (pMLMEContext->IRPPending == TRUE))
+ {
+
+ /* Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself*/
+ /* remove it from the HeadPendingSendList and NULL out HeadPendingSendList*/
+ /* when the last IRP on the list has been cancelled; that's how we exit this loop*/
+
+
+ RTUSB_UNLINK_URB(pMLMEContext->pUrb);
+ pMLMEContext->IRPPending = FALSE;
+
+ /* Sleep 200 microsecs to give cancellation time to work*/
+ RTMPusecDelay(200);
+ }
+ }
+ pAd->BulkOutPending[MGMTPIPEIDX] = FALSE;
+ /*RTMP_IRQ_UNLOCK(pLock, IrqFlags);*/
+
+ pNullContext = &(pAd->NullContext);
+ if (pNullContext->IRPPending == TRUE)
+ RTUSB_UNLINK_URB(pNullContext->pUrb);
+
+ pPsPollContext = &(pAd->PsPollContext);
+ if (pPsPollContext->IRPPending == TRUE)
+ RTUSB_UNLINK_URB(pPsPollContext->pUrb);
+
+ for (Idx = 0; Idx < 4; Idx++)
+ {
+ NdisAcquireSpinLock(&pAd->BulkOutLock[Idx]);
+ pAd->BulkOutPending[Idx] = FALSE;
+ NdisReleaseSpinLock(&pAd->BulkOutLock[Idx]);
+ }
+}
+
+#endif /* RTMP_MAC_USB */
diff --git a/cleopatre/devkit/mt7601udrv/common/rtusb_data.c b/cleopatre/devkit/mt7601udrv/common/rtusb_data.c
new file mode 100644
index 0000000000..321cc5a219
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rtusb_data.c
@@ -0,0 +1,31 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2005, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ rtusb_data.c
+
+ Abstract:
+ Ralink USB driver Tx/Rx functions.
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Jan 03-25-2006 created
+
+*/
+
+
diff --git a/cleopatre/devkit/mt7601udrv/common/rtusb_dev_id.c b/cleopatre/devkit/mt7601udrv/common/rtusb_dev_id.c
new file mode 100644
index 0000000000..d3e03736a0
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rtusb_dev_id.c
@@ -0,0 +1,48 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ****************************************************************************
+
+ Module Name:
+ rtusb_dev_id.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ --------- ---------- ----------------------------------------------
+ */
+
+#define RTMP_MODULE_OS
+
+/*#include "rt_config.h"*/
+#include "rtmp_comm.h"
+#include "rt_os_util.h"
+#include "rt_os_net.h"
+
+
+/* module table */
+USB_DEVICE_ID rtusb_dev_id[] = {
+#ifdef RT6570
+ {USB_DEVICE(0x148f,0x6570)}, /* Ralink 6570 */
+#endif /* RT6570 */
+ {USB_DEVICE(0x148f, 0x7650)}, /* MT7650 */
+#ifdef MT7601U
+ {USB_DEVICE(0x148f,0x6370)}, /* Ralink 6370 */
+ {USB_DEVICE(0x148f,0x7601)}, /* MT 6370 */
+#endif /* MT7601U */
+ { }/* Terminating entry */
+};
+
+INT const rtusb_usb_id_len = sizeof(rtusb_dev_id) / sizeof(USB_DEVICE_ID);
+MODULE_DEVICE_TABLE(usb, rtusb_dev_id);
diff --git a/cleopatre/devkit/mt7601udrv/common/rtusb_io.c b/cleopatre/devkit/mt7601udrv/common/rtusb_io.c
new file mode 100644
index 0000000000..11148338d9
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/rtusb_io.c
@@ -0,0 +1,2021 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2006, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ rtusb_io.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+ Paul Lin 06-25-2004 created
+*/
+
+#ifdef RTMP_MAC_USB
+
+
+#include "rt_config.h"
+
+#define MAX_VENDOR_REQ_RETRY_COUNT 10
+
+/*
+ ========================================================================
+
+ Routine Description: NIC initialization complete
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+
+static NTSTATUS RTUSBFirmwareRun(
+ IN PRTMP_ADAPTER pAd)
+{
+ NTSTATUS Status;
+
+ Status = RTUSB_VendorRequest(
+ pAd,
+ USBD_TRANSFER_DIRECTION_OUT,
+ DEVICE_VENDOR_REQUEST_OUT,
+ 0x01,
+ 0x8,
+ 0,
+ NULL,
+ 0);
+
+ return Status;
+}
+
+
+
+/*
+ ========================================================================
+
+ Routine Description: Get current firmware operation mode (Return Value)
+
+ Arguments:
+
+ Return Value:
+ 0 or 1 = Downloaded by host driver
+ others = Driver doesn't download firmware
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSBFirmwareOpmode(
+ IN PRTMP_ADAPTER pAd,
+ OUT PULONG pValue)
+{
+ NTSTATUS Status;
+
+ Status = RTUSB_VendorRequest(
+ pAd,
+ (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK),
+ DEVICE_VENDOR_REQUEST_IN,
+ 0x1,
+ 0x11,
+ 0,
+ pValue,
+ 4);
+ return Status;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description: Write Firmware to NIC.
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSBFirmwareWrite(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pFwImage,
+ IN ULONG FwLen)
+{
+ UINT32 MacReg;
+ NTSTATUS Status;
+/* ULONG i;*/
+ USHORT writeLen;
+ /*ULONG FMode = 0;*/
+
+
+ Status = RTUSBReadMACRegister(pAd, MAC_CSR0, &MacReg);
+
+
+ /* write firmware */
+ writeLen = FwLen;
+#ifdef USB_FIRMWARE_MULTIBYTE_WRITE
+ DBGPRINT(RT_DEBUG_TRACE, ("USB_FIRMWARE_MULTIBYTE_WRITE defined! Write_Bytes = %d\n", MULTIWRITE_BYTES));
+ RTUSBMultiWrite_nBytes(pAd, FIRMWARE_IMAGE_BASE, pFwImage, writeLen, MULTIWRITE_BYTES);
+#else
+ DBGPRINT(RT_DEBUG_TRACE, ("USB_FIRMWARE_MULTIBYTE_WRITE not defined!\n"));
+ RTUSBMultiWrite(pAd, FIRMWARE_IMAGE_BASE, pFwImage, writeLen, FALSE);
+#endif
+ Status = RTUSBWriteMACRegister(pAd, 0x7014, 0xffffffff, FALSE);
+ Status = RTUSBWriteMACRegister(pAd, 0x701c, 0xffffffff, FALSE);
+
+ /* change 8051 from ROM to RAM */
+ Status = RTUSBFirmwareRun(pAd);
+
+
+ return Status;
+}
+
+
+NTSTATUS RTUSBVenderReset(
+ IN PRTMP_ADAPTER pAd)
+{
+ NTSTATUS Status;
+
+ pAd->VendorResetFlag = TRUE;
+
+ Status = RTUSB_VendorRequest(
+ pAd,
+ USBD_TRANSFER_DIRECTION_OUT,
+ DEVICE_VENDOR_REQUEST_OUT,
+ 0x01,
+ 0x1,
+ 0,
+ NULL,
+ 0);
+
+ pAd->VendorResetFlag = FALSE;
+
+ return Status;
+}
+/*
+ ========================================================================
+
+ Routine Description: Read various length data from RT2573
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSBMultiRead(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ OUT PUCHAR pData,
+ IN USHORT length)
+{
+ NTSTATUS Status;
+
+ Status = RTUSB_VendorRequest(
+ pAd,
+ (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK),
+ DEVICE_VENDOR_REQUEST_IN,
+ 0x7,
+ 0,
+ Offset,
+ pData,
+ length);
+
+ return Status;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description: Write various length data to RT USB Wifi device, the maxima length should not large than 65535 bytes.
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+ Use this funciton carefully cause it may not stable in some special USB host controllers.
+
+ ========================================================================
+*/
+NTSTATUS RTUSBMultiWrite_nBytes(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN PUCHAR pData,
+ IN USHORT length,
+ IN USHORT batchLen)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ USHORT index = Offset, actLen = batchLen, leftLen = length;
+ PUCHAR pSrc = pData;
+
+
+ do
+ {
+ actLen = (actLen > batchLen ? batchLen : actLen);
+ Status = RTUSB_VendorRequest(
+ pAd,
+ USBD_TRANSFER_DIRECTION_OUT,
+ DEVICE_VENDOR_REQUEST_OUT,
+ 0x6,
+ 0,
+ index,
+ pSrc,
+ actLen);
+
+ if (Status != STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("VendrCmdMultiWrite_nBytes failed!\n"));
+ break;
+ }
+
+ index += actLen;
+ leftLen -= actLen;
+ pSrc = pSrc + actLen;
+ }while(leftLen > 0);
+
+ return Status;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description: Write various length data to RT2573
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSBMultiWrite_OneByte(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN PUCHAR pData)
+{
+ NTSTATUS Status;
+
+ /* TODO: In 2870, use this funciton carefully cause it's not stable.*/
+ Status = RTUSB_VendorRequest(
+ pAd,
+ USBD_TRANSFER_DIRECTION_OUT,
+ DEVICE_VENDOR_REQUEST_OUT,
+ 0x6,
+ 0,
+ Offset,
+ pData,
+ 1);
+
+ return Status;
+}
+
+NTSTATUS RTUSBMultiWrite(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN PUCHAR pData,
+ IN USHORT length,
+ IN BOOLEAN bWriteHigh)
+{
+ NTSTATUS Status;
+
+
+ USHORT index = 0,Value;
+ PUCHAR pSrc = pData;
+ USHORT resude = 0;
+
+ resude = length % 2;
+ length += resude;
+ do
+ {
+ Value =(USHORT)( *pSrc | (*(pSrc + 1) << 8));
+ Status = RTUSBSingleWrite(pAd,Offset + index, Value, bWriteHigh);
+ index +=2;
+ length -= 2;
+ pSrc = pSrc + 2;
+ }while(length > 0);
+
+ return Status;
+}
+
+
+NTSTATUS RTUSBSingleWrite(
+ IN RTMP_ADAPTER *pAd,
+ IN USHORT Offset,
+ IN USHORT Value,
+ IN BOOLEAN WriteHigh)
+{
+ NTSTATUS Status;
+
+ Status = RTUSB_VendorRequest(
+ pAd,
+ USBD_TRANSFER_DIRECTION_OUT,
+ DEVICE_VENDOR_REQUEST_OUT,
+ (WriteHigh == TRUE) ? 0x10 : 0x2,
+ Value,
+ Offset,
+ NULL,
+ 0);
+
+ return Status;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description: Read 32-bit MAC register
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSBReadMACRegister(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ OUT PUINT32 pValue)
+{
+ NTSTATUS Status = 0;
+ UINT32 localVal;
+
+ Status = RTUSB_VendorRequest(
+ pAd,
+ (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK),
+ DEVICE_VENDOR_REQUEST_IN,
+ 0x7,
+ 0,
+ Offset,
+ &localVal,
+ 4);
+
+ *pValue = le2cpu32(localVal);
+
+
+ if (Status != 0)
+ *pValue = 0xffffffff;
+
+ return Status;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description: Write 32-bit MAC register
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSBWriteMACRegister(
+ IN RTMP_ADAPTER *pAd,
+ IN USHORT Offset,
+ IN UINT32 Value,
+ IN BOOLEAN bWriteHigh)
+{
+ NTSTATUS Status;
+ UINT32 localVal;
+
+ localVal = Value;
+ Status = RTUSBSingleWrite(pAd, Offset, (USHORT)(localVal & 0xffff), bWriteHigh);
+ Status = RTUSBSingleWrite(pAd, Offset + 2, (USHORT)((localVal & 0xffff0000) >> 16), bWriteHigh);
+
+ return Status;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description: Read 8-bit BBP register via firmware
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSBReadBBPRegister(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Id,
+ IN PUCHAR pValue)
+{
+ BBP_CSR_CFG_STRUC BbpCsr;
+ int i, k, ret;
+
+
+ RTMP_SEM_EVENT_WAIT(&pAd->reg_atomic, ret);
+ if (ret != 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("reg_atomic get failed(ret=%d)\n", ret));
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ for (i=0; i<MAX_BUSY_COUNT; i++)
+ {
+ RTUSBReadMACRegister(pAd, H2M_BBP_AGENT, &BbpCsr.word);
+ if (BbpCsr.field.Busy == BUSY)
+ continue;
+
+ BbpCsr.word = 0;
+ BbpCsr.field.fRead = 1;
+ BbpCsr.field.BBP_RW_MODE = 1;
+ BbpCsr.field.Busy = 1;
+ BbpCsr.field.RegNum = Id;
+ RTUSBWriteMACRegister(pAd, H2M_BBP_AGENT, BbpCsr.word, FALSE);
+ AsicSendCommandToMcu(pAd, 0x80, 0xff, 0x0, 0x0, TRUE);
+ for (k=0; k<MAX_BUSY_COUNT; k++)
+ {
+ RTUSBReadMACRegister(pAd, H2M_BBP_AGENT, &BbpCsr.word);
+ if (BbpCsr.field.Busy == IDLE)
+ break;
+ }
+ if ((BbpCsr.field.Busy == IDLE) &&
+ (BbpCsr.field.RegNum == Id))
+ {
+ *pValue = (UCHAR)BbpCsr.field.Value;
+ break;
+ }
+ }
+
+ RTMP_SEM_EVENT_UP(&pAd->reg_atomic);
+
+ if (BbpCsr.field.Busy == BUSY)
+ {
+ DBGPRINT_ERR(("BBP read R%d=0x%x fail\n", Id, BbpCsr.word));
+ *pValue = pAd->BbpWriteLatch[Id];
+ return STATUS_UNSUCCESSFUL;
+ }
+ return STATUS_SUCCESS;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description: Write 8-bit BBP register via firmware
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSBWriteBBPRegister(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Id,
+ IN UCHAR Value)
+{
+ BBP_CSR_CFG_STRUC BbpCsr;
+ int BusyCnt;
+ int ret;
+
+ RTMP_SEM_EVENT_WAIT(&pAd->reg_atomic, ret);
+ if (ret != 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("reg_atomic get failed(ret=%d)\n", ret));
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ for (BusyCnt=0; BusyCnt<MAX_BUSY_COUNT; BusyCnt++)
+ {
+ RTMP_IO_READ32(pAd, H2M_BBP_AGENT, &BbpCsr.word);
+ if (BbpCsr.field.Busy == BUSY)
+ continue;
+ BbpCsr.word = 0;
+ BbpCsr.field.fRead = 0;
+ BbpCsr.field.BBP_RW_MODE = 1;
+ BbpCsr.field.Busy = 1;
+ BbpCsr.field.Value = Value;
+ BbpCsr.field.RegNum = Id;
+ RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word);
+ AsicSendCommandToMcu(pAd, 0x80, 0xff, 0x0, 0x0, TRUE);
+ pAd->BbpWriteLatch[Id] = Value;
+ break;
+ }
+
+ RTMP_SEM_EVENT_UP(&pAd->reg_atomic);
+
+ if (BusyCnt == MAX_BUSY_COUNT)
+ {
+ DBGPRINT_ERR(("BBP write R%d=0x%x fail\n", Id, BbpCsr.word));
+ return STATUS_UNSUCCESSFUL;
+ }
+ return STATUS_SUCCESS;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description: Write RF register through MAC
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSBWriteRFRegister(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT32 Value)
+{
+ RF_CSR_CFG0_STRUC PhyCsr4;
+ UINT i = 0;
+ NTSTATUS status;
+
+ NdisZeroMemory(&PhyCsr4, sizeof(RF_CSR_CFG0_STRUC));
+
+ RTMP_SEM_EVENT_WAIT(&pAd->reg_atomic, status);
+ if (status != 0) {
+ DBGPRINT(RT_DEBUG_ERROR, ("reg_atomic get failed(ret=%d)\n", status));
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ status = STATUS_UNSUCCESSFUL;
+ do
+ {
+ status = RTUSBReadMACRegister(pAd, RF_CSR_CFG0, &PhyCsr4.word);
+ if (status >= 0)
+ {
+ if (!(PhyCsr4.field.Busy))
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("RTUSBWriteRFRegister(RF_CSR_CFG0):retry count=%d!\n", i));
+ i++;
+ }
+ while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
+
+ if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+ {
+ DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
+ goto done;
+ }
+
+ RTUSBWriteMACRegister(pAd, RF_CSR_CFG0, Value, FALSE);
+ status = STATUS_SUCCESS;
+
+done:
+ RTMP_SEM_EVENT_UP(&pAd->reg_atomic);
+
+ return status;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSBReadEEPROM(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ OUT PUCHAR pData,
+ IN USHORT length)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ Status = RTUSB_VendorRequest(
+ pAd,
+ (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK),
+ DEVICE_VENDOR_REQUEST_IN,
+ 0x9,
+ 0,
+ Offset,
+ pData,
+ length);
+
+ return Status;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSBWriteEEPROM(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN PUCHAR pData,
+ IN USHORT length)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ USHORT Value;
+
+ Status = RTUSB_VendorRequest(
+ pAd,
+ USBD_TRANSFER_DIRECTION_OUT,
+ DEVICE_VENDOR_REQUEST_OUT,
+ 0x8,
+ 0,
+ Offset,
+ pData,
+ length);
+
+ return Status;
+}
+
+
+NTSTATUS RTUSBReadEEPROM16(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT offset,
+ OUT PUSHORT pData)
+{
+ NTSTATUS status;
+ USHORT localData;
+
+ status = RTUSBReadEEPROM(pAd, offset, (PUCHAR)(&localData), 2);
+ if (status == STATUS_SUCCESS)
+ *pData = le2cpu16(localData);
+
+ return status;
+
+}
+
+NTSTATUS RTUSBWriteEEPROM16(
+ IN RTMP_ADAPTER *pAd,
+ IN USHORT offset,
+ IN USHORT value)
+{
+ USHORT tmpVal;
+
+ tmpVal = cpu2le16(value);
+ return RTUSBWriteEEPROM(pAd, offset, (PUCHAR)&(tmpVal), 2);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTUSBPutToSleep(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 value;
+
+ /* Timeout 0x40 x 50us*/
+ value = (SLEEPCID<<16)+(OWNERMCU<<24)+ (0x40<<8)+1;
+ RTUSBWriteMACRegister(pAd, 0x7010, value, FALSE);
+ RTUSBWriteMACRegister(pAd, 0x404, 0x30, FALSE);
+ /*RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); */
+ DBGPRINT_RAW(RT_DEBUG_ERROR, ("Sleep Mailbox testvalue %x\n", value));
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSBWakeUp(
+ IN PRTMP_ADAPTER pAd)
+{
+ NTSTATUS Status;
+
+ Status = RTUSB_VendorRequest(
+ pAd,
+ USBD_TRANSFER_DIRECTION_OUT,
+ DEVICE_VENDOR_REQUEST_OUT,
+ 0x01,
+ 0x09,
+ 0,
+ NULL,
+ 0);
+
+ return Status;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+
+ IRQL =
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS RTUSBEnqueueCmdFromNdis(
+ IN PRTMP_ADAPTER pAd,
+ IN NDIS_OID Oid,
+ IN BOOLEAN SetInformation,
+ IN PVOID pInformationBuffer,
+ IN UINT32 InformationBufferLength)
+{
+ NDIS_STATUS status;
+ PCmdQElmt cmdqelmt = NULL;
+ RTMP_OS_TASK *pTask = &pAd->cmdQTask;
+
+
+ RTMP_OS_TASK_LEGALITY(pTask)
+ ;
+ else
+ return (NDIS_STATUS_RESOURCES);
+
+ status = os_alloc_mem(pAd, (PUCHAR *)(&cmdqelmt), sizeof(CmdQElmt));
+ if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt == NULL))
+ return (NDIS_STATUS_RESOURCES);
+
+ cmdqelmt->buffer = NULL;
+ if (pInformationBuffer != NULL)
+ {
+ status = os_alloc_mem(pAd, (PUCHAR *)&cmdqelmt->buffer, InformationBufferLength);
+ if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt->buffer == NULL))
+ {
+/* kfree(cmdqelmt);*/
+ os_free_mem(NULL, cmdqelmt);
+ return (NDIS_STATUS_RESOURCES);
+ }
+ else
+ {
+ NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength);
+ cmdqelmt->bufferlength = InformationBufferLength;
+ }
+ }
+ else
+ cmdqelmt->bufferlength = 0;
+
+ cmdqelmt->command = Oid;
+ cmdqelmt->CmdFromNdis = TRUE;
+ if (SetInformation == TRUE)
+ cmdqelmt->SetOperation = TRUE;
+ else
+ cmdqelmt->SetOperation = FALSE;
+
+ NdisAcquireSpinLock(&pAd->CmdQLock);
+ if (pAd->CmdQ.CmdQState & RTMP_TASK_CAN_DO_INSERT)
+ {
+ EnqueueCmd((&pAd->CmdQ), cmdqelmt);
+ status = NDIS_STATUS_SUCCESS;
+ }
+ else
+ {
+ status = NDIS_STATUS_FAILURE;
+ }
+ NdisReleaseSpinLock(&pAd->CmdQLock);
+
+ if (status == NDIS_STATUS_FAILURE)
+ {
+ if (cmdqelmt->buffer)
+ os_free_mem(pAd, cmdqelmt->buffer);
+ os_free_mem(pAd, cmdqelmt);
+ }
+ else
+ RTCMDUp(&pAd->cmdQTask);
+
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+
+/*
+ ========================================================================
+ Routine Description:
+ RTUSB_VendorRequest - Builds a ralink specific request, sends it off to USB endpoint zero and waits for completion
+
+ Arguments:
+ @pAd:
+ @TransferFlags:
+ @RequestType: USB message request type value
+ @Request: USB message request value
+ @Value: USB message value
+ @Index: USB message index value
+ @TransferBuffer: USB data to be sent
+ @TransferBufferLength: Lengths in bytes of the data to be sent
+
+ Context: ! in atomic context
+
+ Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_FAILURE
+
+ Note:
+ This function sends a simple control message to endpoint zero
+ and waits for the message to complete, or CONTROL_TIMEOUT_JIFFIES timeout.
+ Because it is synchronous transfer, so don't use this function within an atomic context,
+ otherwise system will hang, do be careful.
+
+ TransferBuffer may located in stack region which may not in DMA'able region in some embedded platforms,
+ so need to copy TransferBuffer to UsbVendorReqBuf allocated by kmalloc to do DMA transfer.
+ Use UsbVendorReq_semaphore to protect this region which may be accessed by multi task.
+ Normally, coherent issue is resloved by low-level HC driver, so do not flush this zone by RTUSB_VendorRequest.
+
+ ========================================================================
+*/
+NTSTATUS RTUSB_VendorRequest(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT32 TransferFlags,
+ IN UCHAR RequestType,
+ IN UCHAR Request,
+ IN USHORT Value,
+ IN USHORT Index,
+ IN PVOID TransferBuffer,
+ IN UINT32 TransferBufferLength)
+{
+ int RET = 0;
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ if(in_interrupt())
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("BUG: RTUSB_VendorRequest is called from invalid context\n"));
+ return NDIS_STATUS_FAILURE;
+ }
+
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ {
+ /*DBGPRINT(RT_DEBUG_ERROR, ("WIFI device has been disconnected\n"));*/
+ return NDIS_STATUS_FAILURE;
+ }
+ else if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_MCU_SLEEP))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MCU has entered sleep mode\n"));
+ return NDIS_STATUS_FAILURE;
+ }
+ else
+ {
+
+ int RetryCount = 0; /* RTUSB_CONTROL_MSG retry counts*/
+ ASSERT(TransferBufferLength <MAX_PARAM_BUFFER_SIZE);
+
+ RTMP_SEM_EVENT_WAIT(&(pAd->UsbVendorReq_semaphore), RET);
+ if (RET != 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("UsbVendorReq_semaphore get failed\n"));
+ return NDIS_STATUS_FAILURE;
+ }
+
+ if ((TransferBufferLength > 0) && (RequestType == DEVICE_VENDOR_REQUEST_OUT))
+ NdisMoveMemory(pAd->UsbVendorReqBuf, TransferBuffer, TransferBufferLength);
+
+ do {
+ RTUSB_CONTROL_MSG(pObj->pUsb_Dev, 0, Request, RequestType, Value, Index, pAd->UsbVendorReqBuf, TransferBufferLength, CONTROL_TIMEOUT_JIFFIES, RET);
+
+ if (RET < 0 && !pAd->VendorResetFlag) {
+ DBGPRINT(RT_DEBUG_OFF, ("#\n"));
+ if (RET == RTMP_USB_CONTROL_MSG_ENODEV)
+ {
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
+ break;
+ }
+ RetryCount++;
+ RTMPusecDelay(5000); /* wait for 5ms*/
+ }
+ } while((RET < 0 && !pAd->VendorResetFlag) && (RetryCount < MAX_VENDOR_REQ_RETRY_COUNT));
+
+ if ( (!(RET < 0)) && (TransferBufferLength > 0) && (RequestType == DEVICE_VENDOR_REQUEST_IN))
+ NdisMoveMemory(TransferBuffer, pAd->UsbVendorReqBuf, TransferBufferLength);
+
+ RTMP_SEM_EVENT_UP(&(pAd->UsbVendorReq_semaphore));
+
+ if (RET < 0) {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTUSB_VendorRequest failed(%d),TxFlags=0x%x, ReqType=%s, Req=0x%x, Idx=0x%x,pAd->Flags=0x%lx\n",
+ RET, TransferFlags, (RequestType == DEVICE_VENDOR_REQUEST_OUT ? "OUT" : "IN"), Request, Index, pAd->Flags));
+ if (Request == 0x2)
+ DBGPRINT(RT_DEBUG_ERROR, ("\tRequest Value=0x%04x!\n", Value));
+
+ if ((!TransferBuffer) && (TransferBufferLength > 0))
+ hex_dump("Failed TransferBuffer value", TransferBuffer, TransferBufferLength);
+
+ if (RET == RTMP_USB_CONTROL_MSG_ENODEV)
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
+
+ }
+
+ }
+
+ if (RET < 0)
+ return NDIS_STATUS_FAILURE;
+ else
+ return NDIS_STATUS_SUCCESS;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Creates an IRP to submite an IOCTL_INTERNAL_USB_RESET_PORT
+ synchronously. Callers of this function must be running at
+ PASSIVE LEVEL.
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+NTSTATUS RTUSB_ResetDevice(
+ IN PRTMP_ADAPTER pAd)
+{
+ NTSTATUS Status = TRUE;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("--->USB_ResetDevice\n"));
+ /*RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS);*/
+ return Status;
+}
+
+
+NTSTATUS CheckGPIOHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+ return NDIS_STATUS_SUCCESS;
+ }
+#endif /* RALINK_ATE */
+
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+static NTSTATUS ResetBulkOutHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+
+ INT32 MACValue = 0;
+ UCHAR Index = 0;
+ int ret=0;
+ PHT_TX_CONTEXT pHTTXContext;
+/* RTMP_TX_RING *pTxRing;*/
+ unsigned long IrqFlags;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_OUT(ResetPipeid=0x%0x)===>\n", pAd->bulkResetPipeid));
+
+ /* All transfers must be aborted or cancelled before attempting to reset the pipe. */
+ /*RTUSBCancelPendingBulkOutIRP(pAd);*/
+ /* Wait 10ms to let previous packet that are already in HW FIFO to clear. by MAXLEE 12-25-2007*/
+ do
+ {
+ if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ break;
+
+ RTUSBReadMACRegister(pAd, TXRXQ_PCNT, &MACValue);
+ if ((MACValue & 0xf00000/*0x800000*/) == 0)
+ break;
+
+ Index++;
+ RTMPusecDelay(10000);
+ }while(Index < 100);
+
+ RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue);
+
+ /* 2nd, to prevent Read Register error, we check the validity.*/
+ if ((MACValue & 0xc00000) == 0)
+ RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue);
+
+ /* 3rd, to prevent Read Register error, we check the validity.*/
+ if ((MACValue & 0xc00000) == 0)
+ RTUSBReadMACRegister(pAd, USB_DMA_CFG, &MACValue);
+
+ MACValue |= 0x80000;
+ RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue, FALSE);
+
+ /* Wait 1ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007*/
+ RTMPusecDelay(1000);
+
+ MACValue &= (~0x80000);
+ RTUSBWriteMACRegister(pAd, USB_DMA_CFG, MACValue, FALSE);
+ DBGPRINT(RT_DEBUG_TRACE, ("\tSet 0x2a0 bit19. Clear USB DMA TX path\n"));
+
+ /* Wait 5ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007*/
+ /*RTMPusecDelay(5000);*/
+
+ if ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG)
+ {
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+
+ if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */)
+ RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME);
+
+ RTUSBKickBulkOut(pAd);
+ DBGPRINT(RT_DEBUG_TRACE, ("\tTX MGMT RECOVER Done!\n"));
+ }
+ else
+ {
+ pHTTXContext = &(pAd->TxContext[pAd->bulkResetPipeid]);
+
+ /*NdisAcquireSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]);*/
+ RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+ if ( pAd->BulkOutPending[pAd->bulkResetPipeid] == FALSE)
+ {
+ pAd->BulkOutPending[pAd->bulkResetPipeid] = TRUE;
+ pHTTXContext->IRPPending = TRUE;
+ pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 1;
+
+ /* no matter what, clean the flag*/
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+
+ /*NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]);*/
+ RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ ret = ATEResetBulkOut(pAd);
+ else
+#endif /* RALINK_ATE */
+ {
+ RTUSBInitHTTxDesc(pAd, pHTTXContext, pAd->bulkResetPipeid,
+ pHTTXContext->BulkOutSize,
+ RtmpUsbBulkOutDataPacketComplete);
+
+ if ((ret = RTUSB_SUBMIT_URB(pHTTXContext->pUrb))!=0)
+ {
+ RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+ pAd->BulkOutPending[pAd->bulkResetPipeid] = FALSE;
+ pHTTXContext->IRPPending = FALSE;
+ pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 0;
+ RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+
+ DBGPRINT(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_OUT:Submit Tx URB failed %d\n", ret));
+ }
+ else
+ {
+ RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+
+ DBGPRINT(RT_DEBUG_TRACE,("\tCMDTHREAD_RESET_BULK_OUT: TxContext[%d]:CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, pending=%d!\n",
+ pAd->bulkResetPipeid, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition,
+ pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad,
+ pAd->BulkOutPending[pAd->bulkResetPipeid]));
+ DBGPRINT(RT_DEBUG_TRACE,("\t\tBulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n",
+ pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther));
+
+ RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("\tCMDTHREAD_RESET_BULK_OUT: Submit Tx DATA URB for failed BulkReq(0x%lx) Done, status=%d!\n",
+ pAd->bulkResetReq[pAd->bulkResetPipeid],
+ RTMP_USB_URB_STATUS_GET(pHTTXContext->pUrb)));
+ }
+ }
+ }
+ else
+ {
+ /*NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]);*/
+ /*RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);*/
+
+ DBGPRINT(RT_DEBUG_ERROR, ("CmdThread : TX DATA RECOVER FAIL for BulkReq(0x%lx) because BulkOutPending[%d] is TRUE!\n",
+ pAd->bulkResetReq[pAd->bulkResetPipeid], pAd->bulkResetPipeid));
+
+ if (pAd->bulkResetPipeid == 0)
+ {
+ UCHAR pendingContext = 0;
+ PHT_TX_CONTEXT pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[pAd->bulkResetPipeid ]);
+ PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa);
+ PTX_CONTEXT pNULLContext = (PTX_CONTEXT)(&pAd->PsPollContext);
+ PTX_CONTEXT pPsPollContext = (PTX_CONTEXT)(&pAd->NullContext[0]);
+
+ if (pHTTXContext->IRPPending)
+ pendingContext |= 1;
+ else if (pMLMEContext->IRPPending)
+ pendingContext |= 2;
+ else if (pNULLContext->IRPPending)
+ pendingContext |= 4;
+ else if (pPsPollContext->IRPPending)
+ pendingContext |= 8;
+ else
+ pendingContext = 0;
+
+ DBGPRINT(RT_DEBUG_ERROR, ("\tTX Occupied by %d!\n", pendingContext));
+ }
+
+ /* no matter what, clean the flag*/
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET);
+
+ RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);
+
+ RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << pAd->bulkResetPipeid));
+ }
+
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+ /*RTUSBKickBulkOut(pAd);*/
+ }
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_OUT<===\n"));
+ return NDIS_STATUS_SUCCESS;
+
+
+}
+
+
+/* All transfers must be aborted or cancelled before attempting to reset the pipe.*/
+static NTSTATUS ResetBulkInHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ UINT32 MACValue;
+ NTSTATUS ntStatus;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN === >\n"));
+
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ ATEResetBulkIn(pAd);
+ else
+#endif /* RALINK_ATE */
+ {
+ /*while ((atomic_read(&pAd->PendingRx) > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) */
+ if((pAd->PendingRx > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+ {
+ DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!!\n"));
+ RTUSBCancelPendingBulkInIRP(pAd);
+ RTMPusecDelay(100000);
+ pAd->PendingRx = 0;
+ }
+ }
+
+ /* Wait 10ms before reading register.*/
+ RTMPusecDelay(10000);
+ ntStatus = RTUSBReadMACRegister(pAd, MAC_CSR0, &MACValue);
+
+ /* It must be removed. Or ATE will have no RX success. */
+ if ((NT_SUCCESS(ntStatus) == TRUE) &&
+ (!(RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF |
+ fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))))
+ {
+ UCHAR i;
+
+ if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF |
+ fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))
+ return NDIS_STATUS_SUCCESS;
+
+ pAd->NextRxBulkInPosition = pAd->RxContext[pAd->NextRxBulkInIndex].BulkInOffset;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BULK_IN_RESET: NBIIdx=0x%x,NBIRIdx=0x%x, BIRPos=0x%lx. BIReq=x%lx, BIComplete=0x%lx, BICFail0x%lx\n",
+ pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, pAd->NextRxBulkInPosition, pAd->BulkInReq, pAd->BulkInComplete, pAd->BulkInCompleteFail));
+
+ for (i = 0; i < RX_RING_SIZE; i++)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("\tRxContext[%d]: IRPPending=%d, InUse=%d, Readable=%d!\n"
+ , i, pAd->RxContext[i].IRPPending, pAd->RxContext[i].InUse, pAd->RxContext[i].Readable));
+ }
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
+
+ for (i = 0; i < pAd->CommonCfg.NumOfBulkInIRP; i++)
+ {
+ /*RTUSBBulkReceive(pAd);*/
+ PRX_CONTEXT pRxContext;
+ PURB pUrb;
+ int ret = 0;
+ unsigned long IrqFlags;
+
+ RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+ pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]);
+
+ if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) || (pRxContext->InUse == TRUE))
+ {
+ RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+ return NDIS_STATUS_SUCCESS;
+ }
+
+ pRxContext->InUse = TRUE;
+ pRxContext->IRPPending = TRUE;
+ pAd->PendingRx++;
+ pAd->BulkInReq++;
+ RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+
+ /* Init Rx context descriptor*/
+ RTUSBInitRxDesc(pAd, pRxContext);
+ pUrb = pRxContext->pUrb;
+ if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0)
+ { /* fail*/
+ RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
+ pRxContext->InUse = FALSE;
+ pRxContext->IRPPending = FALSE;
+ pAd->PendingRx--;
+ pAd->BulkInReq--;
+ RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
+ DBGPRINT(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB failed(%d), status=%d\n", ret, RTMP_USB_URB_STATUS_GET(pUrb)));
+ }
+ else
+ { /* success*/
+ /*DBGPRINT(RT_DEBUG_TRACE, ("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", */
+ /* pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex));*/
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB Done, status=%d!\n", RTMP_USB_URB_STATUS_GET(pUrb)));
+ ASSERT((pRxContext->InUse == pRxContext->IRPPending));
+ }
+ }
+
+ }
+ else
+ {
+ /* Card must be removed*/
+ if (NT_SUCCESS(ntStatus) != TRUE)
+ {
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
+ DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Read Register Failed!Card must be removed!!\n\n"));
+ }
+ else
+ DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Cannot do bulk in because flags(0x%lx) on !\n", pAd->Flags));
+ }
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN <===\n"));
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+static NTSTATUS SetAsicWcidHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ RT_SET_ASIC_WCID SetAsicWcid;
+ USHORT offset;
+ UINT32 MACValue, MACRValue = 0;
+ SetAsicWcid = *((PRT_SET_ASIC_WCID)(CMDQelmt->buffer));
+
+ if (SetAsicWcid.WCID >= MAX_LEN_OF_MAC_TABLE)
+ return NDIS_STATUS_FAILURE;
+
+ offset = MAC_WCID_BASE + ((UCHAR)SetAsicWcid.WCID)*HW_WCID_ENTRY_SIZE;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_SET_ASIC_WCID : WCID = %ld, SetTid = %lx, DeleteTid = %lx.\n",
+ SetAsicWcid.WCID, SetAsicWcid.SetTid, SetAsicWcid.DeleteTid));
+
+ MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[3]<<24)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[2]<<16)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[1]<<8)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[0]);
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("1-MACValue= %x,\n", MACValue));
+ RTUSBWriteMACRegister(pAd, offset, MACValue, FALSE);
+ /* Read bitmask*/
+ RTUSBReadMACRegister(pAd, offset+4, &MACRValue);
+ if ( SetAsicWcid.DeleteTid != 0xffffffff)
+ MACRValue &= (~SetAsicWcid.DeleteTid);
+ if (SetAsicWcid.SetTid != 0xffffffff)
+ MACRValue |= (SetAsicWcid.SetTid);
+
+ MACRValue &= 0xffff0000;
+ MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[5]<<8)+pAd->MacTab.Content[SetAsicWcid.WCID].Addr[4];
+ MACValue |= MACRValue;
+ RTUSBWriteMACRegister(pAd, offset+4, MACValue, FALSE);
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-MACValue= %x,\n", MACValue));
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+static NTSTATUS DelAsicWcidHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ RT_SET_ASIC_WCID SetAsicWcid;
+ SetAsicWcid = *((PRT_SET_ASIC_WCID)(CMDQelmt->buffer));
+
+ if (SetAsicWcid.WCID >= MAX_LEN_OF_MAC_TABLE)
+ return NDIS_STATUS_FAILURE;
+
+ AsicDelWcidTab(pAd, (UCHAR)SetAsicWcid.WCID);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+static NTSTATUS SetWcidSecInfoHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ PRT_ASIC_WCID_SEC_INFO pInfo;
+
+ pInfo = (PRT_ASIC_WCID_SEC_INFO)CMDQelmt->buffer;
+ RTMPSetWcidSecurityInfo(pAd,
+ pInfo->BssIdx,
+ pInfo->KeyIdx,
+ pInfo->CipherAlg,
+ pInfo->Wcid,
+ pInfo->KeyTabFlag);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+static NTSTATUS SetAsicWcidIVEIVHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ PRT_ASIC_WCID_IVEIV_ENTRY pInfo;
+
+ pInfo = (PRT_ASIC_WCID_IVEIV_ENTRY)CMDQelmt->buffer;
+ AsicUpdateWCIDIVEIV(pAd,
+ pInfo->Wcid,
+ pInfo->Iv,
+ pInfo->Eiv);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+static NTSTATUS SetAsicWcidAttrHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ PRT_ASIC_WCID_ATTR_ENTRY pInfo;
+
+ pInfo = (PRT_ASIC_WCID_ATTR_ENTRY)CMDQelmt->buffer;
+ AsicUpdateWcidAttributeEntry(pAd,
+ pInfo->BssIdx,
+ pInfo->KeyIdx,
+ pInfo->CipherAlg,
+ pInfo->Wcid,
+ pInfo->KeyTabFlag);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+static NTSTATUS SETAsicSharedKeyHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ PRT_ASIC_SHARED_KEY pInfo;
+
+ pInfo = (PRT_ASIC_SHARED_KEY)CMDQelmt->buffer;
+ AsicAddSharedKeyEntry(pAd,
+ pInfo->BssIndex,
+ pInfo->KeyIdx,
+ &pInfo->CipherKey);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+static NTSTATUS SetAsicPairwiseKeyHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ PRT_ASIC_PAIRWISE_KEY pInfo;
+
+ pInfo = (PRT_ASIC_PAIRWISE_KEY)CMDQelmt->buffer;
+ AsicAddPairwiseKeyEntry(pAd,
+ pInfo->WCID,
+ &pInfo->CipherKey);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+
+static NTSTATUS RemovePairwiseKeyHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ UCHAR Wcid = *((PUCHAR)(CMDQelmt->buffer));
+
+ AsicRemovePairwiseKeyEntry(pAd, Wcid);
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+static NTSTATUS SetClientMACEntryHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ PRT_SET_ASIC_WCID pInfo;
+
+ pInfo = (PRT_SET_ASIC_WCID)CMDQelmt->buffer;
+ AsicUpdateRxWCIDTable(pAd, pInfo->WCID, pInfo->Addr);
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+static NTSTATUS UpdateProtectHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ PRT_ASIC_PROTECT_INFO pAsicProtectInfo;
+
+ pAsicProtectInfo = (PRT_ASIC_PROTECT_INFO)CMDQelmt->buffer;
+ AsicUpdateProtect(pAd, pAsicProtectInfo->OperationMode, pAsicProtectInfo->SetMask,
+ pAsicProtectInfo->bDisableBGProtect, pAsicProtectInfo->bNonGFExist);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+#ifdef CONFIG_AP_SUPPORT
+static NTSTATUS APUpdateCapabilityAndErpieHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ APUpdateCapabilityAndErpIe(pAd);
+ return NDIS_STATUS_SUCCESS;
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef CONFIG_AP_SUPPORT
+static NTSTATUS _802_11_CounterMeasureHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ MAC_TABLE_ENTRY *pEntry;
+
+ pEntry = (MAC_TABLE_ENTRY *)CMDQelmt->buffer;
+ HandleCounterMeasure(pAd, pEntry);
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+static NTSTATUS APEnableTXBurstHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ EDCA_AC_CFG_STRUC Ac0Cfg;
+ DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::CMDTHREAD_AP_ENABLE_TX_BURST \n"));
+
+ RTUSBReadMACRegister(pAd, EDCA_AC0_CFG, &Ac0Cfg.word);
+ Ac0Cfg.field.AcTxop = 0x20;
+ RTUSBWriteMACRegister(pAd, EDCA_AC0_CFG, Ac0Cfg.word, FALSE);
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+static NTSTATUS APDisableTXBurstHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ EDCA_AC_CFG_STRUC Ac0Cfg;
+ DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::CMDTHREAD_AP_DISABLE_TX_BURST \n"));
+
+ RTUSBReadMACRegister(pAd, EDCA_AC0_CFG, &Ac0Cfg.word);
+ Ac0Cfg.field.AcTxop = 0x0;
+ RTUSBWriteMACRegister(pAd, EDCA_AC0_CFG, Ac0Cfg.word, FALSE);
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+static NTSTATUS APAdjustEXPAckTimeHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::CMDTHREAD_AP_ADJUST_EXP_ACK_TIME \n"));
+ RTUSBWriteMACRegister(pAd, EXP_ACK_TIME, 0x005400ca, FALSE);
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+static NTSTATUS APRecoverEXPAckTimeHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::CMDTHREAD_AP_RECOVER_EXP_ACK_TIME \n"));
+ RTUSBWriteMACRegister(pAd, EXP_ACK_TIME, 0x002400ca, FALSE);
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef LED_CONTROL_SUPPORT
+static NTSTATUS SetLEDStatusHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ UCHAR LEDStatus = *((PUCHAR)(CMDQelmt->buffer));
+
+ RTMPSetLEDStatus(pAd, LEDStatus);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: CMDTHREAD_SET_LED_STATUS (LEDStatus = %d)\n",
+ __FUNCTION__, LEDStatus));
+
+ return NDIS_STATUS_SUCCESS;
+}
+#endif /* LED_CONTROL_SUPPORT */
+
+#ifdef WSC_INCLUDED
+#ifdef WSC_LED_SUPPORT
+/*WPS LED MODE 10*/
+static NTSTATUS LEDWPSMode10Hdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ UINT WPSLedMode10 = *((PUINT)(CMDQelmt->buffer));
+
+ DBGPRINT(RT_DEBUG_INFO, ("WPS LED mode 10::ON or Flash or OFF : %x\n", WPSLedMode10));
+
+ switch(WPSLedMode10)
+ {
+ case LINK_STATUS_WPS_MODE10_TURN_ON:
+ RTMPSetLEDStatus(pAd, LED_WPS_MODE10_TURN_ON);
+ break;
+ case LINK_STATUS_WPS_MODE10_FLASH:
+ RTMPSetLEDStatus(pAd,LED_WPS_MODE10_FLASH);
+ break;
+ case LINK_STATUS_WPS_MODE10_TURN_OFF:
+ RTMPSetLEDStatus(pAd, LED_WPS_MODE10_TURN_OFF);
+ break;
+ default:
+ DBGPRINT(RT_DEBUG_INFO, ("WPS LED mode 10:: No this status %d!!!\n", WPSLedMode10));
+ break;
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+#endif /* WSC_LED_SUPPORT */
+#endif /* WSC_INCLUDED */
+
+
+#ifdef CONFIG_AP_SUPPORT
+static NTSTATUS ChannelRescanHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ DBGPRINT(RT_DEBUG_TRACE, ("cmd> Re-scan channel! \n"));
+
+ pAd->CommonCfg.Channel = AP_AUTO_CH_SEL(pAd, TRUE);
+#ifdef DOT11_N_SUPPORT
+ /* If WMODE_CAP_N(phymode) and BW=40 check extension channel, after select channel */
+ N_ChannelCheck(pAd);
+#endif /* DOT11_N_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("cmd> Switch to %d! \n", pAd->CommonCfg.Channel));
+ APStop(pAd);
+ APStartUp(pAd);
+
+#ifdef AP_QLOAD_SUPPORT
+ QBSS_LoadAlarmResume(pAd);
+#endif /* AP_QLOAD_SUPPORT */
+
+ return NDIS_STATUS_SUCCESS;
+}
+#endif /* CONFIG_AP_SUPPORT*/
+
+
+#ifdef LINUX
+#ifdef RT_CFG80211_SUPPORT
+static NTSTATUS RegHintHdlr (IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ RT_CFG80211_CRDA_REG_HINT(pAd, CMDQelmt->buffer, CMDQelmt->bufferlength);
+ return NDIS_STATUS_SUCCESS;
+}
+
+static NTSTATUS RegHint11DHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ RT_CFG80211_CRDA_REG_HINT11D(pAd, CMDQelmt->buffer, CMDQelmt->bufferlength);
+ return NDIS_STATUS_SUCCESS;
+}
+
+static NTSTATUS RT_Mac80211_ScanEnd(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ RT_CFG80211_SCAN_END(pAd, FALSE);
+ return NDIS_STATUS_SUCCESS;
+}
+
+static NTSTATUS RT_Mac80211_ConnResultInfom(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ RT_CFG80211_CONN_RESULT_INFORM(pAd,
+ pAd->MlmeAux.Bssid,
+ CMDQelmt->buffer, CMDQelmt->bufferlength,
+ CMDQelmt->buffer, CMDQelmt->bufferlength,
+ 1);
+ return NDIS_STATUS_SUCCESS;
+}
+#endif /* RT_CFG80211_SUPPORT */
+#endif /* LINUX */
+
+
+
+#ifdef STREAM_MODE_SUPPORT
+static NTSTATUS UpdateTXChainAddress(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ AsicUpdateTxChainAddress(pAd, CMDQelmt->buffer);
+ return NDIS_STATUS_SUCCESS;
+}
+#endif /* STREAM_MODE_SUPPORT */
+
+#ifdef RLT_MAC
+extern CMD_RSP_HANDLER CmdRspHandlerTable[];
+
+static NTSTATUS CmdRspEventCallback(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt)
+{
+ RXFCE_INFO_CMD *pFceInfo = CMDQelmt->buffer;
+
+ (*CmdRspHandlerTable[pFceInfo->evt_type])(pAd, CMDQelmt->buffer + sizeof(*pFceInfo));
+
+ return NDIS_STATUS_SUCCESS;
+}
+#endif /* RLT_MAC */
+
+typedef NTSTATUS (*CMDHdlr)(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt);
+
+static CMDHdlr CMDHdlrTable[] = {
+ ResetBulkOutHdlr, /* CMDTHREAD_RESET_BULK_OUT*/
+ ResetBulkInHdlr, /* CMDTHREAD_RESET_BULK_IN*/
+ CheckGPIOHdlr, /* CMDTHREAD_CHECK_GPIO */
+ SetAsicWcidHdlr, /* CMDTHREAD_SET_ASIC_WCID*/
+ DelAsicWcidHdlr, /* CMDTHREAD_DEL_ASIC_WCID*/
+ SetClientMACEntryHdlr, /* CMDTHREAD_SET_CLIENT_MAC_ENTRY*/
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+#ifdef CONFIG_AP_SUPPORT
+ APUpdateCapabilityAndErpieHdlr, /* CMDTHREAD_AP_UPDATE_CAPABILITY_AND_ERPIE*/
+ APEnableTXBurstHdlr, /* CMDTHREAD_AP_ENABLE_TX_BURST*/
+ APDisableTXBurstHdlr, /* CMDTHREAD_AP_DISABLE_TX_BURST*/
+ APAdjustEXPAckTimeHdlr, /* CMDTHREAD_AP_ADJUST_EXP_ACK_TIME*/
+ APRecoverEXPAckTimeHdlr, /* CMDTHREAD_AP_RECOVER_EXP_ACK_TIME*/
+ ChannelRescanHdlr, /* CMDTHREAD_CHAN_RESCAN*/
+#else
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef LED_CONTROL_SUPPORT
+ SetLEDStatusHdlr, /* CMDTHREAD_SET_LED_STATUS*/
+#else
+ NULL,
+#endif /* LED_CONTROL_SUPPORT */
+
+#ifdef WSC_INCLUDED
+#ifdef WSC_LED_SUPPORT
+ LEDWPSMode10Hdlr, /* CMDTHREAD_LED_WPS_MODE10*/
+#else
+ NULL,
+#endif /* WSC_LED_SUPPORT */
+
+#else
+ NULL,
+#endif /* WSC_INCLUDED */
+
+ /* Security related */
+ SetWcidSecInfoHdlr, /* CMDTHREAD_SET_WCID_SEC_INFO*/
+ SetAsicWcidIVEIVHdlr, /* CMDTHREAD_SET_ASIC_WCID_IVEIV*/
+ SetAsicWcidAttrHdlr, /* CMDTHREAD_SET_ASIC_WCID_ATTR*/
+ SETAsicSharedKeyHdlr, /* CMDTHREAD_SET_ASIC_SHARED_KEY*/
+ SetAsicPairwiseKeyHdlr, /* CMDTHREAD_SET_ASIC_PAIRWISE_KEY*/
+ RemovePairwiseKeyHdlr, /* CMDTHREAD_REMOVE_PAIRWISE_KEY*/
+
+ NULL,
+
+#ifdef CONFIG_AP_SUPPORT
+ _802_11_CounterMeasureHdlr, /* CMDTHREAD_802_11_COUNTER_MEASURE*/
+#else
+ NULL,
+#endif /* CONFIG_AP_SUPPORT */
+
+ UpdateProtectHdlr, /* CMDTHREAD_UPDATE_PROTECT*/
+
+
+#ifdef LINUX
+#ifdef RT_CFG80211_SUPPORT
+ RegHintHdlr,
+ RegHint11DHdlr,
+ RT_Mac80211_ScanEnd,
+ RT_Mac80211_ConnResultInfom,
+#else
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+#endif /* RT_CFG80211_SUPPORT */
+
+#else
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+#endif /* LINUX */
+
+ NULL,
+
+ NULL,
+
+#ifdef STREAM_MODE_SUPPORT
+ UpdateTXChainAddress, /* CMDTHREAD_UPDATE_TX_CHAIN_ADDRESS */
+#else
+ NULL,
+#endif
+
+#ifdef RLT_MAC
+ CmdRspEventCallback, /* CMDTHREAD_RESPONSE_EVENT_CALLBACK */
+#endif /* RLT_MAC */
+};
+
+
+static inline BOOLEAN ValidCMD(IN PCmdQElmt CMDQelmt)
+{
+ SHORT CMDIndex = CMDQelmt->command - CMDTHREAD_FIRST_CMD_ID;
+ USHORT CMDHdlrTableLength= sizeof(CMDHdlrTable) / sizeof(CMDHdlr);
+
+ if ( (CMDIndex >= 0) && (CMDIndex < CMDHdlrTableLength))
+ {
+ if (CMDHdlrTable[CMDIndex] > 0)
+ return TRUE;
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("No corresponding CMDHdlr for this CMD(%x)\n", CMDQelmt->command));
+ return FALSE;
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("CMD(%x) is out of boundary\n", CMDQelmt->command));
+ return FALSE;
+ }
+}
+
+
+VOID CMDHandler(
+ IN PRTMP_ADAPTER pAd)
+{
+ PCmdQElmt cmdqelmt;
+ NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
+ NTSTATUS ntStatus;
+/* unsigned long IrqFlags;*/
+
+ while (pAd && pAd->CmdQ.size > 0)
+ {
+ NdisStatus = NDIS_STATUS_SUCCESS;
+
+ NdisAcquireSpinLock(&pAd->CmdQLock);
+ RTThreadDequeueCmd(&pAd->CmdQ, &cmdqelmt);
+ NdisReleaseSpinLock(&pAd->CmdQLock);
+
+ if (cmdqelmt == NULL)
+ break;
+
+
+ if(!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
+ {
+ if(ValidCMD(cmdqelmt))
+ ntStatus = (*CMDHdlrTable[cmdqelmt->command - CMDTHREAD_FIRST_CMD_ID])(pAd, cmdqelmt);
+ }
+
+ if (cmdqelmt->CmdFromNdis == TRUE)
+ {
+ if (cmdqelmt->buffer != NULL)
+ os_free_mem(pAd, cmdqelmt->buffer);
+ os_free_mem(pAd, cmdqelmt);
+ }
+ else
+ {
+ if ((cmdqelmt->buffer != NULL) && (cmdqelmt->bufferlength != 0))
+ os_free_mem(pAd, cmdqelmt->buffer);
+ os_free_mem(pAd, cmdqelmt);
+ }
+ } /* end of while */
+}
+
+VOID RTUSBWatchDog(IN RTMP_ADAPTER *pAd)
+{
+ PHT_TX_CONTEXT pHTTXContext;
+ int idx;
+ ULONG irqFlags;
+ PURB pUrb;
+ BOOLEAN needDumpSeq = FALSE;
+ UINT32 MACValue;
+
+
+ return;
+
+ if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+
+ idx = 0;
+ RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
+ if ((MACValue & 0xff) !=0 )
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 0 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
+ RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40012);
+ while((MACValue &0xff) != 0 && (idx++ < 10))
+ {
+ RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
+ RTMPusecDelay(1);
+ }
+ RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
+ }
+
+ idx = 0;
+ if ((MACValue & 0xff00) !=0 )
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("TX QUEUE 1 Not EMPTY(Value=0x%0x). !!!!!!!!!!!!!!!\n", MACValue));
+ RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf4000a);
+ while((MACValue &0xff00) != 0 && (idx++ < 10))
+ {
+ RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue);
+ RTMPusecDelay(1);
+ }
+ RTMP_IO_WRITE32(pAd, PBF_CFG, 0xf40006);
+ }
+
+
+ if (pAd->watchDogRxOverFlowCnt >= 2)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Rx Bulk-In hanged! Cancel the pending Rx bulks request!\n"));
+ if ((!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS |
+ fRTMP_ADAPTER_BULKIN_RESET |
+ fRTMP_ADAPTER_HALT_IN_PROGRESS |
+ fRTMP_ADAPTER_NIC_NOT_EXIST))))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Call CMDTHREAD_RESET_BULK_IN to cancel the pending Rx Bulk!\n"));
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET);
+ RTEnqueueInternalCmd(pAd, CMDTHREAD_RESET_BULK_IN, NULL, 0);
+ needDumpSeq = TRUE;
+ }
+ pAd->watchDogRxOverFlowCnt = 0;
+ }
+
+
+ for (idx = 0; idx < NUM_OF_TX_RING; idx++)
+ {
+ pUrb = NULL;
+
+ RTMP_IRQ_LOCK(&pAd->BulkOutLock[idx], irqFlags);
+/* if ((pAd->BulkOutPending[idx] == TRUE) && pAd->watchDogTxPendingCnt)*/
+ if (pAd->BulkOutPending[idx] == TRUE)
+ {
+ pAd->watchDogTxPendingCnt[idx]++;
+
+ if ((pAd->watchDogTxPendingCnt[idx] > 2) &&
+ (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_BULKOUT_RESET)))
+ )
+ {
+ /* FIXME: Following code just support single bulk out. If you wanna support multiple bulk out. Modify it!*/
+ pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[idx]);
+ if (pHTTXContext->IRPPending)
+ { /* Check TxContext.*/
+ pUrb = pHTTXContext->pUrb;
+ }
+ else if (idx == MGMTPIPEIDX)
+ {
+ PTX_CONTEXT pMLMEContext, pNULLContext, pPsPollContext;
+
+ /*Check MgmtContext.*/
+ pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa);
+ pPsPollContext = (PTX_CONTEXT)(&pAd->PsPollContext);
+ pNULLContext = (PTX_CONTEXT)(&pAd->NullContext[0]);
+
+ if (pMLMEContext->IRPPending)
+ {
+ ASSERT(pMLMEContext->IRPPending);
+ pUrb = pMLMEContext->pUrb;
+ }
+ else if (pNULLContext->IRPPending)
+ {
+ ASSERT(pNULLContext->IRPPending);
+ pUrb = pNULLContext->pUrb;
+ }
+ else if (pPsPollContext->IRPPending)
+ {
+ ASSERT(pPsPollContext->IRPPending);
+ pUrb = pPsPollContext->pUrb;
+ }
+ }
+
+ RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Maybe the Tx Bulk-Out hanged! Cancel the pending Tx bulks request of idx(%d)!\n", idx));
+ if (pUrb)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Unlink the pending URB!\n"));
+ /* unlink it now*/
+ RTUSB_UNLINK_URB(pUrb);
+ /* Sleep 200 microseconds to give cancellation time to work*/
+ RTMPusecDelay(200);
+ needDumpSeq = TRUE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Unkonw bulkOut URB maybe hanged!!!!!!!!!!!!\n"));
+ }
+ }
+ else
+ {
+ RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
+ }
+ }
+ else
+ {
+ RTMP_IRQ_UNLOCK(&pAd->BulkOutLock[idx], irqFlags);
+ }
+ }
+
+#ifdef DOT11_N_SUPPORT
+ /* For Sigma debug, dump the ba_reordering sequence.*/
+ if((needDumpSeq == TRUE) && (pAd->CommonCfg.bDisableReordering == 0))
+ {
+ USHORT Idx;
+ PBA_REC_ENTRY pBAEntry = NULL;
+ UCHAR count = 0;
+ struct reordering_mpdu *mpdu_blk;
+
+ Idx = pAd->MacTab.Content[BSSID_WCID].BARecWcidArray[0];
+
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ if((pBAEntry->list.qlen > 0) && (pBAEntry->list.next != NULL))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("NICUpdateRawCounters():The Queueing pkt in reordering buffer:\n"));
+ NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+ mpdu_blk = pBAEntry->list.next;
+ while (mpdu_blk)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("\t%d:Seq-%d, bAMSDU-%d!\n", count, mpdu_blk->Sequence, mpdu_blk->bAMSDU));
+ mpdu_blk = mpdu_blk->next;
+ count++;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("\npBAEntry->LastIndSeq=%d!\n", pBAEntry->LastIndSeq));
+ NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+ }
+ }
+#endif /* DOT11_N_SUPPORT */
+}
+
+#endif /* RTMP_MAC_USB */
diff --git a/cleopatre/devkit/mt7601udrv/common/scan.c b/cleopatre/devkit/mt7601udrv/common/scan.c
new file mode 100644
index 0000000000..fc2b90dc7e
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/scan.c
@@ -0,0 +1,415 @@
+/*
+
+*/
+
+#include "rt_config.h"
+
+
+#ifdef SCAN_SUPPORT
+static INT scan_ch_restore(RTMP_ADAPTER *pAd, UCHAR OpMode)
+{
+ INT bw, ch;
+
+ if (pAd->CommonCfg.BBPCurrentBW != pAd->hw_cfg.bbp_bw)
+ {
+ rtmp_bbp_set_bw(pAd, pAd->hw_cfg.bbp_bw);
+
+ AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+
+ ch = pAd->CommonCfg.CentralChannel;
+ }
+ else
+ {
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+ ch = pAd->CommonCfg.Channel;
+
+ }
+
+ switch(pAd->CommonCfg.BBPCurrentBW)
+ {
+ case BW_80:
+ bw = 80;
+ break;
+ case BW_40:
+ bw = 40;
+ break;
+ case BW_10:
+ bw = 10;
+ break;
+ case BW_20:
+ default:
+ bw =20;
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to %dMHz channel %d, Total BSS[%02d]\n",
+ bw, ch, pAd->ScanTab.BssNr));
+
+
+#ifdef CONFIG_AP_SUPPORT
+ if (OpMode == OPMODE_AP)
+ {
+
+ pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE;
+ RTMPResumeMsduTransmission(pAd);
+
+ /* iwpriv set auto channel selection*/
+ /* scanned all channels*/
+ if (pAd->ApCfg.bAutoChannelAtBootup==TRUE)
+ {
+ pAd->CommonCfg.Channel = SelectBestChannel(pAd, pAd->ApCfg.AutoChannelAlg);
+ pAd->ApCfg.bAutoChannelAtBootup = FALSE;
+#ifdef DOT11_N_SUPPORT
+ N_ChannelCheck(pAd);
+#endif /* DOT11_N_SUPPORT */
+ APStop(pAd);
+ APStartUp(pAd);
+ }
+
+ if (!((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == TRUE)))
+ AsicEnableBssSync(pAd);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ return TRUE;
+}
+
+
+
+static INT scan_active(RTMP_ADAPTER *pAd, UCHAR OpMode, UCHAR ScanType)
+{
+ UCHAR *frm_buf = NULL;
+ HEADER_802_11 Hdr80211;
+ ULONG FrameLen = 0;
+ UCHAR SsidLen = 0;
+
+
+ if (MlmeAllocateMemory(pAd, &frm_buf) != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+ if (OpMode == OPMODE_AP)
+ pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE;
+#endif /* CONFIG_AP_SUPPORT */
+ return FALSE;
+ }
+
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+ if (ScanType == SCAN_2040_BSS_COEXIST)
+ {
+ DBGPRINT(RT_DEBUG_INFO, ("SYNC - SCAN_2040_BSS_COEXIST !! Prepare to send Probe Request\n"));
+ }
+#endif /* DOT11N_DRAFT3 */
+#endif /* DOT11_N_SUPPORT */
+
+ /* There is no need to send broadcast probe request if active scan is in effect.*/
+ SsidLen = 0;
+ if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE)
+#ifdef WSC_STA_SUPPORT
+ || ((ScanType == SCAN_WSC_ACTIVE) && (OpMode == OPMODE_STA))
+#endif /* WSC_STA_SUPPORT */
+ )
+ SsidLen = pAd->MlmeAux.SsidLen;
+
+ {
+#ifdef CONFIG_AP_SUPPORT
+ /*IF_DEV_CONFIG_OPMODE_ON_AP(pAd) */
+ if (OpMode == OPMODE_AP)
+ {
+ MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR,
+ pAd->ApCfg.MBSSID[0].Bssid);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ MakeOutgoingFrame(frm_buf, &FrameLen,
+ sizeof(HEADER_802_11), &Hdr80211,
+ 1, &SsidIe,
+ 1, &SsidLen,
+ SsidLen, pAd->MlmeAux.Ssid,
+ 1, &SupRateIe,
+ 1, &pAd->CommonCfg.SupRateLen,
+ pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate,
+ END_OF_ARGS);
+
+ if (pAd->CommonCfg.ExtRateLen)
+ {
+ ULONG Tmp;
+ MakeOutgoingFrame(frm_buf + FrameLen, &Tmp,
+ 1, &ExtRateIe,
+ 1, &pAd->CommonCfg.ExtRateLen,
+ pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate,
+ END_OF_ARGS);
+ FrameLen += Tmp;
+ }
+ }
+#ifdef DOT11_N_SUPPORT
+ if (WMODE_CAP_N(pAd->CommonCfg.PhyMode))
+ {
+ ULONG Tmp;
+ UCHAR HtLen;
+ UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
+#ifdef RT_BIG_ENDIAN
+ HT_CAPABILITY_IE HtCapabilityTmp;
+#endif
+ if (pAd->bBroadComHT == TRUE)
+ {
+ HtLen = pAd->MlmeAux.HtCapabilityLen + 4;
+#ifdef RT_BIG_ENDIAN
+ NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
+ *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+#ifdef UNALIGNMENT_SUPPORT
+ {
+ EXT_HT_CAP_INFO extHtCapInfo;
+
+ NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO));
+ *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo));
+ NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO));
+ }
+#else
+ *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+#endif /* UNALIGNMENT_SUPPORT */
+
+ MakeOutgoingFrame(frm_buf + FrameLen, &Tmp,
+ 1, &WpaIe,
+ 1, &HtLen,
+ 4, &BROADCOM[0],
+ pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp,
+ END_OF_ARGS);
+#else
+ MakeOutgoingFrame(frm_buf + FrameLen, &Tmp,
+ 1, &WpaIe,
+ 1, &HtLen,
+ 4, &BROADCOM[0],
+ pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
+ END_OF_ARGS);
+#endif /* RT_BIG_ENDIAN */
+ }
+ else
+ {
+ HtLen = sizeof(HT_CAPABILITY_IE);
+#ifdef RT_BIG_ENDIAN
+ NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE);
+ *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+#ifdef UNALIGNMENT_SUPPORT
+ {
+ EXT_HT_CAP_INFO extHtCapInfo;
+
+ NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO));
+ *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo));
+ NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO));
+ }
+#else
+ *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+#endif /* UNALIGNMENT_SUPPORT */
+
+ MakeOutgoingFrame(frm_buf + FrameLen, &Tmp,
+ 1, &HtCapIe,
+ 1, &HtLen,
+ HtLen, &HtCapabilityTmp,
+ END_OF_ARGS);
+#else
+ MakeOutgoingFrame(frm_buf + FrameLen, &Tmp,
+ 1, &HtCapIe,
+ 1, &HtLen,
+ HtLen, &pAd->CommonCfg.HtCapability,
+ END_OF_ARGS);
+#endif /* RT_BIG_ENDIAN */
+ }
+ FrameLen += Tmp;
+
+#ifdef DOT11N_DRAFT3
+ if ((pAd->MlmeAux.Channel <= 14) && (pAd->CommonCfg.bBssCoexEnable == TRUE))
+ {
+ ULONG Tmp;
+ HtLen = 1;
+ MakeOutgoingFrame(frm_buf + FrameLen, &Tmp,
+ 1, &ExtHtCapIe,
+ 1, &HtLen,
+ 1, &pAd->CommonCfg.BSSCoexist2040.word,
+ END_OF_ARGS);
+
+ FrameLen += Tmp;
+ }
+#endif /* DOT11N_DRAFT3 */
+ }
+#endif /* DOT11_N_SUPPORT */
+
+#ifdef DOT11_VHT_AC
+ if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) &&
+ (pAd->MlmeAux.Channel > 14)) {
+ FrameLen += build_vht_ies(pAd, (UCHAR *)(frm_buf + FrameLen), SUBTYPE_PROBE_REQ);
+ }
+#endif /* DOT11_VHT_AC */
+
+#ifdef WSC_STA_SUPPORT
+ if (OpMode == OPMODE_STA)
+ {
+ BOOLEAN bHasWscIe = FALSE;
+ /*
+ Append WSC information in probe request if WSC state is running
+ */
+ if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) &&
+ (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) &&
+ (pAd->StaCfg.WscControl.bWscTrigger == TRUE))
+ bHasWscIe = TRUE;
+#ifdef WSC_V2_SUPPORT
+ else if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) &&
+ (pAd->StaCfg.WscControl.WscV2Info.bEnableWpsV2))
+ bHasWscIe = TRUE;
+#endif /* WSC_V2_SUPPORT */
+
+
+ if (bHasWscIe)
+ {
+ UCHAR *pWscBuf = NULL, WscIeLen = 0;
+ ULONG WscTmpLen = 0;
+
+ os_alloc_mem(NULL, (UCHAR **)&pWscBuf, 512);
+ if (pWscBuf != NULL)
+ {
+ NdisZeroMemory(pWscBuf, 512);
+ WscBuildProbeReqIE(pAd, STA_MODE, pWscBuf, &WscIeLen);
+
+ MakeOutgoingFrame(frm_buf + FrameLen, &WscTmpLen,
+ WscIeLen, pWscBuf,
+ END_OF_ARGS);
+
+ FrameLen += WscTmpLen;
+ os_free_mem(NULL, pWscBuf);
+ }
+ else
+ DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__));
+ }
+ }
+
+#endif /* WSC_STA_SUPPORT */
+
+
+
+ MiniportMMRequest(pAd, 0, frm_buf, FrameLen);
+
+
+ MlmeFreeMemory(pAd, frm_buf);
+
+ return TRUE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Scan next channel
+ ==========================================================================
+ */
+VOID ScanNextChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR OpMode)
+{
+ UCHAR ScanType = pAd->MlmeAux.ScanType;
+ UINT ScanTimeIn5gChannel = SHORT_CHANNEL_TIME;
+ BOOLEAN ScanPending = FALSE;
+ RALINK_TIMER_STRUCT *sc_timer;
+ UINT stay_time = 0;
+ UCHAR ImprovedScan_MaxScanChannelCnt;
+
+
+#ifdef RALINK_ATE
+ /* Nothing to do in ATE mode. */
+ if (ATE_ON(pAd))
+ return;
+#endif /* RALINK_ATE */
+
+
+
+
+ if ((pAd->MlmeAux.Channel == 0) || ScanPending)
+ {
+ scan_ch_restore(pAd, OpMode);
+ }
+#ifdef RTMP_MAC_USB
+#endif /* RTMP_MAC_USB */
+ else
+ {
+
+ AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE);
+ AsicLockChannel(pAd, pAd->MlmeAux.Channel);
+
+
+ /* Check if channel if passive scan under current regulatory domain */
+ if (CHAN_PropertyCheck(pAd, pAd->MlmeAux.Channel, CHANNEL_PASSIVE_SCAN) == TRUE)
+ ScanType = SCAN_PASSIVE;
+
+
+ if (OpMode == OPMODE_AP)
+ sc_timer = &pAd->MlmeAux.APScanTimer;
+ else
+ sc_timer = &pAd->MlmeAux.ScanTimer;
+
+ /* We need to shorten active scan time in order for WZC connect issue */
+ /* Chnage the channel scan time for CISCO stuff based on its IAPP announcement */
+ if (ScanType == FAST_SCAN_ACTIVE)
+ stay_time = FAST_ACTIVE_SCAN_TIME;
+ else /* must be SCAN_PASSIVE or SCAN_ACTIVE*/
+ {
+
+#ifdef CONFIG_AP_SUPPORT
+ if ((OpMode == OPMODE_AP) && (pAd->ApCfg.bAutoChannelAtBootup))
+ stay_time = AUTO_CHANNEL_SEL_TIMEOUT;
+ else
+#endif /* CONFIG_AP_SUPPORT */
+ if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode) &&
+ WMODE_CAP_5G(pAd->CommonCfg.PhyMode))
+ {
+ if (pAd->MlmeAux.Channel > 14)
+ stay_time = ScanTimeIn5gChannel;
+ else
+ stay_time = MIN_CHANNEL_TIME;
+ }
+#ifdef WIFI_P2P_CONCURRENT_FAST_SCAN
+ /* If this is not PASSIVE scan && Fast scan is enabled, we shorten the chanenl dwell time */
+ else if (ScanType != SCAN_PASSIVE && pAd->StaCfg.bImprovedScan)
+ stay_time = FAST_ACTIVE_SCAN_TIME;
+#endif /* WIFI_P2P_CONCURRENT_FAST_SCAN */
+ else
+ stay_time = MAX_CHANNEL_TIME;
+ }
+
+ RTMPSetTimer(sc_timer, stay_time);
+
+ if (SCAN_MODE_ACT(ScanType))
+ {
+ if (scan_active(pAd, OpMode, ScanType) == FALSE)
+ return;
+ }
+
+ /* For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse*/
+
+#ifdef CONFIG_AP_SUPPORT
+ if (OpMode == OPMODE_AP)
+ pAd->Mlme.ApSyncMachine.CurrState = AP_SCAN_LISTEN;
+#endif /* CONFIG_AP_SUPPORT */
+ }
+}
+
+
+BOOLEAN ScanRunning(
+ IN PRTMP_ADAPTER pAd)
+{
+ BOOLEAN rv = FALSE;
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef AP_SCAN_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ rv = ((pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_LISTEN) ? TRUE : FALSE);
+#endif /* AP_SCAN_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ return rv;
+}
+
+#endif /* SCAN_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/spectrum.c b/cleopatre/devkit/mt7601udrv/common/spectrum.c
new file mode 100644
index 0000000000..7f94ed9098
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/spectrum.c
@@ -0,0 +1,2393 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ****************************************************************************
+
+ Module Name:
+ action.c
+
+ Abstract:
+ Handle association related requests either from WSTA or from local MLME
+
+ Revision History:
+ Who When What
+ --------- ---------- ----------------------------------------------
+ Fonchi Wu 2008 created for 802.11h
+ */
+
+#include "rt_config.h"
+#include "action.h"
+
+
+/* The regulatory information in the USA (US) */
+DOT11_REGULATORY_INFORMATION USARegulatoryInfo[] =
+{
+/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
+ {0, {0, 0, {0}}}, /* Invlid entry*/
+ {1, {4, 16, {36, 40, 44, 48}}},
+ {2, {4, 23, {52, 56, 60, 64}}},
+ {3, {4, 29, {149, 153, 157, 161}}},
+ {4, {11, 23, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}},
+ {5, {5, 30, {149, 153, 157, 161, 165}}},
+ {6, {10, 14, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}},
+ {7, {10, 27, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}},
+ {8, {5, 17, {11, 13, 15, 17, 19}}},
+ {9, {5, 30, {11, 13, 15, 17, 19}}},
+ {10, {2, 20, {21, 25}}},
+ {11, {2, 33, {21, 25}}},
+ {12, {11, 30, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}}
+};
+#define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
+
+
+/* The regulatory information in Europe */
+DOT11_REGULATORY_INFORMATION EuropeRegulatoryInfo[] =
+{
+/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
+ {0, {0, 0, {0}}}, /* Invalid entry*/
+ {1, {4, 20, {36, 40, 44, 48}}},
+ {2, {4, 20, {52, 56, 60, 64}}},
+ {3, {11, 30, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}},
+ {4, {13, 20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}}
+};
+#define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
+
+
+/* The regulatory information in Japan */
+DOT11_REGULATORY_INFORMATION JapanRegulatoryInfo[] =
+{
+/* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
+ {0, {0, 0, {0}}}, /* Invalid entry*/
+ {1, {4, 22, {34, 38, 42, 46}}},
+ {2, {3, 24, {8, 12, 16}}},
+ {3, {3, 24, {8, 12, 16}}},
+ {4, {3, 24, {8, 12, 16}}},
+ {5, {3, 24, {8, 12, 16}}},
+ {6, {3, 22, {8, 12, 16}}},
+ {7, {4, 24, {184, 188, 192, 196}}},
+ {8, {4, 24, {184, 188, 192, 196}}},
+ {9, {4, 24, {184, 188, 192, 196}}},
+ {10, {4, 24, {184, 188, 192, 196}}},
+ {11, {4, 22, {184, 188, 192, 196}}},
+ {12, {4, 24, {7, 8, 9, 11}}},
+ {13, {4, 24, {7, 8, 9, 11}}},
+ {14, {4, 24, {7, 8, 9, 11}}},
+ {15, {4, 24, {7, 8, 9, 11}}},
+ {16, {6, 24, {183, 184, 185, 187, 188, 189}}},
+ {17, {6, 24, {183, 184, 185, 187, 188, 189}}},
+ {18, {6, 24, {183, 184, 185, 187, 188, 189}}},
+ {19, {6, 24, {183, 184, 185, 187, 188, 189}}},
+ {20, {6, 17, {183, 184, 185, 187, 188, 189}}},
+ {21, {6, 24, {6, 7, 8, 9, 10, 11}}},
+ {22, {6, 24, {6, 7, 8, 9, 10, 11}}},
+ {23, {6, 24, {6, 7, 8, 9, 10, 11}}},
+ {24, {6, 24, {6, 7, 8, 9, 10, 11}}},
+ {25, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}},
+ {26, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}},
+ {27, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}},
+ {28, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}},
+ {29, {8, 17, {182, 183, 184, 185, 186, 187, 188, 189}}},
+ {30, {13, 23, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}},
+ {31, {1, 23, {14}}},
+ {32, {4, 22, {52, 56, 60, 64}}}
+};
+#define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
+
+
+UINT8 GetRegulatoryMaxTxPwr(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 channel)
+{
+ ULONG RegulatoryClassLoop, ChIdx;
+ UINT8 RegulatoryClass;
+ UINT8 MaxRegulatoryClassNum;
+ PDOT11_REGULATORY_INFORMATION pRegulatoryClass;
+ PSTRING pCountry = (PSTRING)(pAd->CommonCfg.CountryCode);
+
+
+ if (strncmp(pCountry, "US", 2) == 0)
+ {
+ MaxRegulatoryClassNum = USA_REGULATORY_INFO_SIZE;
+ pRegulatoryClass = &USARegulatoryInfo[0];
+ }
+ else if (strncmp(pCountry, "JP", 2) == 0)
+ {
+ MaxRegulatoryClassNum = JP_REGULATORY_INFO_SIZE;
+ pRegulatoryClass = &JapanRegulatoryInfo[0];
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n",
+ __FUNCTION__, pCountry));
+ return 0xff;
+ }
+
+ for (RegulatoryClassLoop = 0;
+ RegulatoryClassLoop<MAX_NUM_OF_REGULATORY_CLASS;
+ RegulatoryClassLoop++)
+ {
+ PDOT11_CHANNEL_SET pChannelSet;
+
+ RegulatoryClass = pAd->CommonCfg.RegulatoryClass[RegulatoryClassLoop];
+ if (RegulatoryClass >= MaxRegulatoryClassNum)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: %c%c Unknow Requlatory class (%d)\n",
+ __FUNCTION__, pCountry[0], pCountry[1], RegulatoryClass));
+ return 0xff;
+ }
+ pChannelSet = &pRegulatoryClass[RegulatoryClass].ChannelSet;
+ for (ChIdx=0; ChIdx<pChannelSet->NumberOfChannels; ChIdx++)
+ {
+ if (channel == pChannelSet->ChannelList[ChIdx])
+ return pChannelSet->MaxTxPwr;
+
+ }
+ if (ChIdx == pChannelSet->NumberOfChannels)
+ return 0xff;
+ }
+
+ return 0xff;
+}
+
+typedef struct __TX_PWR_CFG
+{
+ UINT8 Mode;
+ UINT8 MCS;
+ UINT16 req;
+ UINT8 shift;
+ UINT32 BitMask;
+} TX_PWR_CFG;
+
+/* Note: the size of TxPwrCfg is too large, do not put it to function */
+TX_PWR_CFG TxPwrCfg[] = {
+ {MODE_CCK, 0, 0, 4, 0x000000f0},
+ {MODE_CCK, 1, 0, 0, 0x0000000f},
+ {MODE_CCK, 2, 0, 12, 0x0000f000},
+ {MODE_CCK, 3, 0, 8, 0x00000f00},
+
+ {MODE_OFDM, 0, 0, 20, 0x00f00000},
+ {MODE_OFDM, 1, 0, 16, 0x000f0000},
+ {MODE_OFDM, 2, 0, 28, 0xf0000000},
+ {MODE_OFDM, 3, 0, 24, 0x0f000000},
+ {MODE_OFDM, 4, 1, 4, 0x000000f0},
+ {MODE_OFDM, 5, 1, 0, 0x0000000f},
+ {MODE_OFDM, 6, 1, 12, 0x0000f000},
+ {MODE_OFDM, 7, 1, 8, 0x00000f00}
+#ifdef DOT11_N_SUPPORT
+ ,{MODE_HTMIX, 0, 1, 20, 0x00f00000},
+ {MODE_HTMIX, 1, 1, 16, 0x000f0000},
+ {MODE_HTMIX, 2, 1, 28, 0xf0000000},
+ {MODE_HTMIX, 3, 1, 24, 0x0f000000},
+ {MODE_HTMIX, 4, 2, 4, 0x000000f0},
+ {MODE_HTMIX, 5, 2, 0, 0x0000000f},
+ {MODE_HTMIX, 6, 2, 12, 0x0000f000},
+ {MODE_HTMIX, 7, 2, 8, 0x00000f00},
+ {MODE_HTMIX, 8, 2, 20, 0x00f00000},
+ {MODE_HTMIX, 9, 2, 16, 0x000f0000},
+ {MODE_HTMIX, 10, 2, 28, 0xf0000000},
+ {MODE_HTMIX, 11, 2, 24, 0x0f000000},
+ {MODE_HTMIX, 12, 3, 4, 0x000000f0},
+ {MODE_HTMIX, 13, 3, 0, 0x0000000f},
+ {MODE_HTMIX, 14, 3, 12, 0x0000f000},
+ {MODE_HTMIX, 15, 3, 8, 0x00000f00}
+#endif /* DOT11_N_SUPPORT */
+};
+#define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(TX_PWR_CFG))
+
+CHAR RTMP_GetTxPwr(
+ IN PRTMP_ADAPTER pAd,
+ IN HTTRANSMIT_SETTING HTTxMode)
+{
+ UINT32 Value;
+ INT Idx;
+ UINT8 PhyMode;
+ CHAR CurTxPwr;
+ UINT8 TxPwrRef = 0;
+ CHAR DaltaPwr;
+ ULONG TxPwr[5];
+
+
+#ifdef SINGLE_SKU
+ CurTxPwr = pAd->CommonCfg.DefineMaxTxPwr;
+#else
+ CurTxPwr = 19;
+#endif /* SINGLE_SKU */
+
+ /* check Tx Power setting from UI. */
+ if (pAd->CommonCfg.TxPowerPercentage > 90)
+ ;
+ else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */
+ CurTxPwr -= 1;
+ else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */
+ CurTxPwr -= 3;
+ else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */
+ CurTxPwr -= 6;
+ else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */
+ CurTxPwr -= 9;
+ else /* reduce Pwr for 12 dB. */
+ CurTxPwr -= 12;
+
+ if (pAd->CommonCfg.BBPCurrentBW == BW_40)
+ {
+ if (pAd->CommonCfg.CentralChannel > 14)
+ {
+ TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
+ TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
+ TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
+ TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
+ TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
+ }
+ else
+ {
+ TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
+ TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
+ TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
+ TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
+ TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
+ }
+ }
+ else
+ {
+ if (pAd->CommonCfg.Channel > 14)
+ {
+ TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
+ TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
+ TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
+ TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
+ TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
+ }
+ else
+ {
+ TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
+ TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
+ TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
+ TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
+ TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
+ }
+ }
+
+
+ switch(HTTxMode.field.MODE)
+ {
+ case MODE_CCK:
+ case MODE_OFDM:
+ Value = TxPwr[1];
+ TxPwrRef = (Value & 0x00000f00) >> 8;
+
+ break;
+
+#ifdef DOT11_N_SUPPORT
+ case MODE_HTMIX:
+ case MODE_HTGREENFIELD:
+ if (pAd->CommonCfg.TxStream == 1)
+ {
+ Value = TxPwr[2];
+ TxPwrRef = (Value & 0x00000f00) >> 8;
+ }
+ else if (pAd->CommonCfg.TxStream == 2)
+ {
+ Value = TxPwr[3];
+ TxPwrRef = (Value & 0x00000f00) >> 8;
+ }
+ break;
+#endif /* DOT11_N_SUPPORT */
+ }
+
+ PhyMode =
+#ifdef DOT11_N_SUPPORT
+ (HTTxMode.field.MODE == MODE_HTGREENFIELD)
+ ? MODE_HTMIX :
+#endif /* DOT11_N_SUPPORT */
+ HTTxMode.field.MODE;
+
+ for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++)
+ {
+ if ((TxPwrCfg[Idx].Mode == PhyMode)
+ && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS))
+ {
+ Value = TxPwr[TxPwrCfg[Idx].req];
+ DaltaPwr = TxPwrRef - (CHAR)((Value & TxPwrCfg[Idx].BitMask)
+ >> TxPwrCfg[Idx].shift);
+ CurTxPwr -= DaltaPwr;
+ break;
+ }
+ }
+
+ return CurTxPwr;
+}
+
+
+NDIS_STATUS MeasureReqTabInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+ NdisAllocateSpinLock(pAd, &pAd->CommonCfg.MeasureReqTabLock);
+
+/* pAd->CommonCfg.pMeasureReqTab = kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC);*/
+ os_alloc_mem(pAd, (UCHAR **)&(pAd->CommonCfg.pMeasureReqTab), sizeof(MEASURE_REQ_TAB));
+ 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", __FUNCTION__));
+ Status = NDIS_STATUS_FAILURE;
+ }
+
+ return Status;
+}
+
+VOID MeasureReqTabExit(
+ IN PRTMP_ADAPTER pAd)
+{
+ NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
+
+ if (pAd->CommonCfg.pMeasureReqTab)
+/* kfree(pAd->CommonCfg.pMeasureReqTab);*/
+ os_free_mem(NULL, pAd->CommonCfg.pMeasureReqTab);
+ pAd->CommonCfg.pMeasureReqTab = NULL;
+
+ return;
+}
+
+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", __FUNCTION__));
+ 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;
+}
+
+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", __FUNCTION__));
+ 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", __FUNCTION__));
+ }
+
+ /* 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;
+}
+
+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", __FUNCTION__));
+ 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;
+}
+
+NDIS_STATUS TpcReqTabInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+ NdisAllocateSpinLock(pAd, &pAd->CommonCfg.TpcReqTabLock);
+
+/* pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC);*/
+ os_alloc_mem(pAd, (UCHAR **)&(pAd->CommonCfg.pTpcReqTab), sizeof(TPC_REQ_TAB));
+ 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", __FUNCTION__));
+ Status = NDIS_STATUS_FAILURE;
+ }
+
+ return Status;
+}
+
+VOID TpcReqTabExit(
+ IN PRTMP_ADAPTER pAd)
+{
+ NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
+
+ if (pAd->CommonCfg.pTpcReqTab)
+/* kfree(pAd->CommonCfg.pTpcReqTab);*/
+ os_free_mem(NULL, 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", __FUNCTION__));
+ 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", __FUNCTION__));
+ 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", __FUNCTION__));
+ }
+
+ /* 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", __FUNCTION__));
+ 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:
+ Get Current Transmit Power.
+
+ Parametrs:
+
+ Return : Current Time Stamp.
+ ==========================================================================
+ */
+VOID InsertChannelRepIE(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pFrameBuf,
+ OUT PULONG pFrameLen,
+ IN PSTRING pCountry,
+ IN UINT8 RegulatoryClass)
+{
+ ULONG TempLen;
+ UINT8 Len;
+ UINT8 IEId = IE_AP_CHANNEL_REPORT;
+ PUCHAR pChListPtr = NULL;
+ PDOT11_CHANNEL_SET pChannelSet = NULL;
+
+ Len = 1;
+ if (strncmp(pCountry, "US", 2) == 0)
+ {
+ if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: USA Unknow Requlatory class (%d)\n",
+ __FUNCTION__, RegulatoryClass));
+ return;
+ }
+ pChannelSet = &USARegulatoryInfo[RegulatoryClass].ChannelSet;
+ }
+ else if (strncmp(pCountry, "JP", 2) == 0)
+ {
+ if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: JP Unknow Requlatory class (%d)\n",
+ __FUNCTION__, RegulatoryClass));
+ return;
+ }
+
+ pChannelSet = &JapanRegulatoryInfo[RegulatoryClass].ChannelSet;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n",
+ __FUNCTION__, pCountry));
+ return;
+ }
+
+ /* no match channel set. */
+ if (pChannelSet == NULL)
+ return;
+
+ /* empty channel set. */
+ if (pChannelSet->NumberOfChannels == 0)
+ return;
+
+ Len += pChannelSet->NumberOfChannels;
+ pChListPtr = pChannelSet->ChannelList;
+
+ if (Len > 1)
+ {
+ MakeOutgoingFrame(pFrameBuf, &TempLen,
+ 1, &IEId,
+ 1, &Len,
+ 1, &RegulatoryClass,
+ Len -1, pChListPtr,
+ END_OF_ARGS);
+
+ *pFrameLen = *pFrameLen + TempLen;
+ }
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Insert Dialog Token into frame.
+
+ Parametrs:
+ 1. frame buffer pointer.
+ 2. frame length.
+ 3. Dialog token.
+
+ Return : None.
+ ==========================================================================
+ */
+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;
+ UINT8 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.
+ ==========================================================================
+ */
+VOID InsertTpcReportIE(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pFrameBuf,
+ OUT PULONG pFrameLen,
+ IN UINT8 TxPwr,
+ IN UINT8 LinkMargin)
+{
+ ULONG TempLen;
+ UINT8 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 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 UINT8 Len,
+ IN PMEASURE_REQ_INFO pMeasureReqIE)
+{
+ ULONG TempLen;
+ UINT8 ElementID = IE_MEASUREMENT_REQUEST;
+
+ MakeOutgoingFrame(pFrameBuf, &TempLen,
+ 1, &ElementID,
+ 1, &Len,
+ sizeof(MEASURE_REQ_INFO), 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;
+ UINT8 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 MakeMeasurementReqFrame(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pOutBuffer,
+ OUT PULONG pFrameLen,
+ IN UINT8 TotalLen,
+ IN UINT8 Category,
+ IN UINT8 Action,
+ IN UINT8 MeasureToken,
+ IN UINT8 MeasureReqMode,
+ IN UINT8 MeasureReqType,
+ IN UINT16 NumOfRepetitions)
+{
+ ULONG TempLen;
+ MEASURE_REQ_INFO MeasureReqIE;
+
+ InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category, Action);
+
+ /* fill Dialog Token*/
+ InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen, MeasureToken);
+
+ /* fill Number of repetitions. */
+ if (Category == CATEGORY_RM)
+ {
+ MakeOutgoingFrame((pOutBuffer+*pFrameLen), &TempLen,
+ 2, &NumOfRepetitions,
+ END_OF_ARGS);
+
+ *pFrameLen += TempLen;
+ }
+
+ /* prepare Measurement IE.*/
+ NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO));
+ MeasureReqIE.Token = MeasureToken;
+ MeasureReqIE.ReqMode.word = MeasureReqMode;
+ MeasureReqIE.ReqType = MeasureReqType;
+ InsertMeasureReqIE(pAd, (pOutBuffer+*pFrameLen), pFrameLen,
+ TotalLen, &MeasureReqIE);
+
+ 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", __FUNCTION__));
+ 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 = 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", __FUNCTION__));
+ 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", __FUNCTION__));
+ 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;
+}
+
+#ifdef WDS_SUPPORT
+/*
+ ==========================================================================
+ 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:
+ 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", __FUNCTION__));
+ 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;
+}
+#endif /* WDS_SUPPORT */
+
+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->Dot11_H.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->Dot11_H.RDMode = RD_SWITCHING_MODE;
+ pAd->Dot11_H.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,
+ OUT PMEASURE_REQ pMeasureReq)
+{
+ 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 = (PUCHAR)(eid_ptr->Octet + 3);
+ NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1);
+ NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
+ pMeasureReq->MeasureStartTime = SWAP64(MeasureStartTime);
+ NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
+ pMeasureReq->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 = (PUCHAR)(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 = (PUCHAR)(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 = (PUCHAR)(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;
+
+ 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_AP_SUPPORT
+ /* ChSwAnn need check.*/
+ if ((pAd->OpMode == OPMODE_AP) &&
+ (DfsRequirementCheck(pAd, ChSwAnnInfo.Channel) == TRUE))
+ {
+ NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, ChSwAnnInfo.ChSwMode, ChSwAnnInfo.Channel);
+ StartDFSProcedure(pAd, ChSwAnnInfo.Channel, ChSwAnnInfo.ChSwMode);
+ }
+#endif /* CONFIG_AP_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_REQ MeasureReq;
+ MEASURE_REPORT_MODE ReportMode;
+
+ if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo, &MeasureReq))
+ {
+ 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;*/
+
+ os_alloc_mem(pAd, (UCHAR **)&pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT));
+/* if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)*/
+ if (pMeasureReportInfo == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __FUNCTION__, 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);*/
+ os_free_mem(NULL, 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, Elem->AntSel, BW_20),
+ ConvertToRssi(pAd, Elem->Rssi1, RSSI_1, Elem->AntSel, BW_20),
+ ConvertToRssi(pAd, Elem->Rssi2, RSSI_2, Elem->AntSel, BW_20));
+
+ /* 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",
+ __FUNCTION__, 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 PSTRING arg)
+{
+ UINT Aid = 1;
+ UINT ArgIdx;
+ PSTRING thisChar;
+
+ MEASURE_REQ_MODE MeasureReqMode;
+ UINT8 MeasureReqToken = RandomByte(pAd);
+ UINT8 MeasureReqType = RM_BASIC;
+ UINT8 MeasureCh = 1;
+ UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd);
+ MEASURE_REQ MeasureReq;
+ UINT8 TotalLen;
+
+ HEADER_802_11 ActHdr;
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen;
+
+ NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory*/
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
+ goto END_OF_MEASURE_REQ;
+ }
+
+ ArgIdx = 1;
+ while ((thisChar = strsep((char **)&arg, "-")) != NULL)
+ {
+ switch(ArgIdx)
+ {
+ case 1: /* Aid.*/
+ Aid = (UINT8) 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", __FUNCTION__, MeasureReqType));
+ goto END_OF_MEASURE_REQ;
+ }
+ break;
+
+ case 3: /* Measurement channel.*/
+ MeasureCh = (UINT8) simple_strtol(thisChar, 0, 16);
+ break;
+ }
+ ArgIdx++;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __FUNCTION__, Aid, MeasureReqType, MeasureCh));
+ if (!VALID_WCID(Aid))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid));
+ goto END_OF_MEASURE_REQ;
+ }
+
+ MeasureReqMode.word = 0;
+ MeasureReqMode.field.Enable = 1;
+
+ MeasureReqInsert(pAd, MeasureReqToken);
+
+ /* build action frame header.*/
+ MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[Aid].Addr,
+ pAd->CurrentAddress);
+
+ NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
+ FrameLen = sizeof(HEADER_802_11);
+
+ TotalLen = sizeof(MEASURE_REQ_INFO) + sizeof(MEASURE_REQ);
+
+ MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen,
+ sizeof(MEASURE_REQ_INFO), CATEGORY_RM, RM_BASIC,
+ MeasureReqToken, MeasureReqMode.word,
+ MeasureReqType, 1);
+
+ MeasureReq.ChNum = MeasureCh;
+ MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
+ MeasureReq.MeasureDuration = cpu2le16(2000);
+
+ {
+ ULONG TempLen;
+ MakeOutgoingFrame( pOutBuffer+FrameLen, &TempLen,
+ sizeof(MEASURE_REQ), &MeasureReq,
+ END_OF_ARGS);
+ FrameLen += TempLen;
+ }
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (UINT)FrameLen);
+
+END_OF_MEASURE_REQ:
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ return TRUE;
+}
+
+INT Set_TpcReq_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UINT Aid;
+
+ UINT8 TpcReqToken = RandomByte(pAd);
+
+ Aid = (UINT) simple_strtol(arg, 0, 16);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __FUNCTION__, Aid));
+ if (!VALID_WCID(Aid))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid));
+ return TRUE;
+ }
+
+ TpcReqInsert(pAd, TpcReqToken);
+
+ EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);
+
+ return TRUE;
+}
+
+#ifdef CONFIG_AP_SUPPORT
+INT Set_PwrConstraint(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+
+typedef struct __PWR_CONSTRAIN_CFG
+{
+ CHAR Attenuation;
+ ULONG TxPowerPercentage;
+} PWR_CONSTRAIN_CFG;
+
+ PWR_CONSTRAIN_CFG PwrConstrainTab[] =
+ {
+ {0, 100},
+ {1, 70},
+ {4, 50},
+ {6, 20},
+ {10, 10},
+ {13, 5}
+ };
+#define PWR_CONSTRAION_TAB_SIZE \
+ (sizeof(PwrConstrainTab)/sizeof(PWR_CONSTRAIN_CFG))
+
+ INT Idx;
+ LONG Value;
+ CHAR MaxTxPwr;
+ CHAR CurTxPwr;
+ CHAR DaltaPwr;
+
+ Value = (UINT) simple_strtol(arg, 0, 10);
+ MaxTxPwr = GetRegulatoryMaxTxPwr(pAd, pAd->CommonCfg.Channel) - (CHAR)Value;
+ CurTxPwr = RTMP_GetTxPwr(pAd, pAd->MacTab.Content[0].HTPhyMode);
+ DaltaPwr = CurTxPwr - MaxTxPwr;
+
+ if (pAd->CommonCfg.TxPowerPercentage > 90)
+ ;
+ else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */
+ DaltaPwr += 1;
+ else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */
+ DaltaPwr += 3;
+ else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */
+ DaltaPwr += 6;
+ else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */
+ DaltaPwr += 9;
+ else /* reduce Pwr for 12 dB. */
+ DaltaPwr += 12;
+
+ DBGPRINT(RT_DEBUG_OFF, ("MaxTxPwr=%d, CurTxPwr=%d, DaltaPwr=%d\n",
+ MaxTxPwr, CurTxPwr, DaltaPwr));
+
+ for (Idx = 0; Idx < PWR_CONSTRAION_TAB_SIZE; Idx++)
+ {
+ if (DaltaPwr < PwrConstrainTab[Idx].Attenuation)
+ {
+ pAd->CommonCfg.PwrConstraint = Value;
+ pAd->CommonCfg.TxPowerPercentage =
+ PwrConstrainTab[Idx].TxPowerPercentage;
+
+ break;
+ }
+ }
+
+ if (Idx == PWR_CONSTRAION_TAB_SIZE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, \
+ ("Power constraint value be in range from 0 to 13dB\n"));
+ }
+
+
+ return TRUE;
+}
+
+
+static PDOT11_REGULATORY_INFORMATION GetRugClassRegion(
+ IN PSTRING pCountryCode,
+ IN UINT8 RugClass)
+{
+ PDOT11_REGULATORY_INFORMATION pRugClass;
+
+ pRugClass = NULL;
+ do
+ {
+ if (strncmp(pCountryCode, "US", 2) == 0)
+ {
+ if (RugClass >= USA_REGULATORY_INFO_SIZE)
+ break;
+ pRugClass = &USARegulatoryInfo[RugClass];
+ }
+
+ if (strncmp(pCountryCode, "JP", 2) == 0)
+ {
+ if (RugClass >= JP_REGULATORY_INFO_SIZE)
+ break;
+ pRugClass = &JapanRegulatoryInfo[RugClass];
+
+ }
+ } while (FALSE);
+
+ return pRugClass;
+}
+
+VOID RguClass_BuildBcnChList(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf,
+ OUT PULONG pBufLen)
+{
+ INT loop;
+ ULONG TmpLen;
+ PDOT11_REGULATORY_INFORMATION pRguClassRegion;
+ PDOT11_CHANNEL_SET pChList;
+
+ for (loop = 0 ;loop < MAX_NUM_OF_REGULATORY_CLASS; loop++)
+ {
+ if (pAd->CommonCfg.RegulatoryClass[loop] == 0)
+ break;
+
+ pRguClassRegion = GetRugClassRegion(
+ (PSTRING)pAd->CommonCfg.CountryCode,
+ pAd->CommonCfg.RegulatoryClass[loop]);
+
+ pChList = &pRguClassRegion->ChannelSet;
+
+ if (pRguClassRegion == NULL)
+ return;
+
+ MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen,
+ 1, &pChList->ChannelList[0],
+ 1, &pChList->NumberOfChannels,
+ 1, &pChList->MaxTxPwr,
+ END_OF_ARGS);
+
+ *pBufLen += TmpLen;
+ }
+
+ return;
+}
+#endif /* CONFIG_AP_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/txpower.c b/cleopatre/devkit/mt7601udrv/common/txpower.c
new file mode 100644
index 0000000000..74e3cc8be7
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/txpower.c
@@ -0,0 +1,1172 @@
+/*
+
+*/
+
+#include "rt_config.h"
+
+
+#define MDSM_NORMAL_TX_POWER 0x00
+#define MDSM_DROP_TX_POWER_BY_6dBm 0x01
+#define MDSM_DROP_TX_POWER_BY_12dBm 0x02
+#define MDSM_ADD_TX_POWER_BY_6dBm 0x03
+#define MDSM_BBP_R1_STATIC_TX_POWER_CONTROL_MASK 0x03
+
+VOID AsicGetTxPowerOffset(RTMP_ADAPTER *pAd, ULONG *TxPwr)
+{
+ CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC CfgOfTxPwrCtrlOverMAC;
+ DBGPRINT(RT_DEBUG_INFO, ("-->AsicGetTxPowerOffset\n"));
+
+ NdisZeroMemory(&CfgOfTxPwrCtrlOverMAC, sizeof(CfgOfTxPwrCtrlOverMAC));
+
+ CfgOfTxPwrCtrlOverMAC.NumOfEntries = 5; /* MAC 0x1314, 0x1318, 0x131C, 0x1320 and 1324 */
+
+#ifdef DOT11_VHT_AC
+ if (pAd->CommonCfg.BBPCurrentBW == BW_80 &&
+ pAd->CommonCfg.Channel > 14)
+ {
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx80MPwrCfgABand[0];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx80MPwrCfgABand[1];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx80MPwrCfgABand[2];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx80MPwrCfgABand[3];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx80MPwrCfgABand[4];
+ }
+ else
+#endif /* DOT11_VHT_AC */
+ if (pAd->CommonCfg.BBPCurrentBW == BW_40)
+ {
+ if (pAd->CommonCfg.CentralChannel > 14)
+ {
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx40MPwrCfgABand[0];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx40MPwrCfgABand[1];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx40MPwrCfgABand[2];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx40MPwrCfgABand[3];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx40MPwrCfgABand[4];
+ }
+ else
+ {
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx40MPwrCfgGBand[0];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx40MPwrCfgGBand[1];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx40MPwrCfgGBand[2];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx40MPwrCfgGBand[3];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx40MPwrCfgGBand[4];
+ }
+ }
+ else
+ {
+ if (pAd->CommonCfg.CentralChannel > 14)
+ {
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx20MPwrCfgABand[0];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx20MPwrCfgABand[1];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx20MPwrCfgABand[2];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx20MPwrCfgABand[3];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx20MPwrCfgABand[4];
+ }
+ else
+ {
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx20MPwrCfgGBand[0];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx20MPwrCfgGBand[1];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx20MPwrCfgGBand[2];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx20MPwrCfgGBand[3];
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4;
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx20MPwrCfgGBand[4];
+ }
+ }
+
+ NdisCopyMemory(TxPwr, (UCHAR *)&CfgOfTxPwrCtrlOverMAC, sizeof(CfgOfTxPwrCtrlOverMAC));
+
+ DBGPRINT(RT_DEBUG_INFO, ("<--AsicGetTxPowerOffset\n"));
+}
+
+
+VOID AsicGetAutoAgcOffsetForExternalTxAlc(
+ IN PRTMP_ADAPTER pAd,
+ IN PCHAR pDeltaPwr,
+ IN PCHAR pTotalDeltaPwr,
+ IN PCHAR pAgcCompensate,
+ IN PCHAR pDeltaPowerByBbpR1)
+{
+ BBP_R49_STRUC BbpR49;
+ BOOLEAN bAutoTxAgc = FALSE;
+ UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep, idx;
+ PCHAR pTxAgcCompensate = NULL;
+ CHAR DeltaPwr = 0;
+
+ DBGPRINT(RT_DEBUG_INFO, ("-->%s\n", __FUNCTION__));
+
+ BbpR49.byte = 0;
+
+ /* TX power compensation for temperature variation based on TSSI. Try every 4 second */
+ if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
+ {
+ if (pAd->CommonCfg.Channel <= 14)
+ {
+ /* bg channel */
+ bAutoTxAgc = pAd->bAutoTxAgcG;
+ TssiRef = pAd->TssiRefG;
+ pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
+ pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
+ TxAgcStep = pAd->TxAgcStepG;
+ pTxAgcCompensate = &pAd->TxAgcCompensateG;
+ }
+ else
+ {
+ /* a channel */
+ bAutoTxAgc = pAd->bAutoTxAgcA;
+ TssiRef = pAd->TssiRefA;
+ pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
+ pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
+ TxAgcStep = pAd->TxAgcStepA;
+ pTxAgcCompensate = &pAd->TxAgcCompensateA;
+ }
+
+ if (bAutoTxAgc)
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49.byte);
+
+ /* TSSI representation */
+ if (IS_RT3071(pAd) || IS_RT3390(pAd) || IS_RT3090A(pAd) || IS_RT3572(pAd)) /* 5-bits */
+ {
+ BbpR49.byte = (BbpR49.byte & 0x1F);
+ }
+
+ /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
+ /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
+ /* step value is defined in pAd->TxAgcStepG for tx power value */
+
+ /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
+ /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
+ above value are examined in mass factory production */
+ /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
+
+ /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
+ /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
+ /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
+
+ if (BbpR49.byte > pTssiMinusBoundary[1])
+ {
+ /* Reading is larger than the reference value */
+ /* Check for how large we need to decrease the Tx power */
+ for (idx = 1; idx < 5; idx++)
+ {
+ if (BbpR49.byte <= pTssiMinusBoundary[idx]) /* Found the range */
+ break;
+ }
+ /* The index is the step we should decrease, idx = 0 means there is nothing to compensate */
+
+ *pTxAgcCompensate = -(TxAgcStep * (idx-1));
+ DeltaPwr += (*pTxAgcCompensate);
+ DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
+ BbpR49.byte, TssiRef, TxAgcStep, idx-1));
+ }
+ else if (BbpR49.byte < pTssiPlusBoundary[1])
+ {
+ /* Reading is smaller than the reference value */
+ /* Check for how large we need to increase the Tx power */
+ for (idx = 1; idx < 5; idx++)
+ {
+ if (BbpR49.byte >= pTssiPlusBoundary[idx]) /* Found the range*/
+ break;
+ }
+
+ /* The index is the step we should increase, idx = 0 means there is nothing to compensate */
+ *pTxAgcCompensate = TxAgcStep * (idx-1);
+ DeltaPwr += (*pTxAgcCompensate);
+ DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
+ BbpR49.byte, TssiRef, TxAgcStep, idx-1));
+ }
+ else
+ {
+ *pTxAgcCompensate = 0;
+ DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
+ BbpR49.byte, TssiRef, TxAgcStep, 0));
+ }
+ }
+ }
+ else
+ {
+ if (pAd->CommonCfg.Channel <= 14)
+ {
+ bAutoTxAgc = pAd->bAutoTxAgcG;
+ pTxAgcCompensate = &pAd->TxAgcCompensateG;
+ }
+ else
+ {
+ bAutoTxAgc = pAd->bAutoTxAgcA;
+ pTxAgcCompensate = &pAd->TxAgcCompensateA;
+ }
+
+ if (bAutoTxAgc)
+ DeltaPwr += (*pTxAgcCompensate);
+ }
+
+
+ *pDeltaPwr = DeltaPwr;
+ *pAgcCompensate = *pTxAgcCompensate;
+
+ DBGPRINT(RT_DEBUG_INFO, ("<--%s\n", __FUNCTION__));
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Gives CCK TX rate 2 more dB TX power.
+ This routine works only in LINK UP in INFRASTRUCTURE mode.
+
+ calculate desired Tx power in RF R3.Tx0~5, should consider -
+ 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
+ 1. TxPowerPercentage
+ 2. auto calibration based on TSSI feedback
+ 3. extra 2 db for CCK
+ 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
+
+ NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
+ it should be called AFTER MlmeDynamicTxRatSwitching()
+ ==========================================================================
+ */
+
+VOID AsicAdjustTxPower(
+ IN PRTMP_ADAPTER pAd)
+{
+ INT i, j;
+ CHAR Value;
+ CHAR Rssi = -127;
+ CHAR DeltaPwr = 0;
+ CHAR TxAgcCompensate = 0;
+ CHAR DeltaPowerByBbpR1 = 0;
+ CHAR TotalDeltaPower = 0; /* (non-positive number) including the transmit power controlled by the MAC and the BBP R1 */
+ CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC CfgOfTxPwrCtrlOverMAC = {0};
+#ifdef SINGLE_SKU
+ CHAR TotalDeltaPowerOri = 0;
+ UCHAR SingleSKUBbpR1Offset = 0;
+ ULONG SingleSKUTotalDeltaPwr[MAX_TXPOWER_ARRAY_SIZE] = {0};
+#endif /* SINGLE_SKU */
+
+
+
+ /* Get Tx rate offset table which from EEPROM 0xDEh ~ 0xEFh */
+ RTMP_CHIP_ASIC_TX_POWER_OFFSET_GET(pAd, (PULONG)&CfgOfTxPwrCtrlOverMAC);
+ /* Get temperature compensation delta power value */
+ RTMP_CHIP_ASIC_AUTO_AGC_OFFSET_GET(
+ pAd, &DeltaPwr, &TotalDeltaPower, &TxAgcCompensate, &DeltaPowerByBbpR1);
+
+ DBGPRINT(RT_DEBUG_INFO, ("%s: DeltaPwr=%d, TotalDeltaPower=%d, TxAgcCompensate=%d, DeltaPowerByBbpR1=%d\n",
+ __FUNCTION__,
+ DeltaPwr,
+ TotalDeltaPower,
+ TxAgcCompensate,
+ DeltaPowerByBbpR1));
+
+ /* Get delta power based on the percentage specified from UI */
+ //AsicPercentageDeltaPower(pAd, Rssi, &DeltaPwr,&DeltaPowerByBbpR1);
+
+ /* The transmit power controlled by the BBP */
+ TotalDeltaPower += DeltaPowerByBbpR1;
+ /* The transmit power controlled by the MAC */
+ TotalDeltaPower += DeltaPwr;
+
+#ifdef SINGLE_SKU
+ if (pAd->CommonCfg.bSKUMode == TRUE)
+ {
+ /* Re calculate delta power while enabling Single SKU */
+ GetSingleSkuDeltaPower(pAd, &TotalDeltaPower, (PULONG)&SingleSKUTotalDeltaPwr, &SingleSKUBbpR1Offset);
+
+ TotalDeltaPowerOri = TotalDeltaPower;
+ }
+ else
+#endif /* SINGLE_SKU */
+ {
+ AsicCompensatePowerViaBBP(pAd, &TotalDeltaPower);
+ }
+
+#ifdef MT7601
+ if ( IS_MT7601(pAd) )
+ return;
+#endif /* MT7601 */
+
+ /* Power will be updated each 4 sec. */
+ if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
+ {
+/*****************************************************************************/
+ /* Set new Tx power for different Tx rates */
+ for (i=0; i < CfgOfTxPwrCtrlOverMAC.NumOfEntries; i++)
+ {
+ TX_POWER_CONTROL_OVER_MAC_ENTRY *pTxPwrEntry;
+ ULONG reg_val;
+
+ pTxPwrEntry = &CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i];
+ reg_val = pTxPwrEntry->RegisterValue;
+ if (reg_val != 0xffffffff)
+ {
+ for (j=0; j<8; j++)
+ {
+ CHAR _upbound, _lowbound, t_pwr;
+ BOOLEAN _bValid;
+
+ _lowbound = 0;
+ _bValid = TRUE;
+
+ Value = (CHAR)((reg_val >> j*4) & 0x0F);
+#ifdef SINGLE_SKU
+ if (pAd->CommonCfg.bSKUMode == TRUE)
+ {
+ TotalDeltaPower = SingleSKUBbpR1Offset + TotalDeltaPowerOri - (CHAR)((SingleSKUTotalDeltaPwr[i] >> j*4) & 0x0F);
+
+ DBGPRINT(RT_DEBUG_INFO, ("%s: BbpR1Offset(%d) + TX ALC(%d) - SingleSKU[%d/%d](%d) = TotalDeltaPower(%d)\n",
+ __FUNCTION__, SingleSKUBbpR1Offset,
+ TotalDeltaPowerOri, i, j,
+ (CHAR)((SingleSKUTotalDeltaPwr[i] >> j*4) & 0x0F),
+ TotalDeltaPower));
+ }
+#endif /* SINGLE_SKU */
+
+#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION)
+ /* The upper bounds of MAC 0x1314 ~ 0x1324 are variable */
+ if ((pAd->TxPowerCtrl.bInternalTxALC == TRUE)^(pAd->chipCap.bTempCompTxALC == TRUE))
+ {
+ switch (0x1314 + (i * 4))
+ {
+ case 0x1314:
+ _upbound = 0xe;
+ break;
+
+ case 0x1318:
+ _upbound = (j <= 3) ? 0xc : 0xe;
+ break;
+
+ case 0x131C:
+ _upbound = ((j == 0) || (j == 2) || (j == 3)) ? 0xc : 0xe;
+ break;
+
+ case 0x1320:
+ _upbound = (j == 1) ? 0xe : 0xc;
+ break;
+
+ case 0x1324:
+ _upbound = 0xc;
+ break;
+
+ default:
+ {
+ /* do nothing */
+ _bValid = FALSE;
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown register = 0x%x\n", __FUNCTION__, (0x1314 + (i * 4))));
+ }
+ break;
+ }
+ }
+ else
+#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */
+ _upbound = 0xc;
+
+ if (_bValid)
+ {
+ t_pwr = Value + TotalDeltaPower;
+ if (t_pwr < _lowbound)
+ Value = _lowbound;
+ else if (t_pwr > _upbound)
+ Value = _upbound;
+ else
+ Value = t_pwr;
+ }
+
+ /* Fill new value into the corresponding MAC offset */
+ reg_val = (reg_val & ~(0x0000000F << j*4)) | (Value << j*4);
+ }
+
+ pTxPwrEntry->RegisterValue = reg_val;
+ RTMP_IO_WRITE32(pAd, pTxPwrEntry->MACRegisterOffset, pTxPwrEntry->RegisterValue);
+
+ }
+ }
+
+ /* Extra set MAC registers to compensate Tx power if any */
+ RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(pAd);
+ }
+
+}
+
+
+#ifdef SINGLE_SKU
+VOID GetSingleSkuDeltaPower(
+ IN PRTMP_ADAPTER pAd,
+ IN PCHAR pTotalDeltaPower,
+ INOUT PULONG pSingleSKUTotalDeltaPwr,
+ INOUT PUCHAR pSingleSKUBbpR1Offset)
+{
+ INT i, j;
+ CHAR Value;
+ CHAR MinValue = 127;
+ UCHAR BbpR1 = 0;
+ UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
+ UCHAR AdjustMaxTxPwr[(MAX_TX_PWR_CONTROL_OVER_MAC_REGISTERS * 8)];
+ CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC CfgOfTxPwrCtrlOverMAC = {0};
+
+ /* Get TX rate offset table which from EEPROM 0xDEh ~ 0xEFh */
+ RTMP_CHIP_ASIC_TX_POWER_OFFSET_GET(pAd, (PULONG)&CfgOfTxPwrCtrlOverMAC);
+
+ /* Handle regulatory max. TX power constraint */
+ if (pAd->CommonCfg.Channel > 14)
+ {
+ TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8); /* 5G band */
+ }
+ else
+ {
+ TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF); /* 2.4G band */
+ }
+
+ CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
+
+ /* Use OFDM 6M as the criterion */
+ criterion = (UCHAR)((CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue & 0x000F0000) >> 16);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d\n",
+ __FUNCTION__, criterion, TxPwrInEEPROM, CountryTxPwr));
+
+ /* Adjust max. TX power according to the relationship of TX power in EEPROM */
+ for (i=0; i<CfgOfTxPwrCtrlOverMAC.NumOfEntries; i++)
+ {
+ if (i == 0)
+ {
+ for (j=0; j<8; j++)
+ {
+ Value = (CHAR)((CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue >> j*4) & 0x0F);
+
+ if (j < 4)
+ {
+ AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4; /* CCK has 4dBm larger than OFDM */
+ }
+ else
+ {
+ AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: offset = 0x%04X, i/j=%d/%d, (Default)Value=%d, %d\n",
+ __FUNCTION__,
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset,
+ i,
+ j,
+ Value,
+ AdjustMaxTxPwr[i*8+j]));
+ }
+ }
+ else
+ {
+ for (j=0; j<8; j++)
+ {
+ Value = (CHAR)((CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue >> j*4) & 0x0F);
+
+ AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: offset = 0x%04X, i/j=%d/%d, (Default)Value=%d, %d\n",
+ __FUNCTION__,
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset,
+ i,
+ j,
+ Value,
+ AdjustMaxTxPwr[i*8+j]));
+ }
+ }
+ }
+
+ /* Adjust TX power according to the relationship */
+ for (i=0; i<CfgOfTxPwrCtrlOverMAC.NumOfEntries; i++)
+ {
+ if (CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue != 0xffffffff)
+ {
+ for (j=0; j<8; j++)
+ {
+ Value = (CHAR)((CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue >> j*4) & 0x0F);
+
+ /* The TX power is larger than the regulatory, the power should be restrained */
+ if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
+ {
+ Value = (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
+
+ if (Value > 0xF)
+ {
+ /* The output power is larger than Country Regulatory over 15dBm, the origianl design has overflow case */
+ DBGPRINT(RT_DEBUG_ERROR,("%s: Value overflow - %d\n", __FUNCTION__, Value));
+ }
+
+ *(pSingleSKUTotalDeltaPwr+i) = (*(pSingleSKUTotalDeltaPwr+i) & ~(0x0000000F << j*4)) | (Value << j*4);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: offset = 0x%04X, i/j=%d/%d, (Exceed)Value=%d, %d\n",
+ __FUNCTION__,
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset,
+ i,
+ j,
+ Value,
+ AdjustMaxTxPwr[i*8+j]));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: offset = 0x%04X, i/j=%d/%d, Value=%d, %d, no change\n",
+ __FUNCTION__,
+ CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset,
+ i,
+ j,
+ Value,
+ AdjustMaxTxPwr[i*8+j]));
+ }
+ }
+ }
+ }
+
+ /* Calculate the min. TX power */
+ for(i=0; i<CfgOfTxPwrCtrlOverMAC.NumOfEntries; i++)
+ {
+ if (CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue != 0xffffffff)
+ {
+ for (j=0; j<8; j++)
+ {
+ CHAR PwrChange;
+ /*
+ After Single SKU, each data rate offset power value is saved in TotalDeltaPwr[].
+ PwrChange will add SingleSKUDeltaPwr and TotalDeltaPwr[] for each data rate to calculate
+ the final adjust output power value which is saved in MAC Reg. and BBP_R1.
+ */
+
+ /*
+ Value / TxPwr[] is get from eeprom 0xDEh ~ 0xEFh and increase or decrease the
+ 20/40 Bandwidth Delta Value in eeprom 0x50h.
+ */
+ Value = (CHAR)((CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue >> j*4) & 0x0F); /* 0 ~ 15 */
+
+ /* Fix the corner case of Single SKU read eeprom offset 0xF0h ~ 0xFEh which for BBP Instruction configuration */
+ if (Value == 0xF)
+ continue;
+
+ /* Value_offset is current Pwr comapre with Country Regulation and need adjust delta value */
+ PwrChange = (CHAR)((*(pSingleSKUTotalDeltaPwr+i) >> j*4) & 0x0F); /* 0 ~ 15 */
+ PwrChange -= *pTotalDeltaPower;
+
+ Value -= PwrChange;
+
+ if (MinValue > Value)
+ MinValue = Value;
+ }
+ }
+ }
+
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
+ /* Depend on the min. TX power to adjust and prevent the value of MAC_TX_PWR_CFG less than 0 */
+ if ((MinValue < 0) && (MinValue >= -6))
+ {
+ BbpR1 |= MDSM_DROP_TX_POWER_BY_6dBm;
+ *pSingleSKUBbpR1Offset = 6;
+ }
+ else if ((MinValue < -6)&&(MinValue >= -12))
+ {
+ BbpR1 |= MDSM_DROP_TX_POWER_BY_12dBm;
+ *pSingleSKUBbpR1Offset = 12;
+ }
+ else if (MinValue < -12)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s: ASIC limit..\n", __FUNCTION__));
+ BbpR1 |= MDSM_DROP_TX_POWER_BY_12dBm;
+ *pSingleSKUBbpR1Offset = 12;
+ }
+
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: <After BBP R1> TotalDeltaPower = %d dBm, BbpR1 = 0x%02X \n", __FUNCTION__, *pTotalDeltaPower, BbpR1));
+}
+#endif /* SINGLE_SKU */
+
+
+VOID AsicPercentageDeltaPower(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR Rssi,
+ INOUT PCHAR pDeltaPwr,
+ INOUT PCHAR pDeltaPowerByBbpR1)
+{
+ /*
+ Calculate delta power based on the percentage specified from UI.
+ E2PROM setting is calibrated for maximum TX power (i.e. 100%).
+ We lower TX power here according to the percentage specified from UI.
+ */
+
+ if (pAd->CommonCfg.TxPowerPercentage >= 100) /* AUTO TX POWER control */
+ {
+ }
+ else if (pAd->CommonCfg.TxPowerPercentage > 90) /* 91 ~ 100% & AUTO, treat as 100% in terms of mW */
+ ;
+ else if (pAd->CommonCfg.TxPowerPercentage > 60) /* 61 ~ 90%, treat as 75% in terms of mW DeltaPwr -= 1; */
+ {
+ *pDeltaPwr -= 1;
+ }
+ else if (pAd->CommonCfg.TxPowerPercentage > 30) /* 31 ~ 60%, treat as 50% in terms of mW DeltaPwr -= 3; */
+ {
+ *pDeltaPwr -= 3;
+ }
+ else if (pAd->CommonCfg.TxPowerPercentage > 15) /* 16 ~ 30%, treat as 25% in terms of mW DeltaPwr -= 6; */
+ {
+ *pDeltaPowerByBbpR1 -= 6; /* -6 dBm */
+ }
+ else if (pAd->CommonCfg.TxPowerPercentage > 9) /* 10 ~ 15%, treat as 12.5% in terms of mW DeltaPwr -= 9; */
+ {
+ *pDeltaPowerByBbpR1 -= 6; /* -6 dBm */
+ *pDeltaPwr -= 3;
+ }
+ else /* 0 ~ 9 %, treat as MIN(~3%) in terms of mW DeltaPwr -= 12; */
+ {
+ *pDeltaPowerByBbpR1 -= 12; /* -12 dBm */
+ }
+}
+
+
+VOID AsicCompensatePowerViaBBP(
+ IN PRTMP_ADAPTER pAd,
+ INOUT PCHAR pTotalDeltaPower)
+{
+ UCHAR mdsm_drop_pwr;
+
+ DBGPRINT(RT_DEBUG_INFO, ("%s: <Before BBP R1> TotalDeltaPower = %d dBm\n", __FUNCTION__, *pTotalDeltaPower));
+
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ {
+ return;
+ }
+#endif /* MT7601 */
+
+ if (*pTotalDeltaPower <= -12)
+ {
+ *pTotalDeltaPower += 12;
+ mdsm_drop_pwr = MDSM_DROP_TX_POWER_BY_12dBm;
+
+ DBGPRINT(RT_DEBUG_INFO, ("%s: Drop the transmit power by 12 dBm (BBP R1)\n", __FUNCTION__));
+ }
+ else if ((*pTotalDeltaPower <= -6) && (*pTotalDeltaPower > -12))
+ {
+ *pTotalDeltaPower += 6;
+ mdsm_drop_pwr = MDSM_DROP_TX_POWER_BY_6dBm;
+
+ DBGPRINT(RT_DEBUG_INFO, ("%s: Drop the transmit power by 6 dBm (BBP R1)\n", __FUNCTION__));
+ }
+ else
+ {
+ /* Control the the transmit power by using the MAC only */
+ mdsm_drop_pwr = MDSM_NORMAL_TX_POWER;
+ }
+
+#ifdef RT65xx
+ if (IS_RT65XX(pAd))
+ {
+ UINT32 bbp_val = 0;
+
+ RTMP_BBP_IO_READ32(pAd, TXBE_R4, &bbp_val);
+ bbp_val &= (~0x3);
+ bbp_val |= mdsm_drop_pwr;
+ RTMP_BBP_IO_WRITE32(pAd, TXBE_R4, bbp_val);
+ DBGPRINT(RT_DEBUG_INFO, ("%s: <After TXBE_R4> TotalDeltaPower = %d dBm, TXBE_R4 = 0x%0x\n", __FUNCTION__, *pTotalDeltaPower, bbp_val));
+ }
+ else
+#endif /* RT65xx */
+ {
+ UCHAR BbpR1 = 0;
+
+ /* The BBP R1 controls the transmit power for all rates */
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
+ BbpR1 &= ~MDSM_BBP_R1_STATIC_TX_POWER_CONTROL_MASK;
+ BbpR1 |= mdsm_drop_pwr;
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
+
+ DBGPRINT(RT_DEBUG_INFO, ("%s: <After BBP R1> TotalDeltaPower = %d dBm, BbpR1 = 0x%02X \n", __FUNCTION__, *pTotalDeltaPower, BbpR1));
+ }
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Read initial Tx power per MCS and BW from EEPROM
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPReadTxPwrPerRate(RTMP_ADAPTER *pAd)
+{
+ ULONG data, Adata, Gdata;
+ USHORT i, value, value2;
+ USHORT value_1, value_2, value_3, value_4;
+ INT Apwrdelta, Gpwrdelta;
+ UCHAR t1,t2,t3,t4;
+ BOOLEAN bApwrdeltaMinus = TRUE, bGpwrdeltaMinus = TRUE;
+
+
+
+
+#ifdef RT8592
+ if (IS_RT8592(pAd)) {
+ RT85592ReadTxPwrPerRate(pAd);
+ return;
+ }
+#endif /* RT8592 */
+
+#ifdef RT65xx
+ if (IS_RT6590(pAd)) {
+ RT6590ReadTxPwrPerRate(pAd);
+ return;
+ }
+#endif /* RT65xx */
+
+
+#ifdef MT7601
+ if (IS_MT7601(pAd)) {
+ MT7601_ReadTxPwrPerRate(pAd);
+ return;
+ }
+#endif /* MT7601 */
+
+ /* For default one, go here!! */
+ {
+
+ /* Get power delta for 20MHz and 40MHz.*/
+ DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n"));
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value2);
+ Apwrdelta = 0;
+ Gpwrdelta = 0;
+
+ if ((value2 & 0xff) != 0xff)
+ {
+ if ((value2 & 0x80))
+ Gpwrdelta = (value2&0xf);
+
+ if ((value2 & 0x40))
+ bGpwrdeltaMinus = FALSE;
+ else
+ bGpwrdeltaMinus = TRUE;
+ }
+ if ((value2 & 0xff00) != 0xff00)
+ {
+ if ((value2 & 0x8000))
+ Apwrdelta = ((value2&0xf00)>>8);
+
+ if ((value2 & 0x4000))
+ bApwrdeltaMinus = FALSE;
+ else
+ bApwrdeltaMinus = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("Gpwrdelta = %x, Apwrdelta = %x .\n", Gpwrdelta, Apwrdelta));
+
+
+ /* Get Txpower per MCS for 20MHz in 2.4G.*/
+
+ for (i=0; i<5; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4, value);
+ data = value;
+
+ /* use value_1 ~ value_4 for code size reduce */
+ value_1 = value&0xf;
+ value_2 = (value&0xf0)>>4;
+ value_3 = (value&0xf00)>>8;
+ value_4 = (value&0xf000)>>12;
+
+ if (bApwrdeltaMinus == FALSE)
+ {
+ t1 = value_1+(Apwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = value_2+(Apwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = value_3+(Apwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = value_4+(Apwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if (value_1 > Apwrdelta)
+ t1 = value_1-(Apwrdelta);
+ else
+ t1 = 0;
+ if (value_2 > Apwrdelta)
+ t2 = value_2-(Apwrdelta);
+ else
+ t2 = 0;
+ if (value_3 > Apwrdelta)
+ t3 = value_3-(Apwrdelta);
+ else
+ t3 = 0;
+ if (value_4 > Apwrdelta)
+ t4 = value_4-(Apwrdelta);
+ else
+ t4 = 0;
+ }
+ Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
+ if (bGpwrdeltaMinus == FALSE)
+ {
+ t1 = value_1+(Gpwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = value_2+(Gpwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = value_3+(Gpwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = value_4+(Gpwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if (value_1 > Gpwrdelta)
+ t1 = value_1-(Gpwrdelta);
+ else
+ t1 = 0;
+ if (value_2 > Gpwrdelta)
+ t2 = value_2-(Gpwrdelta);
+ else
+ t2 = 0;
+ if (value_3 > Gpwrdelta)
+ t3 = value_3-(Gpwrdelta);
+ else
+ t3 = 0;
+ if (value_4 > Gpwrdelta)
+ t4 = value_4-(Gpwrdelta);
+ else
+ t4 = 0;
+ }
+ Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4 + 2, value);
+
+ /* use value_1 ~ value_4 for code size reduce */
+ value_1 = value&0xf;
+ value_2 = (value&0xf0)>>4;
+ value_3 = (value&0xf00)>>8;
+ value_4 = (value&0xf000)>>12;
+
+ if (bApwrdeltaMinus == FALSE)
+ {
+ t1 = value_1+(Apwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = value_2+(Apwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = value_3+(Apwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = value_4+(Apwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if (value_1 > Apwrdelta)
+ t1 = value_1-(Apwrdelta);
+ else
+ t1 = 0;
+ if (value_2 > Apwrdelta)
+ t2 = value_2-(Apwrdelta);
+ else
+ t2 = 0;
+ if (value_3 > Apwrdelta)
+ t3 = value_3-(Apwrdelta);
+ else
+ t3 = 0;
+ if (value_4 > Apwrdelta)
+ t4 = value_4-(Apwrdelta);
+ else
+ t4 = 0;
+ }
+ Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
+ if (bGpwrdeltaMinus == FALSE)
+ {
+ t1 = value_1+(Gpwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = value_2+(Gpwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = value_3+(Gpwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = value_4+(Gpwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if (value_1 > Gpwrdelta)
+ t1 = value_1-(Gpwrdelta);
+ else
+ t1 = 0;
+ if (value_2 > Gpwrdelta)
+ t2 = value_2-(Gpwrdelta);
+ else
+ t2 = 0;
+ if (value_3 > Gpwrdelta)
+ t3 = value_3-(Gpwrdelta);
+ else
+ t3 = 0;
+ if (value_4 > Gpwrdelta)
+ t4 = value_4-(Gpwrdelta);
+ else
+ t4 = 0;
+ }
+ Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
+ data |= (value<<16);
+
+ /* For 20M/40M Power Delta issue */
+ pAd->Tx20MPwrCfgABand[i] = data;
+ pAd->Tx20MPwrCfgGBand[i] = data;
+ pAd->Tx40MPwrCfgABand[i] = Adata;
+ pAd->Tx40MPwrCfgGBand[i] = Gdata;
+
+ if (data != 0xffffffff)
+ RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, data);
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%lx, Adata = %lx, Gdata = %lx \n", data, Adata, Gdata));
+ }
+ }
+
+ /* Extra set MAC registers to compensate Tx power if any */
+ RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(pAd);
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Read initial channel power parameters from EEPROM
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPReadChannelPwr(RTMP_ADAPTER *pAd)
+{
+ UINT32 i, choffset;
+ EEPROM_TX_PWR_STRUC Power;
+ EEPROM_TX_PWR_STRUC Power2;
+
+ /* Read Tx power value for all channels*/
+ /* Value from 1 - 0x7f. Default value is 24.*/
+ /* Power value : 2.4G 0x00 (0) ~ 0x1F (31)*/
+ /* : 5.5G 0xF9 (-7) ~ 0x0F (15)*/
+
+ /* 0. 11b/g, ch1 - ch 14*/
+ for (i = 0; i < 7; i++)
+ {
+
+ { /* Default routine. RT3070 and RT3370 run here. */
+ RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2, Power.word);
+ RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2, Power2.word);
+ pAd->TxPower[i * 2].Channel = i * 2 + 1;
+ pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2;
+
+ pAd->TxPower[i * 2].Power = Power.field.Byte0;
+ if(!IS_RT3390(pAd)) // 3370 has different Tx power range
+ {
+ if ((Power.field.Byte0 > 31) || (Power.field.Byte0 < 0))
+ pAd->TxPower[i * 2].Power = DEFAULT_RF_TX_POWER;
+ }
+
+ pAd->TxPower[i * 2 + 1].Power = Power.field.Byte1;
+ if(!IS_RT3390(pAd)) // 3370 has different Tx power range
+ {
+ if ((Power.field.Byte1 > 31) || (Power.field.Byte1 < 0))
+ pAd->TxPower[i * 2 + 1].Power = DEFAULT_RF_TX_POWER;
+ }
+
+ if ((Power2.field.Byte0 > 31) || (Power2.field.Byte0 < 0))
+ pAd->TxPower[i * 2].Power2 = DEFAULT_RF_TX_POWER;
+ else
+ pAd->TxPower[i * 2].Power2 = Power2.field.Byte0;
+
+ if ((Power2.field.Byte1 > 31) || (Power2.field.Byte1 < 0))
+ pAd->TxPower[i * 2 + 1].Power2 = DEFAULT_RF_TX_POWER;
+ else
+ pAd->TxPower[i * 2 + 1].Power2 = Power2.field.Byte1;
+ }
+ }
+
+
+ {
+ if (IS_RT5592(pAd))
+ return;
+
+ /* 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz)*/
+ /* 1.1 Fill up channel*/
+ choffset = 14;
+ for (i = 0; i < 4; i++)
+ {
+ pAd->TxPower[3 * i + choffset + 0].Channel = 36 + i * 8 + 0;
+ pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * i + choffset + 1].Channel = 36 + i * 8 + 2;
+ pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * i + choffset + 2].Channel = 36 + i * 8 + 4;
+ pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER;
+ }
+
+ /* 1.2 Fill up power*/
+ for (i = 0; i < 6; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2, Power.word);
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2, Power2.word);
+
+ if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7))
+ pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0;
+
+ if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7))
+ pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1;
+
+ if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7))
+ pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0;
+
+ if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7))
+ pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1;
+ }
+
+ /* 2. HipperLAN 2 100, 102 ,104; 108, 110, 112; 116, 118, 120; 124, 126, 128; 132, 134, 136; 140 (including central frequency in BW 40MHz)*/
+ /* 2.1 Fill up channel*/
+ choffset = 14 + 12;
+ for (i = 0; i < 5; i++)
+ {
+ pAd->TxPower[3 * i + choffset + 0].Channel = 100 + i * 8 + 0;
+ pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * i + choffset + 1].Channel = 100 + i * 8 + 2;
+ pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * i + choffset + 2].Channel = 100 + i * 8 + 4;
+ pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER;
+ }
+ pAd->TxPower[3 * 5 + choffset + 0].Channel = 140;
+ pAd->TxPower[3 * 5 + choffset + 0].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * 5 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
+
+ /* 2.2 Fill up power*/
+ for (i = 0; i < 8; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word);
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word);
+
+ if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7))
+ pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0;
+
+ if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7))
+ pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1;
+
+ if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7))
+ pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0;
+
+ if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7))
+ pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1;
+ }
+
+ /* 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165, 167, 169; 171, 173 (including central frequency in BW 40MHz)*/
+ /* 3.1 Fill up channel*/
+ choffset = 14 + 12 + 16;
+ /*for (i = 0; i < 2; i++)*/
+ for (i = 0; i < 3; i++)
+ {
+ pAd->TxPower[3 * i + choffset + 0].Channel = 149 + i * 8 + 0;
+ pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * i + choffset + 1].Channel = 149 + i * 8 + 2;
+ pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * i + choffset + 2].Channel = 149 + i * 8 + 4;
+ pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER;
+ }
+ pAd->TxPower[3 * 3 + choffset + 0].Channel = 171;
+ pAd->TxPower[3 * 3 + choffset + 0].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * 3 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * 3 + choffset + 1].Channel = 173;
+ pAd->TxPower[3 * 3 + choffset + 1].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * 3 + choffset + 1].Power2 = DEFAULT_RF_TX_POWER;
+
+ /* 3.2 Fill up power*/
+ /*for (i = 0; i < 4; i++)*/
+ for (i = 0; i < 6; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word);
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word);
+
+ if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7))
+ pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0;
+
+ if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7))
+ pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1;
+
+ if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7))
+ pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0;
+
+ if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7))
+ pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1;
+ }
+ }
+
+
+ /* 4. Print and Debug*/
+ /*choffset = 14 + 12 + 16 + 7;*/
+ choffset = 14 + 12 + 16 + 11;
+
+
+}
+
diff --git a/cleopatre/devkit/mt7601udrv/common/uapsd.c b/cleopatre/devkit/mt7601udrv/common/uapsd.c
new file mode 100644
index 0000000000..f75164acbd
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/uapsd.c
@@ -0,0 +1,2074 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************/
+
+/****************************************************************************
+
+ Abstract:
+
+ All related WMM UAPSD function body.
+
+ Two EOSP sent mechanism:
+ 1. Use DMA Done to do the check.
+ a. safe but not accuracy, because maybe all packets are still in hardware
+ DMA, not yet be sent to air, but DMA Done are all 1
+ b. in USB chip, the data completion does not mean a packet is sent, it
+ means a block of data is sent, so we need to use another method to
+ know how many packets are sent in the data completion function
+
+ 2. Use TX Statistics to do the check.
+ a. unsafe but accuracy, because too many traffic are sent before TX Done
+ Interrupt occurs and the statistics count will be overwrited.
+ b. management frames will not be counted
+ c. frames using 1Mbps (CCK) will no be counted
+ d. legacy ps frame sent after a PS-Poll frame is also be counted, we
+ need to handle the mix mode case: some AC are legacy PS and some AC
+ are UAPSD
+ e. in USB chip, only one statistics counter for all station entries;
+ so only use DMA Done mechanism in USB device; but in PCI chip,
+ one statistics counter for each station entries.
+
+ All ACs have two UAPSD modes:
+ 1. Delivery-enabled
+ meaningful mode for AC in AP
+
+ 2. Trigger-enabled
+ meaningful mode for AC in STA
+
+ Only WMM ACM is used, we need to discriminate between Delivery-enabled and
+ Trigger-enabled AC, or all AC are Delivery/Trigger-enabled or not
+ Delivery/Trigger-enabled.
+
+***************************************************************************/
+
+#define MODULE_WMM_UAPSD
+#include "rt_config.h"
+
+#ifdef UAPSD_SUPPORT
+#include "uapsd.h"
+
+/*#define UAPSD_DEBUG */
+
+/* used to enable or disable UAPSD power save queue maintain mechanism */
+UCHAR gUAPSD_FlgNotQueueMaintain;
+
+#ifdef UAPSD_DEBUG
+UINT32 gUAPSD_SP_CloseAbnormalNum;
+#endif /* UAPSD_DEBUG */
+
+#ifdef UAPSD_TIMING_RECORD_FUNC
+/* all unit: us */
+
+UCHAR gUAPSD_TimingFlag;
+UINT32 gUAPSD_TimingIndexUapsd;
+UINT32 gUAPSD_TimingLoopIndex;
+
+/* ISR start timestamp */
+UINT64 gUAPSD_TimingIsr[UAPSD_TIMING_RECORD_MAX];
+
+/* Tasklet start timestamp */
+UINT64 gUAPSD_TimingTasklet[UAPSD_TIMING_RECORD_MAX];
+
+UINT64 gUAPSD_TimingTrgRcv[UAPSD_TIMING_RECORD_MAX];
+UINT64 gUAPSD_TimingMov2Tx[UAPSD_TIMING_RECORD_MAX];
+UINT64 gUAPSD_TimingTx2Air[UAPSD_TIMING_RECORD_MAX];
+
+UINT32 gUAPSD_TimingSumIsr2Tasklet;
+UINT32 gUAPSD_TimingSumTrig2Txqueue;
+UINT32 gUAPSD_TimingSumTxqueue2Air;
+#endif /* UAPSD_TIMING_RECORD_FUNC */
+
+
+#ifdef VENDOR_FEATURE3_SUPPORT
+static VOID UAPSD_InsertTailQueueAc(
+ IN RTMP_ADAPTER *pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN QUEUE_HEADER *pQueueHeader,
+ IN QUEUE_ENTRY *pQueueEntry);
+#endif /* VENDOR_FEATURE3_SUPPORT */
+
+
+
+
+/*
+========================================================================
+Routine Description:
+ UAPSD Module Init.
+
+Arguments:
+ pAd Pointer to our adapter
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID UAPSD_Init(
+ IN PRTMP_ADAPTER pAd)
+{
+ /* allocate a lock resource for SMP environment */
+ NdisAllocateSpinLock(pAd, &pAd->UAPSDEOSPLock);
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> allocate a spinlock!\n"));
+#endif /* UAPSD_DEBUG */
+
+#ifdef UAPSD_DEBUG
+ gUAPSD_SP_CloseAbnormalNum = 0;
+#endif /* UAPSD_DEBUG */
+
+#ifdef UAPSD_TIMING_RECORD_FUNC
+ gUAPSD_TimingFlag = 0; /* default: DISABLE */
+ gUAPSD_TimingIndexUapsd = 0;
+ gUAPSD_TimingLoopIndex = 0;
+
+
+ gUAPSD_TimingSumIsr2Tasklet = 0;
+ gUAPSD_TimingSumTrig2Txqueue = 0;
+ gUAPSD_TimingSumTxqueue2Air = 0;
+#endif /* UAPSD_TIMING_RECORD_FUNC */
+}
+
+
+/*
+========================================================================
+Routine Description:
+ UAPSD Module Release.
+
+Arguments:
+ pAd Pointer to our adapter
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID UAPSD_Release(
+ IN PRTMP_ADAPTER pAd)
+{
+ /* free the lock resource for SMP environment */
+ NdisFreeSpinLock(&pAd->UAPSDEOSPLock);
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> release a spinlock!\n"));
+#endif /* UAPSD_DEBUG */
+} /* End of UAPSD_Release */
+
+/*
+========================================================================
+Routine Description:
+ Check if ASIC can enter sleep mode. Not software sleep.
+
+Arguments:
+ pAd Pointer to our adapter
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID RtmpAsicSleepHandle(
+ IN PRTMP_ADAPTER pAd)
+{
+ BOOLEAN FlgCanAsicSleep = TRUE;
+
+
+
+} /* End of RtmpAsicSleepHandle */
+
+
+
+/*
+========================================================================
+Routine Description:
+ Close current Service Period.
+
+Arguments:
+ pAd Pointer to our adapter
+ pEntry Close the SP of the entry
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID UAPSD_SP_Close(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ if ((pEntry != NULL) && (pEntry->PsMode == PWR_SAVE))
+ {
+ RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock);
+
+ if (pEntry->bAPSDFlagSPStart != 0)
+ {
+ /* SP is started for the station */
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> [3] close SP!\n"));
+#endif /* UAPSD_DEBUG */
+
+ if (pEntry->pUAPSDEOSPFrame != NULL)
+ {
+ /*
+ SP will be closed, should not have EOSP frame
+ if exists, release it
+ */
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> [3] Free EOSP (UP = %d)!\n",
+ RTMP_GET_PACKET_UP(
+ QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame))));
+#endif /* UAPSD_DEBUG */
+
+ RELEASE_NDIS_PACKET(pAd,
+ QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame),
+ NDIS_STATUS_FAILURE);
+ pEntry->pUAPSDEOSPFrame = NULL;
+ } /* End of if */
+
+ /* re-init SP related parameters */
+ pEntry->UAPSDTxNum = 0;
+ //pEntry->bAPSDFlagSPStart = 0;
+ pEntry->bAPSDFlagEOSPOK = 0;
+ pEntry->bAPSDFlagLegacySent = 0;
+ UAPSD_SP_END(pAd, pEntry);
+
+#ifdef RTMP_MAC_USB
+ pEntry->UAPSDTagOffset[QID_AC_BE] = 0;
+ pEntry->UAPSDTagOffset[QID_AC_BK] = 0;
+ pEntry->UAPSDTagOffset[QID_AC_VI] = 0;
+ pEntry->UAPSDTagOffset[QID_AC_VO] = 0;
+#endif /* RTMP_MAC_USB */
+ } /* End of if */
+
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+ } /* End of if */
+} /* End of UAPSD_SP_Close */
+
+/*
+========================================================================
+Routine Description:
+ Check if the SP for entry is closed.
+
+Arguments:
+ pAd Pointer to our adapter
+ pEntry the peer entry
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+BOOLEAN UAPSD_SP_IsClosed(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ BOOLEAN FlgIsSpClosed = TRUE;
+
+
+ RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock);
+ if ((pEntry != NULL) && (pEntry->PsMode == PWR_SAVE))
+ {
+ if (pEntry->bAPSDFlagSPStart != 0)
+ FlgIsSpClosed = FALSE;
+ }
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+
+ return FlgIsSpClosed;
+}
+
+/*
+========================================================================
+Routine Description:
+ Deliver all queued packets.
+
+Arguments:
+ pAd Pointer to our adapter
+ *pEntry STATION
+
+Return Value:
+ None
+
+Note:
+ SMP protection by caller for packet enqueue.
+========================================================================
+*/
+VOID UAPSD_AllPacketDeliver(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ QUEUE_HEADER *pQueApsd;
+ PQUEUE_ENTRY pQueEntry;
+ UCHAR QueIdList[WMM_NUM_OF_AC] = { QID_AC_BE, QID_AC_BK,
+ QID_AC_VI, QID_AC_VO };
+ INT32 IdAc, QueId; /* must be signed, can not be unsigned */
+
+
+ RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock);
+
+ /* check if the EOSP frame is yet transmitted out */
+ if (pEntry->pUAPSDEOSPFrame != NULL)
+ {
+ /* queue the EOSP frame to SW queue to be transmitted */
+ QueId = RTMP_GET_PACKET_UAPSD_QUE_ID(
+ QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame));
+
+ if (QueId > QID_AC_VO)
+ {
+ /* should not be here, only for sanity */
+ QueId = QID_AC_BE;
+ } /* End of if */
+
+ UAPSD_INSERT_QUEUE_AC(pAd, pEntry, &pAd->TxSwQueue[QueId],
+ pEntry->pUAPSDEOSPFrame);
+
+ pEntry->pUAPSDEOSPFrame = NULL;
+ pEntry->UAPSDTxNum = 0;
+ } /* End of if */
+
+ /* deliver ALL U-APSD packets from AC3 to AC0 (AC0 to AC3 is also ok) */
+ for(IdAc=(WMM_NUM_OF_AC-1); IdAc>=0; IdAc--)
+ {
+ pQueApsd = &(pEntry->UAPSDQueue[IdAc]);
+ QueId = QueIdList[IdAc];
+
+ while(pQueApsd->Head)
+ {
+ pQueEntry = RemoveHeadQueue(pQueApsd);
+ UAPSD_INSERT_QUEUE_AC(pAd, pEntry, &pAd->TxSwQueue[QueId], pQueEntry);
+ } /* End of while */
+ } /* End of for */
+
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+} /* End of UAPSD_AllPacketDeliver */
+
+
+/*
+========================================================================
+Routine Description:
+ Parse the UAPSD field in WMM element in (re)association request frame.
+
+Arguments:
+ pAd Pointer to our adapter
+ *pEntry STATION
+ *pElm QoS information field
+ FlgApsdCapable TRUE: Support UAPSD
+
+Return Value:
+ None
+
+Note:
+ No protection is needed.
+
+ 1. Association -> TSPEC:
+ use static UAPSD settings in Association
+ update UAPSD settings in TSPEC
+
+ 2. Association -> TSPEC(11r) -> Reassociation:
+ update UAPSD settings in TSPEC
+ backup static UAPSD settings in Reassociation
+
+ 3. Association -> Reassociation:
+ update UAPSD settings in TSPEC
+ backup static UAPSD settings in Reassociation
+========================================================================
+*/
+VOID UAPSD_AssocParse(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN UCHAR *pElm,
+ IN BOOLEAN FlgApsdCapable)
+{
+ PQBSS_STA_INFO_PARM pQosInfo;
+ UCHAR UAPSD[4];
+ UINT32 IdApsd;
+
+
+ /* check if the station enables UAPSD function */
+ if ((pEntry) && (FlgApsdCapable == TRUE))
+ {
+ /* backup its UAPSD parameters */
+ pQosInfo = (PQBSS_STA_INFO_PARM) pElm;
+
+
+ UAPSD[QID_AC_BE] = pQosInfo->UAPSD_AC_BE;
+ UAPSD[QID_AC_BK] = pQosInfo->UAPSD_AC_BK;
+ UAPSD[QID_AC_VI] = pQosInfo->UAPSD_AC_VI;
+ UAPSD[QID_AC_VO] = pQosInfo->UAPSD_AC_VO;
+
+ pEntry->MaxSPLength = pQosInfo->MaxSPLength;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("apsd> UAPSD %d %d %d %d!\n",
+ pQosInfo->UAPSD_AC_BE, pQosInfo->UAPSD_AC_BK,
+ pQosInfo->UAPSD_AC_VI, pQosInfo->UAPSD_AC_VO));
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("apsd> MaxSPLength = %d\n", pEntry->MaxSPLength));
+
+ /* use static UAPSD setting of association request frame */
+ for(IdApsd=0; IdApsd<4; IdApsd++)
+ {
+ pEntry->bAPSDCapablePerAC[IdApsd] = UAPSD[IdApsd];
+ pEntry->bAPSDDeliverEnabledPerAC[IdApsd] = UAPSD[IdApsd];
+
+ } /* End of for */
+
+ if ((pEntry->bAPSDCapablePerAC[QID_AC_BE] == 0) &&
+ (pEntry->bAPSDCapablePerAC[QID_AC_BK] == 0) &&
+ (pEntry->bAPSDCapablePerAC[QID_AC_VI] == 0) &&
+ (pEntry->bAPSDCapablePerAC[QID_AC_VO] == 0))
+ {
+ CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_APSD_CAPABLE);
+ }
+ else
+ {
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_APSD_CAPABLE);
+ } /* End of if */
+
+ if ((pEntry->bAPSDCapablePerAC[QID_AC_BE] == 1) &&
+ (pEntry->bAPSDCapablePerAC[QID_AC_BK] == 1) &&
+ (pEntry->bAPSDCapablePerAC[QID_AC_VI] == 1) &&
+ (pEntry->bAPSDCapablePerAC[QID_AC_VO] == 1))
+ {
+ /* all AC are U-APSD */
+ DBGPRINT(RT_DEBUG_TRACE, ("apsd> all AC are UAPSD\n"));
+ pEntry->bAPSDAllAC = 1;
+ }
+ else
+ {
+ /* at least one AC is not U-APSD */
+ DBGPRINT(RT_DEBUG_TRACE, ("apsd> at least one AC is not UAPSD %d %d %d %d\n",
+ pEntry->bAPSDCapablePerAC[QID_AC_BE],
+ pEntry->bAPSDCapablePerAC[QID_AC_BK],
+ pEntry->bAPSDCapablePerAC[QID_AC_VI],
+ pEntry->bAPSDCapablePerAC[QID_AC_VO]));
+ pEntry->bAPSDAllAC = 0;
+ } /* End of if */
+
+ pEntry->VirtualTimeout = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("apsd> MaxSPLength = %d\n", pEntry->MaxSPLength));
+ } /* End of if */
+} /* End of UAPSD_AssocParse */
+
+
+/*
+========================================================================
+Routine Description:
+ Enqueue a UAPSD packet.
+
+Arguments:
+ pAd Pointer to our adapter
+ *pEntry STATION
+ pPacket UAPSD dnlink packet
+ IdAc UAPSD AC ID (0 ~ 3)
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID UAPSD_PacketEnqueue(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN PNDIS_PACKET pPacket,
+ IN UINT32 IdAc)
+{
+ /*
+ 1. the STATION is UAPSD STATION;
+ 2. AC ID is legal;
+ 3. the AC is UAPSD AC.
+ so we queue the packet to its UAPSD queue
+ */
+
+ /* [0] ~ [3], QueIdx base is QID_AC_BE */
+ QUEUE_HEADER *pQueUapsd;
+
+
+ /* check if current queued UAPSD packet number is too much */
+ if (pEntry == NULL)
+ {
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> pEntry == NULL!\n"));
+ return;
+ } /* End of if */
+
+ pQueUapsd = &(pEntry->UAPSDQueue[IdAc]);
+
+ if (pQueUapsd->Number >= MAX_PACKETS_IN_UAPSD_QUEUE)
+ {
+ /* too much queued pkts, free (discard) the tx packet */
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("uapsd> many(%ld) WCID(%d) AC(%d)\n",
+ pQueUapsd->Number,
+ RTMP_GET_PACKET_WCID(pPacket),
+ IdAc));
+
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ }
+ else
+ {
+ /* queue the tx packet to the U-APSD queue of the AC */
+ RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock);
+ InsertTailQueue(pQueUapsd, PACKET_TO_QUEUE_ENTRY(pPacket));
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+
+#ifdef UAPSD_DEBUG
+ if (RTMP_GET_PACKET_MGMT_PKT(pPacket) == 1)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ps> mgmt to uapsd queue...\n"));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("ps> data (0x%08lx) (AC%d) to uapsd queue (num of pkt = %ld)...\n",
+ (ULONG)pPacket, IdAc,
+ pQueUapsd->Number));
+ } /* End of if */
+#endif /* UAPSD_DEBUG */
+ } /* End of if */
+} /* End of UAPSD_PacketEnqueue */
+
+
+
+/*
+========================================================================
+Routine Description:
+ Maintenance our UAPSD PS queue. Release all queued packet if timeout.
+
+Arguments:
+ pAd Pointer to our adapter
+ *pEntry STATION
+
+Return Value:
+ None
+
+Note:
+ If in RT2870, pEntry can not be removed during UAPSD_QueueMaintenance()
+========================================================================
+*/
+VOID UAPSD_QueueMaintenance(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ QUEUE_HEADER *pQue;
+ UINT32 IdAc;
+ BOOLEAN FlgUapsdPkt, FlgEospPkt;
+#ifdef RTMP_MAC_USB
+ ULONG IrqFlags;
+#endif /* RTMP_MAC_USB */
+
+
+ /* sanity check */
+ if (gUAPSD_FlgNotQueueMaintain)
+ return;
+ /* End of if */
+
+ if (pEntry->PsMode != PWR_SAVE)
+ return; /* UAPSD packet only for power-save STA, not active STA */
+ /* End of if */
+
+ /* init */
+ RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock);
+
+ pQue = pEntry->UAPSDQueue;
+ FlgUapsdPkt = 0;
+ FlgEospPkt = 0;
+
+ /* check if more than one U-APSD packets exists */
+ for(IdAc=0; IdAc<WMM_NUM_OF_AC; IdAc++)
+ {
+ if (pQue[IdAc].Head != NULL)
+ {
+ /*
+ At least one U-APSD packets exists so we need to check if
+ queued U-APSD packets are timeout.
+ */
+ FlgUapsdPkt = 1;
+ break;
+ } /* End of if */
+ } /* End of for */
+
+ if (pEntry->pUAPSDEOSPFrame != NULL)
+ FlgEospPkt = 1;
+ /* End of if */
+
+ /* check if any queued UAPSD packet exists */
+ if (FlgUapsdPkt || FlgEospPkt)
+ {
+#ifdef RTMP_MAC_USB
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+#endif /* RTMP_MAC_USB */
+
+ pEntry->UAPSDQIdleCount ++;
+
+ if (pEntry->UAPSDQIdleCount > pAd->MacTab.MsduLifeTime)
+ {
+ if (FlgUapsdPkt)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("uapsd> UAPSD queue timeout! clean all queued frames...\n"));
+ } /* End of if */
+
+ if (FlgEospPkt)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("uapsd> UAPSD EOSP timeout! clean the EOSP frame!\n"));
+ } /* End of if */
+
+ /* UAPSDQIdleCount will be 0 after trigger frame is received */
+
+ /* clear all U-APSD packets */
+ if (FlgUapsdPkt)
+ {
+ for(IdAc=0; IdAc<WMM_NUM_OF_AC; IdAc++)
+ RtmpCleanupPsQueue(pAd, &pQue[IdAc]);
+ /* End of for */
+ } /* End of if */
+
+ /* free the EOSP frame */
+ pEntry->UAPSDTxNum = 0;
+
+ if (pEntry->pUAPSDEOSPFrame != NULL)
+ {
+ RELEASE_NDIS_PACKET(pAd,
+ QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame),
+ NDIS_STATUS_FAILURE);
+ pEntry->pUAPSDEOSPFrame = NULL;
+ } /* End of if */
+
+ pEntry->bAPSDFlagEOSPOK = 0;
+ //pEntry->bAPSDFlagSPStart = 0;
+ pEntry->bAPSDFlagLegacySent = 0;
+ UAPSD_SP_END(pAd, pEntry);
+
+ /* clear idle counter */
+ pEntry->UAPSDQIdleCount = 0;
+
+#ifdef CONFIG_AP_SUPPORT
+ /* check TIM bit */
+ if (pEntry->PsQueue.Number == 0)
+ {
+ WLAN_MR_TIM_BIT_CLEAR(pAd, pEntry->apidx, pEntry->Aid);
+ } /* End of if */
+#endif /* CONFIG_AP_SUPPORT */
+ } /* End of if */
+
+#ifdef RTMP_MAC_USB
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+#endif /* RTMP_MAC_USB */
+ }
+ else
+ {
+ /* clear idle counter */
+ pEntry->UAPSDQIdleCount = 0;
+ } /* End of if (FlgUapsdPkt) */
+
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+
+ /* virtual timeout handle */
+ RTMP_PS_VIRTUAL_TIMEOUT_HANDLE(pEntry);
+} /* End of UAPSD_QueueMaintenance */
+
+
+/*
+========================================================================
+Routine Description:
+ Close SP in Tx Done, not Tx DMA Done.
+
+Arguments:
+ pAd Pointer to our adapter
+ pEntry destination entry
+ FlgSuccess 0:tx success, 1:tx fail
+
+Return Value:
+ None
+
+Note:
+ For RT28xx series, for packetID=0 or multicast frame, no statistics
+ count can be got, ex: ARP response or DHCP packets, we will use
+ low rate to set (CCK, MCS=0=packetID).
+ So SP will not be close until UAPSD_EPT_SP_INT timeout.
+
+ So if the tx rate is 1Mbps for a entry, we will use DMA done, not
+ use UAPSD_SP_AUE_Handle().
+========================================================================
+*/
+VOID UAPSD_SP_AUE_Handle(
+ IN RTMP_ADAPTER *pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN UCHAR FlgSuccess)
+{
+#ifdef UAPSD_SP_ACCURATE
+ USHORT QueId;
+
+
+ if (pEntry == NULL)
+ return;
+ /* End of if */
+
+ if (pEntry->PsMode == PWR_ACTIVE)
+ {
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: Station actives! Close SP!\n"));
+#endif /* UAPSD_DEBUG */
+ //pEntry->bAPSDFlagSPStart = 0;
+ pEntry->bAPSDFlagEOSPOK = 0;
+ UAPSD_SP_END(pAd, pEntry);
+ return;
+ } /* End of if */
+
+ if (pEntry->PsMode == PWR_SAVE)
+ {
+ BOOLEAN FlgEosp;
+
+
+ RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock);
+
+ if (pEntry->bAPSDFlagSpRoughUse != 0)
+ {
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+ return; /* use DMA mechanism, not statistics count mechanism */
+ } /* End of if */
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: Tx Num = %d\n", pEntry->UAPSDTxNum));
+#endif /* UAPSD_DEBUG */
+
+ FlgEosp = FALSE;
+
+ if (pEntry->bAPSDFlagSPStart == 0)
+ {
+ /*
+ When SP is not started, all packets are from legacy PS queue.
+ One downlink packet for one PS-Poll packet.
+ */
+ pEntry->bAPSDFlagLegacySent = 0;
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> legacy PS packet is sent!\n"));
+#endif /* UAPSD_DEBUG */
+ }
+ else
+ {
+#ifdef UAPSD_TIMING_RECORD_FUNC
+ UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_TX2AIR);
+#endif /* UAPSD_TIMING_RECORD_FUNC */
+ } /* End of if */
+
+ /* record current time */
+ UAPSD_TIME_GET(pAd, pEntry->UAPSDTimeStampLast);
+
+ /* Note: UAPSDTxNum does NOT include the EOSP packet */
+ if (pEntry->UAPSDTxNum > 0)
+ {
+ /* some UAPSD packets are not yet transmitted */
+
+ if (pEntry->UAPSDTxNum == 1)
+ {
+ /* this is the last UAPSD packet */
+ if (pEntry->pUAPSDEOSPFrame != NULL)
+ {
+ /* transmit the EOSP frame */
+ PNDIS_PACKET pPkt;
+
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: send EOSP frame...\n"));
+#endif /* UAPSD_DEBUG */
+
+ pPkt = QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame);
+ QueId = RTMP_GET_PACKET_UAPSD_QUE_ID(pPkt);
+
+ if (QueId > QID_AC_VO)
+ {
+ /* should not be here, only for sanity */
+ QueId = QID_AC_BE;
+ } /* End of if */
+
+ UAPSD_INSERT_QUEUE_AC(pAd, pEntry, &pAd->TxSwQueue[QueId],
+ pEntry->pUAPSDEOSPFrame);
+
+ pEntry->pUAPSDEOSPFrame = NULL;
+ FlgEosp = TRUE;
+ } /* End of if */
+ } /* End of if */
+
+ /* a UAPSD frame is transmitted so decrease the counter */
+ pEntry->UAPSDTxNum --;
+
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+
+ /* maybe transmit the EOSP frame */
+ if (FlgEosp == TRUE)
+ {
+ POS_COOKIE pCookie;
+
+ pCookie = (POS_COOKIE) pAd->OS_Cookie;
+
+ /*
+ Too many functions call NICUpdateFifoStaCounters() and
+ NICUpdateFifoStaCounters() will call UAPSD_SP_AUE_Handle(),
+ if we call RTMPDeQueuePacket() here, double-IRQ LOCK will
+ occur. so we need to activate a tasklet to send EOSP frame.
+
+ ex: RTMPDeQueuePacket() --> RTMPFreeTXDUponTxDmaDone() -->
+ NICUpdateFifoStaCounters() --> UAPSD_SP_AUE_Handle() -->
+ RTMPDeQueuePacket() ERROR! or
+
+ RTMPHandleTxRingDmaDoneInterrupt() -->
+ RTMP_IRQ_LOCK() -->
+ RTMPFreeTXDUponTxDmaDone() -->
+ NICUpdateFifoStaCounters() -->
+ UAPSD_SP_AUE_Handle() -->
+ RTMPDeQueuePacket() -->
+ DEQUEUE_LOCK() -->
+ RTMP_IRQ_LOCK() ERROR!
+ */
+ RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_task);
+ }
+ /* must return here; Or double unlock UAPSDEOSPLock */
+ return;
+ }
+ else
+ {
+ /* UAPSDTxNum == 0 so the packet is the EOSP packet */
+
+ if (pAd->bAPSDFlagSPSuspend == 1)
+ {
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: SP is suspend, keep SP if exists!\n"));
+#endif /* UAPSD_DEBUG */
+
+ /* keep SP, not to close SP */
+ pEntry->bAPSDFlagEOSPOK = 1;
+ }
+
+ if ((pEntry->bAPSDFlagSPStart != 0) &&
+ (pAd->bAPSDFlagSPSuspend == 0))
+ {
+ //pEntry->bAPSDFlagSPStart = 0;
+ pEntry->bAPSDFlagEOSPOK = 0;
+ UAPSD_SP_END(pAd, pEntry);
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: close a SP.\n\n\n"));
+#endif /* UAPSD_DEBUG */
+ }
+ }
+
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+ }
+#endif /* UAPSD_SP_ACCURATE */
+}
+
+
+
+/*
+========================================================================
+Routine Description:
+ Close current Service Period.
+
+Arguments:
+ pAd Pointer to our adapter
+
+Return Value:
+ None
+
+Note:
+ When we receive EOSP frame tx done interrupt and a uplink packet
+ from the station simultaneously, we will regard it as a new trigger
+ frame because the packet is received when EOSP frame tx done interrupt.
+
+ We can not sure the uplink packet is sent after old SP or in the old SP.
+ So we must close the old SP in receive done ISR to avoid the problem.
+========================================================================
+*/
+VOID UAPSD_SP_CloseInRVDone(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 IdEntry;
+ int FirstWcid = 0;
+
+
+ if (pAd->MacTab.fAnyStationInPsm == FALSE)
+ return; /* no any station is in power save mode */
+ /* End of if */
+
+
+ /* check for all CLIENT's UAPSD Service Period */
+ for(IdEntry = FirstWcid; IdEntry < MAX_LEN_OF_MAC_TABLE; IdEntry++)
+ {
+ MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[IdEntry];
+
+
+ RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock);
+
+ /* check if SP is started and EOSP is transmitted ok */
+ if ((pEntry->bAPSDFlagSPStart != 0) &&
+ (pEntry->bAPSDFlagEOSPOK != 0))
+ {
+ /*
+ 1. SP is started;
+ 2. EOSP frame is sent ok.
+ */
+
+ /*
+ We close current SP for the STATION so we can receive new
+ trigger frame from the STATION again.
+ */
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE,("uapsd> close SP in UAPSD_SP_CloseInRVDone()!\n\n\n"));
+#endif /* UAPSD_DEBUG */
+
+ //pEntry->bAPSDFlagSPStart = 0;
+ pEntry->bAPSDFlagEOSPOK = 0;
+ pEntry->bAPSDFlagLegacySent = 0;
+ UAPSD_SP_END(pAd, pEntry);
+ } /* End of if */
+
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+ } /* End of for */
+} /* End of UAPSD_SP_CloseInRVDone */
+
+
+
+
+#ifdef UAPSD_TIMING_RECORD_FUNC
+/*
+========================================================================
+Routine Description:
+ Enable/Disable Timing Record Function.
+
+Arguments:
+ pAd Pointer to our adapter
+ Flag 1 (Enable) or 0 (Disable)
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID UAPSD_TimingRecordCtrl(
+ IN UINT32 Flag)
+{
+ if (gUAPSD_TimingFlag == UAPSD_TIMING_CTRL_SUSPEND)
+ return;
+ /* End of if */
+
+ gUAPSD_TimingFlag = Flag;
+} /* End of UAPSD_TimingRecordCtrl */
+
+
+/*
+========================================================================
+Routine Description:
+ Record some timings.
+
+Arguments:
+ pAd Pointer to our adapter
+ Type The timing is for what type
+
+Return Value:
+ None
+
+Note:
+ UAPSD_TIMING_RECORD_ISR
+ UAPSD_TIMING_RECORD_TASKLET
+ UAPSD_TIMING_RECORD_TRG_RCV
+ UAPSD_TIMING_RECORD_MOVE2TX
+ UAPSD_TIMING_RECORD_TX2AIR
+========================================================================
+*/
+VOID UAPSD_TimingRecord(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT32 Type)
+{
+ UINT32 Index;
+
+ if (gUAPSD_TimingFlag == UAPSD_TIMING_CTRL_STOP)
+ return;
+ /* End of if */
+
+ if ((gUAPSD_TimingFlag == UAPSD_TIMING_CTRL_SUSPEND) &&
+ (Type != UAPSD_TIMING_RECORD_TX2AIR))
+ {
+ return;
+ } /* End of if */
+
+ Index = gUAPSD_TimingIndexUapsd;
+
+ switch(Type)
+ {
+ case UAPSD_TIMING_RECORD_ISR:
+ /* start to record the timing */
+ UAPSD_TIMESTAMP_GET(pAd, gUAPSD_TimingIsr[Index]);
+ break;
+
+ case UAPSD_TIMING_RECORD_TASKLET:
+ UAPSD_TIMESTAMP_GET(pAd, gUAPSD_TimingTasklet[Index]);
+ break;
+
+ case UAPSD_TIMING_RECORD_TRG_RCV:
+ if (gUAPSD_TimingLoopIndex == 0)
+ {
+ /*
+ The trigger frame is the first received frame.
+ The received time will be the time recorded in ISR.
+ */
+ gUAPSD_TimingTrgRcv[Index] = gUAPSD_TimingIsr[Index];
+ }
+ else
+ {
+ /*
+ Some packets are handled before the trigger frame so
+ we record next one.
+ */
+ UAPSD_TIMING_RECORD_STOP();
+ } /* End of if */
+ break;
+
+ case UAPSD_TIMING_RECORD_MOVE2TX:
+ UAPSD_TIMESTAMP_GET(pAd, gUAPSD_TimingMov2Tx[Index]);
+
+ /* prepare to wait for tx done */
+ UAPSD_TimingRecordCtrl(UAPSD_TIMING_CTRL_SUSPEND);
+ break;
+
+ case UAPSD_TIMING_RECORD_TX2AIR:
+ UAPSD_TIMESTAMP_GET(pAd, gUAPSD_TimingTx2Air[Index]);
+
+ /* sum the delay */
+ gUAPSD_TimingSumIsr2Tasklet += \
+ (UINT32)(gUAPSD_TimingTasklet[Index] - gUAPSD_TimingIsr[Index]);
+ gUAPSD_TimingSumTrig2Txqueue += \
+ (UINT32)(gUAPSD_TimingMov2Tx[Index] - gUAPSD_TimingTrgRcv[Index]);
+ gUAPSD_TimingSumTxqueue2Air += \
+ (UINT32)(gUAPSD_TimingTx2Air[Index] - gUAPSD_TimingMov2Tx[Index]);
+
+ /* display average delay */
+ if ((Index % UAPSD_TIMING_RECORD_DISPLAY_TIMES) == 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> Isr2Tasklet=%d, Trig2Queue=%d, Queue2Air=%d micro seconds\n",
+ gUAPSD_TimingSumIsr2Tasklet/
+ UAPSD_TIMING_RECORD_DISPLAY_TIMES,
+ gUAPSD_TimingSumTrig2Txqueue/
+ UAPSD_TIMING_RECORD_DISPLAY_TIMES,
+ gUAPSD_TimingSumTxqueue2Air/
+ UAPSD_TIMING_RECORD_DISPLAY_TIMES));
+ gUAPSD_TimingSumIsr2Tasklet = 0;
+ gUAPSD_TimingSumTrig2Txqueue = 0;
+ gUAPSD_TimingSumTxqueue2Air = 0;
+ } /* End of if */
+
+ /* ok, a record is finished; prepare to record the next one */
+ gUAPSD_TimingIndexUapsd ++;
+
+ if (gUAPSD_TimingIndexUapsd >= UAPSD_TIMING_RECORD_MAX)
+ gUAPSD_TimingIndexUapsd = 0;
+ /* End of if */
+
+ /* stop the record */
+ gUAPSD_TimingFlag = UAPSD_TIMING_CTRL_STOP;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("sam> Isr->Tasklet:%d, Trig->TxQueue:%d, TxQueue->TxDone:%d\n",
+ (UINT32)(gUAPSD_TimingTasklet[Index] - gUAPSD_TimingIsr[Index]),
+ (UINT32)(gUAPSD_TimingMov2Tx[Index] - gUAPSD_TimingTrgRcv[Index]),
+ (UINT32)(gUAPSD_TimingTx2Air[Index] - gUAPSD_TimingMov2Tx[Index])));
+ break;
+ } /* End of switch */
+} /* End of UAPSD_TimingRecord */
+
+
+/*
+========================================================================
+Routine Description:
+ Record the loop index for received packet handle.
+
+Arguments:
+ pAd Pointer to our adapter
+ LoopIndex The RxProcessed in APRxDoneInterruptHandle()
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID UAPSD_TimeingRecordLoopIndex(
+ IN UINT32 LoopIndex)
+{
+ gUAPSD_TimingLoopIndex = LoopIndex;
+} /* End of UAPSD_TimeingRecordLoopIndex */
+
+#endif /* UAPSD_TIMING_RECORD_FUNC */
+
+
+/*
+========================================================================
+Routine Description:
+ Handle PS-Poll Frame.
+
+Arguments:
+ pAd Pointer to our adapter
+ *pEntry the source STATION
+
+Return Value:
+ TRUE Handle OK
+ FALSE Handle FAIL
+
+Note:
+========================================================================
+*/
+BOOLEAN UAPSD_PsPollHandle(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ QUEUE_HEADER *pAcPsQue;
+ QUEUE_HEADER *pAcSwQue;
+ PQUEUE_ENTRY pQuedEntry;
+ PNDIS_PACKET pQuedPkt;
+ UINT32 AcQueId;
+ /*
+ AC ID = VO > VI > BK > BE
+ so we need to change BE & BK
+ => AC priority = VO > VI > BE > BK
+ */
+ UINT32 AcPriority[WMM_NUM_OF_AC] = { 1, 0, 2, 3 };
+ UCHAR QueIdList[WMM_NUM_OF_AC] = { QID_AC_BE, QID_AC_BK,
+ QID_AC_VI, QID_AC_VO };
+ BOOLEAN FlgQueEmpty;
+ INT32 IdAc; /* must be signed, can not use unsigned */
+ UINT32 Aid, QueId;
+
+
+ /* sanity check */
+ if (pEntry == NULL)
+ return FALSE; /* fatal error */
+ /* End of if */
+
+ /* init */
+ FlgQueEmpty = TRUE;
+ pAcSwQue = NULL;
+ pQuedPkt = NULL;
+
+ /* sanity check */
+ RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock);
+
+ if (pEntry->bAPSDAllAC == 0)
+ {
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+ return FALSE; /* not all AC are delivery-enabled */
+ } /* End of if */
+
+ if (pEntry->bAPSDFlagSPStart != 0)
+ {
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+ return FALSE; /* its service period is not yet ended */
+ } /* End of if */
+
+ /* from highest priority AC3 --> AC2 --> AC0 --> lowest priority AC1 */
+ for (IdAc=(WMM_NUM_OF_AC-1); IdAc>=0; IdAc--)
+ {
+ AcQueId = AcPriority[IdAc];
+
+ /*
+ NOTE: get U-APSD queue pointer here to speed up, do NOT use
+ pEntry->UAPSDQueue[AcQueId] throughout codes because
+ compiler will compile it to many assembly codes.
+ */
+ pAcPsQue = &pEntry->UAPSDQueue[AcQueId];
+
+ /* check if any U-APSD packet is queued for the AC */
+ if (pAcPsQue->Head == NULL)
+ continue;
+ /* End of if */
+
+ /* at least one U-APSD packet exists here */
+
+ /* put U-APSD packets to the AC software queue */
+ if ((pAcPsQue->Head != NULL) && (pQuedPkt == NULL))
+ {
+ /* get AC software queue */
+ QueId = QueIdList[AcQueId];
+ pAcSwQue = &pAd->TxSwQueue[QueId];
+
+ /* get the U-APSD packet */
+ pQuedEntry = RemoveHeadQueue(pAcPsQue);
+ pQuedPkt = QUEUE_ENTRY_TO_PACKET(pQuedEntry);
+
+ if (pQuedPkt != NULL)
+ {
+ /*
+ WMM Specification V1.1 3.6.1.7
+ The More Data bit (b13) of the directed MSDU or MMPDU
+ associated with delivery-enabled ACs and destined for
+ that WMM STA indicates that more frames are buffered for
+ the delivery-enabled ACs.
+ */
+ RTMP_SET_PACKET_MOREDATA(pQuedPkt, TRUE);
+
+ /* set U-APSD flag & its software queue ID */
+ RTMP_SET_PACKET_UAPSD(pQuedPkt, TRUE, QueId);
+ } /* End of if */
+ } /* End of while */
+
+ if (pAcPsQue->Head != NULL)
+ {
+ /* still have packets in queue */
+ FlgQueEmpty = FALSE;
+ break;
+ } /* End of if */
+ } /* End of for */
+
+ if (pQuedPkt != NULL)
+ {
+ if (FlgQueEmpty == TRUE)
+ {
+ /*
+ No any more queued U-APSD packet so clear More Data bit of
+ the last frame.
+ */
+ RTMP_SET_PACKET_MOREDATA(pQuedPkt, FALSE);
+ } /* End of if */
+
+ UAPSD_INSERT_QUEUE_AC(pAd, pEntry, pAcSwQue, pQuedPkt);
+ } /* End of if */
+
+ /* clear corresponding TIM bit */
+
+ /* get its AID for the station */
+ Aid = pEntry->Aid;
+
+ if ((pEntry->bAPSDAllAC == 1) && (FlgQueEmpty == TRUE))
+ {
+ /* all AC are U-APSD and no any U-APSD packet is queued, set TIM */
+
+#ifdef CONFIG_AP_SUPPORT
+ /* clear TIM bit */
+ if ((Aid > 0) && (Aid < MAX_LEN_OF_MAC_TABLE))
+ {
+ WLAN_MR_TIM_BIT_CLEAR(pAd, pEntry->apidx, Aid);
+ } /* End of if */
+#endif /* CONFIG_AP_SUPPORT */
+ } /* End of if */
+
+ /* reset idle timeout here whenever a trigger frame is received */
+ pEntry->UAPSDQIdleCount = 0;
+
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+
+ /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it */
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+ return TRUE;
+}
+
+/*
+========================================================================
+Routine Description:
+ Get the queue status for delivery-enabled AC.
+
+Arguments:
+ pAd Pointer to our adapter
+ pEntry the peer entry
+ pFlgIsAnyPktForBK TRUE: At lease a BK packet is queued
+ pFlgIsAnyPktForBE TRUE: At lease a BE packet is queued
+ pFlgIsAnyPktForVI TRUE: At lease a VI packet is queued
+ pFlgIsAnyPktForVO TRUE: At lease a VO packet is queued
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID UAPSD_QueueStatusGet(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ OUT BOOLEAN *pFlgIsAnyPktForBK,
+ OUT BOOLEAN *pFlgIsAnyPktForBE,
+ OUT BOOLEAN *pFlgIsAnyPktForVI,
+ OUT BOOLEAN *pFlgIsAnyPktForVO)
+{
+ /* init */
+ *pFlgIsAnyPktForBK = FALSE;
+ *pFlgIsAnyPktForBE = FALSE;
+ *pFlgIsAnyPktForVI = FALSE;
+ *pFlgIsAnyPktForVO = FALSE;
+
+ /* sanity check */
+ if (pEntry == NULL)
+ return;
+
+ /* get queue status */
+ RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock);
+ if (pEntry->UAPSDQueue[QID_AC_BK].Head != NULL)
+ *pFlgIsAnyPktForBK = TRUE;
+ if (pEntry->UAPSDQueue[QID_AC_BE].Head != NULL)
+ *pFlgIsAnyPktForBE = TRUE;
+ if (pEntry->UAPSDQueue[QID_AC_VI].Head != NULL)
+ *pFlgIsAnyPktForVI = TRUE;
+ if (pEntry->UAPSDQueue[QID_AC_VO].Head != NULL)
+ *pFlgIsAnyPktForVO = TRUE;
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+}
+
+/*
+========================================================================
+Routine Description:
+ Handle UAPSD Trigger Frame.
+
+Arguments:
+ pAd Pointer to our adapter
+ *pEntry the source STATION
+ UpOfFrame the UP of the trigger frame
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID UAPSD_TriggerFrameHandle(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN UCHAR UpOfFrame)
+{
+ QUEUE_HEADER *pAcPsQue;
+ QUEUE_HEADER *pAcSwQue, *pLastAcSwQue;
+ PQUEUE_ENTRY pQuedEntry;
+ PNDIS_PACKET pQuedPkt;
+
+ UINT32 AcQueId;
+ UINT32 TxPktNum, SpMaxLen;
+ /*
+ AC ID = VO > VI > BK > BE
+ so we need to change BE & BK
+ => AC priority = VO > VI > BE > BK
+ */
+ UINT32 AcPriority[WMM_NUM_OF_AC] = { 1, 0, 2, 3 };
+ /* 0: deliver all U-APSD packets */
+ UINT32 SpLenMap[WMM_NUM_OF_AC] = { 0, 2, 4, 6 };
+ UCHAR QueIdList[WMM_NUM_OF_AC] = { QID_AC_BE, QID_AC_BK,
+ QID_AC_VI, QID_AC_VO };
+ BOOLEAN FlgQueEmpty;
+ BOOLEAN FlgNullSnd;
+ BOOLEAN FlgMgmtFrame;
+ UINT32 Aid, QueId;
+ INT32 IdAc; /* must be signed, can not use unsigned */
+/* ULONG FlgIrq; */
+
+#ifdef UAPSD_SP_ACCURATE
+ ULONG TimeNow;
+#endif /* UAPSD_SP_ACCURATE */
+
+
+ /* sanity check for Service Period of the STATION */
+ RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock);
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("\nuapsd> bAPSDFlagLegacySent = %d!\n",
+ pEntry->bAPSDFlagLegacySent));
+#endif /* UAPSD_DEBUG */
+
+ if (pEntry->bAPSDFlagSPStart != 0)
+ {
+ /*
+ reset ContinueTxFailCnt
+ */
+ pEntry->ContinueTxFailCnt = 0;
+
+ /*
+ WMM Specification V1.1 3.6.1.5
+ A Trigger Frame received by the WMM AP from a WMM STA that
+ already has an USP underway shall not trigger the start of a new
+ USP.
+ */
+
+ /*
+ Current SP for the STATION is not yet ended so the packet is
+ normal DATA packet.
+ */
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> sorry! SP is not yet closed!\n"));
+#endif /* UAPSD_DEBUG */
+
+#ifdef UAPSD_SP_ACCURATE
+ /*
+ The interval between the data frame from QSTA and last confirmed
+ packet from QAP in UAPSD_SP_AUE_Handle() is too large so maybe
+ we suffer the worse case.
+
+ Currently, if we send any packet with 1Mbps in 2.4GHz and 6Mbps
+ in 5GHz, no any statistics count for the packet so the SP can
+ not be closed.
+ */
+ UAPSD_TIME_GET(pAd, TimeNow);
+
+ if ((TimeNow - pEntry->UAPSDTimeStampLast) >= UAPSD_EPT_SP_INT)
+ {
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> SP period is too large so SP is closed first!"
+ " (%lu %lu %lu)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",
+ TimeNow, pEntry->UAPSDTimeStampLast,
+ (TimeNow - pEntry->UAPSDTimeStampLast)));
+
+ gUAPSD_SP_CloseAbnormalNum ++;
+#endif /* UAPSD_DEBUG */
+
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+ UAPSD_SP_Close(pAd, pEntry);
+ RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock);
+ }
+ else
+ {
+#endif /* UAPSD_SP_ACCURATE */
+
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+ return;
+
+#ifdef UAPSD_SP_ACCURATE
+ }
+#endif /* UAPSD_SP_ACCURATE */
+ }
+
+#ifdef UAPSD_TIMING_RECORD_FUNC
+ UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_TRG_RCV);
+#endif /* UAPSD_TIMING_RECORD_FUNC */
+
+#ifdef UAPSD_DEBUG
+ if (pEntry->pUAPSDEOSPFrame != NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> EOSP is not NULL!\n"));
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+ return;
+ }
+#endif /* UAPSD_DEBUG */
+
+ if (pEntry->MaxSPLength >= 4)
+ {
+ /* fatal error, should be 0 ~ 3 so reset it to 0 */
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("uapsd> MaxSPLength >= 4 (%d)!\n", pEntry->MaxSPLength));
+ pEntry->MaxSPLength = 0;
+ }
+
+
+#ifdef UAPSD_SP_ACCURATE
+ /* mark the start time for the SP */
+ UAPSD_TIME_GET(pAd, pEntry->UAPSDTimeStampLast);
+
+
+ /* check if current rate of the entry is 1Mbps (2.4GHz) or 6Mbps (5GHz) */
+
+#ifdef RTMP_MAC_USB
+ /* always use rough mechanism */
+ pEntry->bAPSDFlagSpRoughUse = 1;
+#endif /* RTMP_MAC_USB */
+#else
+
+ pEntry->bAPSDFlagSpRoughUse = 1;
+#endif /* UAPSD_SP_ACCURATE */
+
+
+ /* sanity Check for UAPSD condition */
+ if (UpOfFrame >= 8)
+ UpOfFrame = 1; /* shout not be here */
+
+ /* get the AC ID of incoming packet */
+ AcQueId = MapUserPriorityToAccessCategory[UpOfFrame];
+
+ /* check whether the AC is trigger-enabled AC */
+ if (pEntry->bAPSDCapablePerAC[AcQueId] == 0)
+ {
+ /*
+ WMM Specification V1.1 Page 4
+ Trigger Frame: A QoS Data or QoS Null frame from a WMM STA in
+ Power Save Mode associated with an AC the WMM STA has configured
+ to be a trigger-enabled AC.
+
+ A QoS Data or QoS Null frame that indicates transition to/from
+ Power Save Mode is not considered to be a Trigger Frame and the
+ AP shall not respond with a QoS Null frame.
+ */
+
+ /*
+ ERROR! the AC does not belong to a trigger-enabled AC or
+ the ACM of the AC is set.
+ */
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+ return;
+ }
+
+
+ /* enqueue U-APSD packets to AC software queues */
+
+ /*
+ Protect TxSwQueue0 & McastPsQueue because use them in
+ interrupt context.
+ */
+/* RTMP_IRQ_LOCK(FlgIrq); */
+
+ /* init */
+ FlgQueEmpty = TRUE;
+ TxPktNum = 0;
+ SpMaxLen = SpLenMap[pEntry->MaxSPLength];
+ pAcSwQue = NULL;
+ pLastAcSwQue = NULL;
+ pQuedPkt = NULL;
+ FlgMgmtFrame = 0;
+
+ /* from highest priority AC3 --> AC2 --> AC0 --> lowest priority AC1 */
+ for (IdAc=(WMM_NUM_OF_AC-1); IdAc>=0; IdAc--)
+ {
+ AcQueId = AcPriority[IdAc];
+
+ /* check if the AC is delivery-enable AC */
+ if (pEntry->bAPSDDeliverEnabledPerAC[AcQueId] == 0)
+ continue;
+
+ /*
+ NOTE: get U-APSD queue pointer here to speed up, do NOT use
+ pEntry->UAPSDQueue[AcQueId] throughout codes because
+ compiler will compile it to many assembly codes.
+ */
+ pAcPsQue = &pEntry->UAPSDQueue[AcQueId];
+
+ /* check if any U-APSD packet is queued for the AC */
+ if (pAcPsQue->Head == NULL)
+ continue;
+
+ /* at least one U-APSD packet exists here */
+
+ /* get AC software queue */
+ QueId = QueIdList[AcQueId];
+ pAcSwQue = &pAd->TxSwQueue[QueId];
+
+ /* put U-APSD packets to the AC software queue */
+ while(pAcPsQue->Head)
+ {
+ /* check if Max SP Length != 0 */
+ if (SpMaxLen != 0)
+ {
+ /*
+ WMM Specification V1.1 3.6.1.7
+ At each USP for a WMM STA, the WMM AP shall attempt to
+ transmit at least one MSDU or MMPDU, but no more than the
+ value encoded in the Max SP Length field in the QoS Info
+ Field of a WMM Information Element from delivery-enabled
+ ACs, that are destined for the WMM STA.
+ */
+ if (TxPktNum >= SpMaxLen)
+ {
+ /*
+ Some queued U-APSD packets still exists so we will
+ not clear MoreData bit of the packet.
+ */
+ FlgQueEmpty = FALSE;
+ break;
+ }
+ }
+
+ /* count U-APSD packet number */
+ TxPktNum ++;
+
+ /* queue last U-APSD packet */
+ if (pQuedPkt != NULL)
+ {
+ /* enqueue U-APSD packet to transmission software queue */
+
+ /*
+ WMM Specification V1.1 3.6.1.7
+ Each buffered frame shall be delivered using the access
+ parameters of its AC.
+ */
+ UAPSD_INSERT_QUEUE_AC(pAd, pEntry, pLastAcSwQue, pQuedPkt);
+ }
+
+ /* get the U-APSD packet */
+ pQuedEntry = RemoveHeadQueue(pAcPsQue);
+ pQuedPkt = QUEUE_ENTRY_TO_PACKET(pQuedEntry);
+
+ if (pQuedPkt != NULL)
+ {
+ if (RTMP_GET_PACKET_MGMT_PKT(pQuedPkt) == 1)
+ FlgMgmtFrame = 1;
+
+ /*
+ WMM Specification V1.1 3.6.1.7
+ The More Data bit (b13) of the directed MSDU or MMPDU
+ associated with delivery-enabled ACs and destined for
+ that WMM STA indicates that more frames are buffered for
+ the delivery-enabled ACs.
+ */
+ RTMP_SET_PACKET_MOREDATA(pQuedPkt, TRUE);
+
+ /* set U-APSD flag & its software queue ID */
+ RTMP_SET_PACKET_UAPSD(pQuedPkt, TRUE, QueId);
+ }
+
+ /* backup its software queue pointer */
+ pLastAcSwQue = pAcSwQue;
+ }
+
+ if (FlgQueEmpty == FALSE)
+ {
+ /* FlgQueEmpty will be FALSE only when TxPktNum >= SpMaxLen */
+ break;
+ }
+ }
+
+ /*
+ For any mamagement UAPSD frame, we use DMA to do SP check
+ because no any FIFO statistics for management frame.
+ */
+ if (FlgMgmtFrame)
+ pEntry->bAPSDFlagSpRoughUse = 1;
+
+ /*
+ No need to protect EOSP handle code because we will be here
+ only when last SP is ended.
+ */
+ FlgNullSnd = FALSE;
+
+ if (TxPktNum >= 1)
+ {
+ if (FlgQueEmpty == TRUE)
+ {
+ /*
+ No any more queued U-APSD packet so clear More Data bit of
+ the last frame.
+ */
+ RTMP_SET_PACKET_MOREDATA(pQuedPkt, FALSE);
+ }
+ }
+
+ //pEntry->bAPSDFlagSPStart = 1; /* set the SP start flag */
+ UAPSD_SP_START(pAd, pEntry); /* set the SP start flag */
+ pEntry->bAPSDFlagEOSPOK = 0;
+
+#ifdef UAPSD_DEBUG
+{
+ ULONG DebugTimeNow;
+
+ UAPSD_TIME_GET(pAd, DebugTimeNow);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> start a SP (Tx Num = %d) (Rough SP = %d) "
+ "(Has Any Mgmt = %d) (Abnormal = %d) (Time = %lu)\n",
+ TxPktNum, pEntry->bAPSDFlagSpRoughUse, FlgMgmtFrame,
+ gUAPSD_SP_CloseAbnormalNum, DebugTimeNow));
+}
+#endif /* UAPSD_DEBUG */
+
+ if (TxPktNum <= 1)
+ {
+ /* if no data needs to tx, respond with QosNull for the trigger frame */
+ pEntry->pUAPSDEOSPFrame = NULL;
+ pEntry->UAPSDTxNum = 0;
+
+ if (TxPktNum <= 0)
+ {
+ FlgNullSnd = TRUE;
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("uapsd> No data, send a Qos-Null frame with ESOP bit on and "
+ "UP=%d to end USP\n", UpOfFrame));
+#endif /* RELEASE_EXCLUDE */
+ }
+ else
+ {
+ /* only one packet so send it directly */
+ RTMP_SET_PACKET_EOSP(pQuedPkt, TRUE);
+ UAPSD_INSERT_QUEUE_AC(pAd, pEntry, pLastAcSwQue, pQuedPkt);
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("uapsd> Only one packet with UP = %d\n",
+ RTMP_GET_PACKET_UP(pQuedPkt)));
+#endif /* RELEASE_EXCLUDE */
+ } /* End of if */
+
+ /*
+ We will send the QoS Null frame below and we will hande the
+ QoS Null tx done in RTMPFreeTXDUponTxDmaDone().
+ */
+ }
+ else
+ {
+ /* more than two U-APSD packets */
+
+ /*
+ NOTE: EOSP bit != !MoreData bit because Max SP Length,
+ we can not use MoreData bit to decide EOSP bit.
+ */
+
+ /*
+ Backup the EOSP frame and
+ we will transmit the EOSP frame in RTMPFreeTXDUponTxDmaDone().
+ */
+ RTMP_SET_PACKET_EOSP(pQuedPkt, TRUE);
+
+ pEntry->pUAPSDEOSPFrame = (PQUEUE_ENTRY)pQuedPkt;
+ pEntry->UAPSDTxNum = TxPktNum-1; /* skip the EOSP frame */
+ }
+
+#ifdef UAPSD_DEBUG
+ if ((pEntry->pUAPSDEOSPFrame != NULL) &&
+ (RTMP_GET_PACKET_MGMT_PKT(pEntry->pUAPSDEOSPFrame) == 1))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> The EOSP frame is a management frame.\n"));
+ }
+#endif /* UAPSD_DEBUG */
+
+
+#ifdef UAPSD_SP_ACCURATE
+ /* count for legacy PS packet */
+
+ /*
+ Note: A worse case for mix mode (UAPSD + legacy PS):
+ PS-Poll --> legacy ps packet --> trigger frame --> QoS Null frame
+ (QSTA) (QAP) (QSTA) (QAP)
+
+ where statistics handler is NICUpdateFifoStaCounters().
+
+ If we receive the trigger frame before the legacy ps packet is sent to
+ the air, when we call statistics handler in tx done, it maybe the
+ legacy ps statistics, not the QoS Null frame statistics, so we will
+ do UAPSD counting fail.
+
+ We need to count the legacy PS here if it is not yet sent to the air.
+ */
+
+ /*
+ Note: in addition, only one legacy PS need to count because one legacy
+ packet for one PS-Poll packet; if we receive a trigger frame from a
+ station, it means that only one legacy ps packet is possible not sent
+ to the air, it is impossible more than 2 legacy packets are not yet
+ sent to the air.
+ */
+
+ if ((pEntry->bAPSDFlagSpRoughUse == 0) &&
+ (pEntry->bAPSDFlagLegacySent != 0))
+ {
+ pEntry->UAPSDTxNum ++;
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> A legacy PS is sent! UAPSDTxNum = %d\n",
+ pEntry->UAPSDTxNum));
+#endif /* UAPSD_DEBUG */
+ }
+#endif /* UAPSD_SP_ACCURATE */
+
+
+ /* clear corresponding TIM bit */
+
+ /* get its AID for the station */
+ Aid = pEntry->Aid;
+
+ if ((pEntry->bAPSDAllAC == 1) && (FlgQueEmpty == 1))
+ {
+ /* all AC are U-APSD and no any U-APSD packet is queued, set TIM */
+
+#ifdef CONFIG_AP_SUPPORT
+ /* clear TIM bit */
+ if ((Aid > 0) && (Aid < MAX_LEN_OF_MAC_TABLE))
+ {
+ WLAN_MR_TIM_BIT_CLEAR(pAd, pEntry->apidx, Aid);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+ /* reset idle timeout here whenever a trigger frame is received */
+ pEntry->UAPSDQIdleCount = 0;
+
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+
+
+ /* check if NULL Frame is needed to be transmitted */
+
+ /* it will be crashed, when spin locked in kernel 2.6 */
+ if (FlgNullSnd)
+ {
+ /* bQosNull = bEOSP = TRUE = 1 */
+
+ /*
+ Use management queue to tx QoS Null frame to avoid delay so
+ us_of_frame is not used.
+ */
+ RtmpEnqueueNullFrame(pAd, pEntry->Addr, pEntry->CurrTxRate,
+ Aid, pEntry->apidx, TRUE, TRUE, UpOfFrame);
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> end a SP by a QoS Null frame!\n"));
+#endif /* UAPSD_DEBUG */
+ }
+
+#ifdef UAPSD_TIMING_RECORD_FUNC
+ UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_MOVE2TX);
+#endif /* UAPSD_TIMING_RECORD_FUNC */
+
+ /* Dequeue outgoing frames from TxSwQueue0..3 queue and process it */
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+}
+
+
+#ifdef RTMP_MAC_USB
+/*
+========================================================================
+Routine Description:
+ Tag current offset of the AC in USB URB tx buffer.
+
+Arguments:
+ pAd Pointer to our adapter
+ *pPkt the tx packet
+ Wcid destination entry id
+ PktOffset USB tx buffer offset
+
+Return Value:
+ None
+
+Note:
+ Only for RT2870.
+========================================================================
+*/
+VOID UAPSD_TagFrame(
+ IN RTMP_ADAPTER *pAd,
+ IN NDIS_PACKET *pPkt,
+ IN UCHAR Wcid,
+ IN UINT32 PktOffset)
+{
+ MAC_TABLE_ENTRY *pEntry;
+ UCHAR AcQueId;
+
+
+ if ((Wcid == MCAST_WCID) || (Wcid >= MAX_LEN_OF_MAC_TABLE))
+ return; /* the frame is broadcast/multicast frame */
+ /* End of if */
+
+ pEntry = &pAd->MacTab.Content[Wcid];
+
+ if (pEntry->bAPSDFlagSPStart == 0)
+ return; /* SP is not started */
+ /* End of if */
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> prepare to tag the frame...\n"));
+#endif /* UAPSD_DEBUG */
+
+ if (RTMP_GET_PACKET_UAPSD_Flag(pPkt) == TRUE)
+ {
+ /* mark the latest USB tx buffer offset for the priority */
+ AcQueId = RTMP_GET_PACKET_UAPSD_QUE_ID(pPkt);
+ pEntry->UAPSDTagOffset[AcQueId] = PktOffset;
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_TRACE, ("uapsd> tag offset = %d\n", PktOffset));
+#endif /* UAPSD_DEBUG */
+ } /* End of if */
+} /* End of UAPSD_TagFrame */
+
+
+/*
+========================================================================
+Routine Description:
+ Check if UAPSD packets are tx ok.
+
+Arguments:
+ pAd Pointer to our adapter
+ AcQueId TX completion for the AC (0 ~ 3)
+ bulkStartPos
+ bulkEnPos
+
+Return Value:
+ None
+
+Note:
+ Only for RT2870.
+========================================================================
+*/
+VOID UAPSD_UnTagFrame(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR AcQueId,
+ IN UINT32 bulkStartPos,
+ IN UINT32 bulkEnPos)
+{
+ MAC_TABLE_ENTRY *pEntry;
+ UINT32 IdEntry;
+ UINT32 TxPktTagOffset;
+ UINT16 QueId;
+ int FirstWcid = 1;
+
+
+ RTMP_SEM_LOCK(&pAd->UAPSDEOSPLock);
+
+ /* loop for all entries to check whether we need to close their SP */
+ for(IdEntry = FirstWcid; IdEntry < MAX_LEN_OF_MAC_TABLE; IdEntry++)
+ {
+ pEntry = &pAd->MacTab.Content[IdEntry];
+
+ if ((IS_ENTRY_CLIENT(pEntry)
+ )
+ && (pEntry->bAPSDFlagSPStart == 1) &&
+ (pEntry->UAPSDTagOffset[AcQueId] != 0))
+ {
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_ERROR, ("uapsd> bulkStartPos = %d\n", bulkStartPos));
+ DBGPRINT(RT_DEBUG_ERROR, ("uapsd> bulkEnPos = %d\n", bulkEnPos));
+ DBGPRINT(RT_DEBUG_ERROR, ("uapsd> record offset = %d\n", pEntry->UAPSDTagOffset[AcQueId]));
+#endif /* UAPSD_DEBUG */
+
+ /*
+ 1. tx tag is in [bulkStartPos, bulkEnPos];
+ 2. when bulkEnPos < bulkStartPos
+ */
+ TxPktTagOffset = pEntry->UAPSDTagOffset[AcQueId];
+
+ if (((TxPktTagOffset >= bulkStartPos) &&
+ (TxPktTagOffset <= bulkEnPos)) ||
+ ((bulkEnPos < bulkStartPos) &&
+ (TxPktTagOffset >= bulkStartPos)) ||
+ ((bulkEnPos < bulkStartPos) &&
+ (TxPktTagOffset <= bulkEnPos)))
+ {
+ /* ok, some UAPSD frames of the AC are transmitted */
+ pEntry->UAPSDTagOffset[AcQueId] = 0;
+
+ if (pEntry->UAPSDTxNum == 0)
+ {
+ /* ok, all UAPSD frames are transmitted */
+ //pEntry->bAPSDFlagSPStart = 0;
+ pEntry->bAPSDFlagEOSPOK = 0;
+ UAPSD_SP_END(pAd, pEntry);
+
+ if (pEntry->pUAPSDEOSPFrame != NULL)
+ {
+ /* should not be here */
+ RELEASE_NDIS_PACKET(pAd,
+ QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame),
+ NDIS_STATUS_FAILURE);
+ pEntry->pUAPSDEOSPFrame = NULL;
+ } /* End of if */
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_ERROR, ("uapsd> [1] close SP (%d)!\n", AcQueId));
+#endif /* UAPSD_DEBUG */
+ continue; /* check next station */
+ } /* End of if */
+
+ if ((pEntry->UAPSDTagOffset[QID_AC_BE] == 0) &&
+ (pEntry->UAPSDTagOffset[QID_AC_BK] == 0) &&
+ (pEntry->UAPSDTagOffset[QID_AC_VI] == 0) &&
+ (pEntry->UAPSDTagOffset[QID_AC_VO] == 0))
+ {
+ /*
+ OK, UAPSD frames of all AC for the entry are transmitted
+ except the EOSP frame.
+ */
+
+ if (pEntry->pUAPSDEOSPFrame != NULL)
+ {
+ /* transmit the EOSP frame */
+ PNDIS_PACKET pPkt;
+
+ pPkt = QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame);
+ QueId = RTMP_GET_PACKET_UAPSD_QUE_ID(pPkt);
+
+ if (QueId > QID_AC_VO)
+ {
+ /* should not be here, only for sanity */
+ QueId = QID_AC_BE;
+ } /* End of if */
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_ERROR, ("uapsd> enqueue the EOSP frame...\n"));
+#endif /* UAPSD_DEBUG */
+
+ UAPSD_INSERT_QUEUE_AC(pAd, pEntry,
+ &pAd->TxSwQueue[QueId],
+ pEntry->pUAPSDEOSPFrame);
+
+ pEntry->pUAPSDEOSPFrame = NULL;
+
+ /*
+ The EOSP frame will be put into ASIC to tx
+ in RTMPHandleTxRingDmaDoneInterrupt(),
+ not the function.
+ */
+
+ /* de-queue packet here to speed up EOSP frame response */
+ printk("%s:: ----> RTMPDeQueuePacket\n", __FUNCTION__);
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+ }
+ else
+ {
+ /* only when 1 data frame with EOSP = 1 is transmitted */
+ //pEntry->bAPSDFlagSPStart = 0;
+ pEntry->bAPSDFlagEOSPOK = 0;
+ UAPSD_SP_END(pAd, pEntry);
+
+#ifdef UAPSD_DEBUG
+ DBGPRINT(RT_DEBUG_ERROR, ("uapsd> [2] close SP (%d)!\n", AcQueId));
+#endif /* UAPSD_DEBUG */
+ } /* End of if */
+
+ /* no any EOSP frames are queued and prepare to close the SP */
+ pEntry->UAPSDTxNum = 0;
+ } /* End of if */
+ } /* End of if */
+ } /* End of if */
+ } /* End of for */
+
+ RTMP_SEM_UNLOCK(&pAd->UAPSDEOSPLock);
+} /* End of UAPSD_UnTagFrame */
+#endif /* RTMP_MAC_USB */
+
+
+#ifdef VENDOR_FEATURE3_SUPPORT
+/*
+========================================================================
+Routine Description:
+ Queue packet to a AC software queue.
+
+Arguments:
+ pAd Pointer to our adapter
+ pEntry The station
+ pQueueHeader The software queue header of the AC
+ bulkEnPos The packet entry
+
+Return Value:
+ None
+
+Note:
+ Only for code size reduce purpose.
+========================================================================
+*/
+static VOID UAPSD_InsertTailQueueAc(
+ IN RTMP_ADAPTER *pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN QUEUE_HEADER *pQueueHeader,
+ IN QUEUE_ENTRY *pQueueEntry)
+{
+ InsertTailQueueAc(pAd, pEntry, pQueueHeader, pQueueEntry);
+} /* End of InsertTailQueueAc */
+#endif /* VENDOR_FEATURE3_SUPPORT */
+
+#endif /* UAPSD_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/vht.c b/cleopatre/devkit/mt7601udrv/common/vht.c
new file mode 100644
index 0000000000..c75757b069
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/vht.c
@@ -0,0 +1,400 @@
+/*
+
+*/
+
+#include "rt_config.h"
+
+
+/*
+ IEEE 802.11AC D2.0 sec 22.3.14
+ Channelization, Table 22-21
+
+ A VHT channel is specified by the four PLME MIB fields
+ (Fields to specify VHT channels).
+
+ dot11CurrentChannelBandwidth:
+ Channel bandwidth. Possible values are
+ cbw20, cbw40, cbw80, cbw160 and cbw80p80.
+ dot11CurrentChannelCenterFrequencyIndex1:
+ In 20 MHz, 40 MHz, 80 MHz and 160 MHz channels, denotes the channel
+ center frequency.
+ In 80+80 MHz channels, denotes the center frequency of the frequency
+ segment 1, which is the frequency segment containing the primary
+ channel..
+ Valid range = 1, ¡K, 200.
+ dot11CurrentChannelCenterFrequencyIndex2:
+ In 80+80 MHz channels, denotes the center frequency of the frequency
+ segment 2, which is the frequency segment that does not contain the
+ primary channel.
+ Valid range = 1, ¡K, 200.
+ Undefined for 20 MHz, 40 MHz, 80 MHz and 160 MHz channels.
+ dot11CurrentPrimaryChannel:
+ Denotes the location of the primary 20 MHz channel.
+ Valid range = 1, ¡K, 200.
+
+
+ Formula:
+ A channel center frequency of 5.000 GHz shall be indicated by
+ dot11ChannelStartingFactor = 8000, and
+ dot11CurrentPrimaryChannel = 200.
+
+ Channel starting frequency
+ = dot11ChannelStartingFactor ¡Ñ 0500 kHz.
+
+ Channel center frequency [MHz]
+ = Channel starting frequency + 5 * dot11CurrentChannelCenterFrequencyIndex
+
+ Primary 20 MHz channel center frequency [MHz]
+ = Channel starting frequency + 5 * dot11CurrentPrimaryChannel
+
+ ex: a channel specified by:
+ dot11CurrentChannelBandwidth = 80 MHz
+ dot11CurrentChannelCenterFrequencyIndex1 = 42
+ dot11CurrentPrimaryChannel = 36
+
+ =>is an 80 MHz channel with a center frequency of 5210 MHz and
+ the primary 20 MHz channel centered at 5180 MHz.
+
+*/
+struct vht_ch_layout{
+ UCHAR ch_low_bnd;
+ UCHAR ch_up_bnd;
+ UCHAR cent_freq_idx;
+};
+
+static struct vht_ch_layout vht_ch_80M[]={
+ {36, 48, 42},
+ {52, 64, 58},
+ {100,112, 106},
+ {116, 128, 122},
+ {132, 144, 138},
+ {149, 161, 155},
+ {0, 0 ,0},
+};
+
+
+
+
+VOID dump_vht_cap(RTMP_ADAPTER *pAd, VHT_CAP_IE *vht_ie)
+{
+ VHT_CAP_INFO *vht_cap = &vht_ie->vht_cap;
+ VHT_MCS_SET *vht_mcs = &vht_ie->mcs_set;
+
+ DBGPRINT(RT_DEBUG_OFF, ("Dump VHT_CAP IE\n"));
+ hex_dump("VHT CAP IE Raw Data", (UCHAR *)vht_ie, sizeof(VHT_CAP_IE));
+
+ DBGPRINT(RT_DEBUG_OFF, ("VHT Capabilities Info Field\n"));
+ DBGPRINT(RT_DEBUG_OFF, ("\tMaximum MPDU Length=%d\n", vht_cap->max_mpdu_len));
+ DBGPRINT(RT_DEBUG_OFF, ("\tSupported Channel Width=%d\n", vht_cap->ch_width));
+ DBGPRINT(RT_DEBUG_OFF, ("\tRxLDPC=%d\n", vht_cap->rx_ldpc));
+ DBGPRINT(RT_DEBUG_OFF, ("\tShortGI_80M=%d\n", vht_cap->sgi_80M));
+ DBGPRINT(RT_DEBUG_OFF, ("\tShortGI_160M=%d\n", vht_cap->sgi_160M));
+ DBGPRINT(RT_DEBUG_OFF, ("\tTxSTBC=%d\n", vht_cap->tx_stbc));
+ DBGPRINT(RT_DEBUG_OFF, ("\tRxSTBC=%d\n", vht_cap->rx_stbc));
+ DBGPRINT(RT_DEBUG_OFF, ("\tSU BeamformerCap=%d\n", vht_cap->bfer_cap_su));
+ DBGPRINT(RT_DEBUG_OFF, ("\tSU BeamformeeCap=%d\n", vht_cap->bfee_cap_su));
+ DBGPRINT(RT_DEBUG_OFF, ("\tCompressedSteeringNumOfBeamformerAnt=%d\n", vht_cap->cmp_st_num_bfer));
+ DBGPRINT(RT_DEBUG_OFF, ("\tNumber of Sounding Dimensions=%d\n", vht_cap->num_snd_dimension));
+ DBGPRINT(RT_DEBUG_OFF, ("\tMU BeamformerCap=%d\n", vht_cap->bfer_cap_mu));
+ DBGPRINT(RT_DEBUG_OFF, ("\tMU BeamformeeCap=%d\n", vht_cap->bfee_cap_mu));
+ DBGPRINT(RT_DEBUG_OFF, ("\tVHT TXOP PS=%d\n", vht_cap->vht_txop_ps));
+ DBGPRINT(RT_DEBUG_OFF, ("\t+HTC-VHT Capable=%d\n", vht_cap->htc_vht_cap));
+ DBGPRINT(RT_DEBUG_OFF, ("\tMaximum A-MPDU Length Exponent=%d\n", vht_cap->max_ampdu_exp));
+ DBGPRINT(RT_DEBUG_OFF, ("\tVHT LinkAdaptation Capable=%d\n", vht_cap->vht_link_adapt));
+
+ DBGPRINT(RT_DEBUG_OFF, ("VHT Supported MCS Set Field\n"));
+ DBGPRINT(RT_DEBUG_OFF, ("\tRx Highest SupDataRate=%d\n", vht_mcs->rx_high_rate));
+ DBGPRINT(RT_DEBUG_OFF, ("\tRxMCS Map_1SS=%d\n", vht_mcs->rx_mcs_map.mcs_ss1));
+ DBGPRINT(RT_DEBUG_OFF, ("\tRxMCS Map_2SS=%d\n", vht_mcs->rx_mcs_map.mcs_ss2));
+ DBGPRINT(RT_DEBUG_OFF, ("\tTx Highest SupDataRate=%d\n", vht_mcs->tx_high_rate));
+ DBGPRINT(RT_DEBUG_OFF, ("\tTxMCS Map_1SS=%d\n", vht_mcs->tx_mcs_map.mcs_ss1));
+ DBGPRINT(RT_DEBUG_OFF, ("\tTxMCS Map_2SS=%d\n", vht_mcs->tx_mcs_map.mcs_ss2));
+}
+
+
+VOID dump_vht_op(RTMP_ADAPTER *pAd, VHT_OP_IE *vht_ie)
+{
+ VHT_OP_INFO *vht_op = &vht_ie->vht_op_info;
+ VHT_MCS_MAP *vht_mcs = &vht_ie->basic_mcs_set;
+
+ DBGPRINT(RT_DEBUG_OFF, ("Dump VHT_OP IE\n"));
+ hex_dump("VHT OP IE Raw Data", (UCHAR *)vht_ie, sizeof(VHT_OP_IE));
+
+ DBGPRINT(RT_DEBUG_OFF, ("VHT Operation Info Field\n"));
+ DBGPRINT(RT_DEBUG_OFF, ("\tChannelWidth=%d\n", vht_op->ch_width));
+ DBGPRINT(RT_DEBUG_OFF, ("\tChannelCenterFrequency Seg 1=%d\n", vht_op->center_freq_1));
+ DBGPRINT(RT_DEBUG_OFF, ("\tChannelCenterFrequency Seg 1=%d\n", vht_op->center_freq_2));
+
+ DBGPRINT(RT_DEBUG_OFF, ("VHT Basic MCS Set Field\n"));
+ DBGPRINT(RT_DEBUG_OFF, ("\tRxMCS Map_1SS=%d\n", vht_mcs->mcs_ss1));
+ DBGPRINT(RT_DEBUG_OFF, ("\tRxMCS Map_2SS=%d\n", vht_mcs->mcs_ss2));
+}
+
+
+/*
+ Currently we only consider about VHT 80MHz!
+*/
+UCHAR vht_cent_ch_freq(RTMP_ADAPTER *pAd, UCHAR prim_ch)
+{
+ INT idx = 0;
+
+
+ if (pAd->CommonCfg.vht_bw < VHT_BW_80 || prim_ch < 36)
+ {
+ pAd->CommonCfg.vht_cent_ch = 0;
+ pAd->CommonCfg.vht_cent_ch2 = 0;
+ return prim_ch;
+ }
+
+ while (vht_ch_80M[idx].ch_up_bnd != 0)
+ {
+ if (prim_ch >= vht_ch_80M[idx].ch_low_bnd &&
+ prim_ch <= vht_ch_80M[idx].ch_up_bnd)
+ {
+ pAd->CommonCfg.vht_cent_ch = vht_ch_80M[idx].cent_freq_idx;
+ return vht_ch_80M[idx].cent_freq_idx;
+ }
+ idx++;
+ }
+
+ return prim_ch;
+}
+
+
+INT vht_mode_adjust(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, VHT_CAP_IE *cap, VHT_OP_IE *op)
+{
+ pEntry->MaxHTPhyMode.field.MODE = MODE_VHT;
+ pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
+ pAd->MacTab.fAnyStationNonGF = TRUE;
+
+ if (op->vht_op_info.ch_width >= 1 && pEntry->MaxHTPhyMode.field.BW == BW_40)
+ {
+ pEntry->MaxHTPhyMode.field.BW= BW_80;
+ pEntry->MaxHTPhyMode.field.ShortGI = (cap->vht_cap.sgi_80M);
+ pEntry->MaxHTPhyMode.field.STBC = (cap->vht_cap.rx_stbc > 1 ? 1 : 0);
+ }
+
+ return TRUE;
+}
+
+
+INT get_vht_op_ch_width(RTMP_ADAPTER *pAd)
+{
+
+ return TRUE;
+}
+
+
+/********************************************************************
+ Procedures for 802.11 AC Information elements
+********************************************************************/
+/*
+ Defined in IEEE 802.11AC
+
+ Appeared in Beacon, ProbResp frames
+*/
+INT build_quiet_channel(RTMP_ADAPTER *pAd, UCHAR *buf)
+{
+ INT len = 0;
+
+
+ return len;
+}
+
+
+/*
+ Defined in IEEE 802.11AC
+
+ Appeared in Beacon, ProbResp frames
+*/
+INT build_ext_bss_load(RTMP_ADAPTER *pAd, UCHAR *buf)
+{
+ INT len = 0;
+
+
+ return len;
+}
+
+
+/*
+ Defined in IEEE 802.11AC
+
+ Appeared in Beacon, ProbResp frames
+*/
+INT build_ext_pwr_constraint(RTMP_ADAPTER *pAd, UCHAR *buf)
+{
+ INT len = 0;
+
+
+ return len;
+}
+
+
+/*
+ Defined in IEEE 802.11AC
+
+ Appeared in Beacon, ProbResp frames
+*/
+INT build_vht_pwr_envelope(RTMP_ADAPTER *pAd, UCHAR *buf)
+{
+ INT len = 0;
+
+
+ return len;
+}
+
+
+/*
+ Defined in IEEE 802.11AC
+
+ Appeared in Beacon, (Re)AssocResp, ProbResp frames
+*/
+INT build_vht_op_ie(RTMP_ADAPTER *pAd, UCHAR *buf)
+{
+ VHT_OP_IE vht_op;
+
+ NdisZeroMemory((UCHAR *)&vht_op, sizeof(VHT_OP_IE));
+ vht_op.vht_op_info.ch_width = (pAd->CommonCfg.vht_bw == VHT_BW_80 ? 1: 0);
+ switch (vht_op.vht_op_info.ch_width)
+ {
+ case 0:
+ vht_op.vht_op_info.center_freq_1 = 0;
+ vht_op.vht_op_info.center_freq_2 = 0;
+ break;
+ case 1:
+ case 2:
+ vht_op.vht_op_info.center_freq_1 = pAd->CommonCfg.vht_cent_ch;
+ vht_op.vht_op_info.center_freq_2 = 0;
+ break;
+ case 3:
+ vht_op.vht_op_info.center_freq_1 = pAd->CommonCfg.vht_cent_ch;
+ vht_op.vht_op_info.center_freq_2 = pAd->CommonCfg.vht_cent_ch2;
+ break;
+ }
+
+ vht_op.basic_mcs_set.mcs_ss1 = 3;
+ vht_op.basic_mcs_set.mcs_ss2 = 3;
+ vht_op.basic_mcs_set.mcs_ss3 = 3;
+ vht_op.basic_mcs_set.mcs_ss4 = 3;
+ vht_op.basic_mcs_set.mcs_ss5 = 3;
+ vht_op.basic_mcs_set.mcs_ss6 = 3;
+ vht_op.basic_mcs_set.mcs_ss7 = 3;
+ vht_op.basic_mcs_set.mcs_ss8 = 3;
+ switch (pAd->CommonCfg.RxStream)
+ {
+ case 2:
+ vht_op.basic_mcs_set.mcs_ss2 = 0;
+ case 1:
+ vht_op.basic_mcs_set.mcs_ss1 = 0;
+ break;
+ }
+
+ NdisMoveMemory((UCHAR *)buf, (UCHAR *)&vht_op, sizeof(VHT_OP_IE));
+
+ return sizeof(VHT_OP_IE);
+}
+
+
+/*
+ Defined in IEEE 802.11AC
+
+ Appeared in Beacon, (Re)AssocReq, (Re)AssocResp, ProbReq/Resp frames
+*/
+INT build_vht_cap_ie(RTMP_ADAPTER *pAd, UCHAR *buf)
+{
+ VHT_CAP_IE vht_cap_ie;
+
+ NdisZeroMemory((UCHAR *)&vht_cap_ie, sizeof(VHT_CAP_IE));
+ vht_cap_ie.vht_cap.max_mpdu_len = 0; // TODO: Ask Jerry about hardware limitation.
+ vht_cap_ie.vht_cap.ch_width = 0; /* not support 160 or 80 + 80 MHz */
+ vht_cap_ie.vht_cap.sgi_80M = 1;
+ vht_cap_ie.vht_cap.htc_vht_cap = 1;
+ vht_cap_ie.vht_cap.max_ampdu_exp = 3; // TODO: Ask Jerry about the hardware limitation, currently set as 64K
+ vht_cap_ie.vht_cap.tx_stbc = 1;
+ vht_cap_ie.vht_cap.rx_stbc = 2; // TODO: is it depends on the number of our antennas?
+ vht_cap_ie.vht_cap.tx_ant_consistency = 1;
+ vht_cap_ie.vht_cap.rx_ant_consistency = 1;
+
+ vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss1 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss2 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss3 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss4 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss5 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss6 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss7 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss8 = VHT_MCS_CAP_NA;
+
+ vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss1 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss2 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss3 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss4 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss5 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss6 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss7 = VHT_MCS_CAP_NA;
+ vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss8 = VHT_MCS_CAP_NA;
+
+
+ switch (pAd->CommonCfg.RxStream)
+ {
+ case 1:
+ vht_cap_ie.mcs_set.rx_high_rate = 292;
+ vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss1 = VHT_MCS_CAP_7;
+ break;
+ case 2:
+ vht_cap_ie.mcs_set.rx_high_rate = 585;
+ vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss1 = VHT_MCS_CAP_7;
+ vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss2 = VHT_MCS_CAP_7;
+ break;
+ default:
+ vht_cap_ie.mcs_set.rx_high_rate = 0;
+ break;
+ }
+
+ switch (pAd->CommonCfg.TxStream)
+ {
+ case 1:
+ vht_cap_ie.mcs_set.tx_high_rate = 292;
+ vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss1 = VHT_MCS_CAP_7;
+ break;
+ case 2:
+ vht_cap_ie.mcs_set.tx_high_rate = 585;
+ vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss1 = VHT_MCS_CAP_7;
+ vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss2 = VHT_MCS_CAP_7;
+ break;
+ default:
+ vht_cap_ie.mcs_set.tx_high_rate = 0;
+ break;
+ }
+
+ NdisMoveMemory(buf, (UCHAR *)&vht_cap_ie, sizeof(VHT_CAP_IE));
+
+ return sizeof(VHT_CAP_IE);
+}
+
+
+INT build_vht_ies(RTMP_ADAPTER *pAd, UCHAR *buf, UCHAR frm)
+{
+ INT len = 0;
+ EID_STRUCT eid_hdr;
+
+
+ eid_hdr.Eid = IE_VHT_CAP;
+ eid_hdr.Len = sizeof(VHT_CAP_IE);
+ NdisMoveMemory(buf, (UCHAR *)&eid_hdr, 2);
+ len = 2;
+
+ len += build_vht_cap_ie(pAd, (UCHAR *)(buf + len));
+ if (frm == SUBTYPE_BEACON || frm == SUBTYPE_PROBE_RSP ||
+ frm == SUBTYPE_ASSOC_RSP || frm == SUBTYPE_REASSOC_RSP)
+ {
+ eid_hdr.Eid = IE_VHT_OP;
+ eid_hdr.Len = sizeof(VHT_OP_IE);
+ NdisMoveMemory((UCHAR *)(buf + len), (UCHAR *)&eid_hdr, 2);
+ len +=2;
+
+ len += build_vht_op_ie(pAd, (UCHAR *)(buf + len));
+ }
+
+ return len;
+}
+
diff --git a/cleopatre/devkit/mt7601udrv/common/wapi.c b/cleopatre/devkit/mt7601udrv/common/wapi.c
new file mode 100644
index 0000000000..8c93cfe646
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/wapi.c
@@ -0,0 +1,1185 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2006, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ wapi.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Albert 2008-4-3 Supoort WAPI protocol
+*/
+/*#include <linux/stdio.h> */
+/*#include <linux/stdlib.h> */
+/*#include <linux/string.h> */
+/*#include <linux/time.h> */
+
+#ifdef WAPI_SUPPORT
+
+#include "rt_config.h"
+
+/* WAPI AKM OUI */
+UCHAR OUI_WAI_CERT_AKM[4] = {0x00, 0x14, 0x72, 0x01};
+UCHAR OUI_WAI_PSK_AKM[4] = {0x00, 0x14, 0x72, 0x02};
+
+/* WAPI CIPHER OUI */
+UCHAR OUI_WPI_CIPHER_SMS4[4] = {0x00, 0x14, 0x72, 0x01};
+
+UCHAR WAPI_TYPE[] = {0x88, 0xb4};
+
+/* IV default value */
+UCHAR AE_BCAST_PN[LEN_WAPI_TSC] = {0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
+ 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c};
+UCHAR ASUE_UCAST_PN[LEN_WAPI_TSC] = {0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
+ 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c};
+UCHAR AE_UCAST_PN[LEN_WAPI_TSC] = {0x37, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
+ 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c};
+
+BUILD_TIMER_FUNCTION(RTMPWapiUskRekeyPeriodicExec);
+BUILD_TIMER_FUNCTION(RTMPWapiMskRekeyPeriodicExec);
+
+static void kd_hmac_sha256(
+ unsigned char *key,
+ unsigned int key_len,
+ unsigned char *text,
+ unsigned int text_len,
+ unsigned char *output,
+ unsigned int output_len)
+{
+ int i;
+
+ for (i = 0; output_len/SHA256_DIGEST_SIZE; i++, output_len -= SHA256_DIGEST_SIZE)
+ {
+ RT_HMAC_SHA256(key, key_len, text, text_len, &output[i*SHA256_DIGEST_SIZE], SHA256_DIGEST_SIZE);
+ text = &output[i*SHA256_DIGEST_SIZE];
+ text_len = SHA256_DIGEST_SIZE;
+ }
+
+ if (output_len > 0)
+ RT_HMAC_SHA256(key, key_len, text, text_len, &output[i*SHA256_DIGEST_SIZE], output_len);
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build WAPI IE in RSN-IE.
+ It only shall be called by RTMPMakeRSNIE.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ AuthMode - indicate the authentication mode
+ WepStatus - indicate the encryption type
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPInsertWapiIe(
+ IN UINT AuthMode,
+ IN UINT WepStatus,
+ OUT PUCHAR pWIe,
+ OUT UCHAR *w_len)
+{
+ WAPIIE *pWapiHdr = (WAPIIE*)pWIe;
+ WAPIIE_UCAST *pWIE_ucast;
+ WAPIIE_MCAST *pWIE_mcast;
+
+ *w_len = 0;
+
+ /* Assign the verson as 1 */
+ pWapiHdr->version = 1;
+
+ /* Set the AKM count and suite */
+ pWapiHdr->acount = 1;
+ switch (AuthMode)
+ {
+ case Ndis802_11AuthModeWAICERT:
+ NdisMoveMemory(pWapiHdr->auth[0].oui, OUI_WAI_CERT_AKM, 4);
+ break;
+
+ case Ndis802_11AuthModeWAIPSK:
+ NdisMoveMemory(pWapiHdr->auth[0].oui, OUI_WAI_PSK_AKM, 4);
+ break;
+ }
+
+ /* swap for big-endian platform */
+ pWapiHdr->version = cpu2le16(pWapiHdr->version);
+ pWapiHdr->acount = cpu2le16(pWapiHdr->acount);
+
+ /* update current length */
+ (*w_len) += sizeof(WAPIIE);
+
+ /* Set the unicast cipher and count */
+ pWIE_ucast = (WAPIIE_UCAST*)(pWIe + (*w_len));
+ pWIE_ucast->ucount = 1;
+ NdisMoveMemory(pWIE_ucast->ucast[0].oui, OUI_WPI_CIPHER_SMS4, 4);
+
+ /* swap for big-endian platform */
+ pWIE_ucast->ucount = cpu2le16(pWIE_ucast->ucount);
+
+ /* update current length */
+ (*w_len) += sizeof(WAPIIE_UCAST);
+
+ /* Set the multicast cipher and capability */
+ pWIE_mcast = (WAPIIE_MCAST*)(pWIe + (*w_len));
+ NdisMoveMemory(pWIE_mcast->mcast, OUI_WPI_CIPHER_SMS4, 4);
+ pWIE_mcast->capability = 0; /* Todo AlbertY - support pre-authentication */
+
+ /* update current length */
+ (*w_len) += sizeof(WAPIIE_MCAST);
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ Check whether the received frame is WAPI frame.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ pData - the received frame
+ DataByteCount - the received frame's length
+
+ Return:
+ TRUE - This frame is WAPI frame
+ FALSE - otherwise
+ ==========================================================================
+*/
+BOOLEAN RTMPCheckWAIframe(
+ IN PUCHAR pData,
+ IN ULONG DataByteCount)
+{
+ if(DataByteCount < (LENGTH_802_1_H + LENGTH_WAI_H))
+ return FALSE;
+
+
+ /* Skip LLC header */
+ if (NdisEqualMemory(SNAP_802_1H, pData, 6))
+ {
+ pData += 6;
+ }
+ /* Skip 2-bytes EAPoL type */
+ if (NdisEqualMemory(WAPI_TYPE, pData, 2))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> Receive a WAI frame \n"));
+ pData += 2;
+ }
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Check whether the cipher is SMS4.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ apidx - interface index
+
+ Return:
+ TRUE - The cipher is SMS4
+ FALSE - otherwise
+ ==========================================================================
+*/
+BOOLEAN RTMPIsWapiCipher(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR apidx)
+{
+ NDIS_802_11_ENCRYPTION_STATUS cipher_mode = Ndis802_11EncryptionDisabled;
+
+ /* Currently, WAPI only support MBSS */
+ if (apidx >= MAX_MBSSID_NUM(pAd) + MAX_P2P_NUM)
+ return FALSE;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ if (apidx < MAX_MBSSID_NUM(pAd))
+ cipher_mode = pAd->ApCfg.MBSSID[apidx].WepStatus;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (cipher_mode == Ndis802_11EncryptionSMS4Enabled)
+ return TRUE;
+
+ return FALSE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Insert the WPI-SMS4 IV header
+
+ +-------+------+-------------+
+ | KeyId | resv | sequence PN |
+ +-------+------+-------------+
+
+ Arguments:
+
+ Return:
+
+ ==========================================================================
+*/
+VOID RTMPConstructWPIIVHdr(
+ IN UCHAR key_id,
+ IN UCHAR *tx_iv,
+ OUT UCHAR *iv_hdr)
+{
+ iv_hdr[0] = key_id;
+ iv_hdr[1] = 0x00;
+
+ NdisMoveMemory(&iv_hdr[2], tx_iv, LEN_WAPI_TSC);
+}
+
+VOID RTMPDeriveWapiGTK(
+ IN PUCHAR nmk,
+ OUT PUCHAR gtk_ptr)
+{
+ const char group_context[100] = "multicast or station key expansion for station unicast and multicast and broadcast";
+
+ NdisZeroMemory(gtk_ptr, 32);
+ kd_hmac_sha256(nmk,
+ 16,
+ (UCHAR *)group_context,
+ strlen(group_context),
+ gtk_ptr,
+ 32);
+}
+
+VOID RT_SMS4_TEST(
+ IN UINT8 test)
+{
+ CIPHER_KEY CipherKey;
+ UINT16 data_len;
+ UINT8 rcvd_data[50];
+ UINT8 mac_hdr_qos[] = {0x88, 0x42, 0x00, 0x00, 0x08, 0xda, 0x75, 0x84,
+ 0xd0, 0xcc, 0x27, 0xe8, 0x72, 0xaa, 0x2c, 0xb9,
+ 0x6b, 0xbb, 0xea, 0x35, 0xa4, 0x20, 0x1e, 0xd2,
+ 0xcf, 0x14};
+
+ UINT8 payload_qos[] = {0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00};
+ UINT8 pn[] = {0x98, 0xba, 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76,
+ 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89};
+ UINT8 key[] = {0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe,
+ 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01,
+ 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01,
+ 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe};
+
+ RTMPSoftEncryptSMS4(mac_hdr_qos,
+ payload_qos,
+ 1,
+ 1,
+ key,
+ pn);
+
+ hex_dump("encrypted payload", payload_qos, 17);
+
+ NdisZeroMemory(&CipherKey, sizeof(CIPHER_KEY));
+ NdisMoveMemory(CipherKey.Key, key, 16);
+ NdisMoveMemory(CipherKey.TxMic, &key[16], 8);
+ NdisMoveMemory(CipherKey.RxMic, &key[24], 8);
+ CipherKey.KeyLen = 16;
+
+
+ NdisZeroMemory(rcvd_data, 50);
+ rcvd_data[0] = 1;
+ data_len = 2;
+ NdisMoveMemory(&rcvd_data[data_len], pn, 16);
+ data_len += 16;
+ NdisMoveMemory(&rcvd_data[data_len], payload_qos, 17);
+ data_len += 17;
+
+
+ if (RTMPSoftDecryptSMS4(mac_hdr_qos,
+ FALSE,
+ &CipherKey,
+ rcvd_data,
+ &data_len) == 0)
+ hex_dump("decrypted payload", rcvd_data, data_len);
+ else
+ printk("decrypted fail\n");
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ In kernel mode read parameters from file
+
+ Arguments:
+ src the location of the file.
+ dest put the parameters to the destination.
+ Length size to read.
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+void rtmp_read_wapi_parms_from_file(
+ IN PRTMP_ADAPTER pAd,
+ PSTRING tmpbuf,
+ PSTRING buffer)
+{
+ UINT32 ip_addr;
+#ifdef CONFIG_AP_SUPPORT
+ INT apidx = 0;
+#endif /* CONFIG_AP_SUPPORT */
+ STRING tok_str[32];
+ INT idx;
+
+ PCOMMON_WAPI_INFO pInfo = &pAd->CommonCfg.comm_wapi_info;
+
+ /* wapi interface name */
+ if (RTMPGetKeyParameter("Wapiifname", tmpbuf, 32, buffer, TRUE))
+ {
+ if (strlen(tmpbuf) > 0)
+ {
+ NdisMoveMemory(pInfo->wapi_ifname, tmpbuf, strlen(tmpbuf));
+ pInfo->wapi_ifname_len = strlen(tmpbuf);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Wapiifname=%s, len=%d\n",
+ pInfo->wapi_ifname,
+ pInfo->wapi_ifname_len));
+ }
+ }
+
+
+ /* WapiAsCertPath */
+ if (RTMPGetKeyParameter("WapiAsCertPath", tmpbuf, 128, buffer, TRUE))
+ {
+ if (strlen(tmpbuf) > 0)
+ {
+ NdisMoveMemory(pInfo->as_cert_path[0], tmpbuf, strlen(tmpbuf));
+ pInfo->as_cert_path_len[0] = strlen(tmpbuf);
+ pInfo->as_cert_no = 1;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WapiAsCertPath=%s, len=%d\n",
+ pInfo->as_cert_path[0],
+ pInfo->as_cert_path_len[0]));
+ }
+ }
+
+ /* WapiAsCertPath2 ~ WapiAsCertPath10 */
+ for (idx = 1; idx < MAX_ID_NO; idx++)
+ {
+ sprintf(tok_str, "WapiAsCertPath%d", idx + 1);
+
+ if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, TRUE))
+ {
+ if (strlen(tmpbuf) > 0)
+ {
+ NdisMoveMemory(pInfo->as_cert_path[idx], tmpbuf, strlen(tmpbuf));
+ pInfo->as_cert_path_len[idx] = strlen(tmpbuf);
+ pInfo->as_cert_no++;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WapiAsCertPath%d=%s, len=%d\n",
+ idx+1,
+ pInfo->as_cert_path[idx],
+ pInfo->as_cert_path_len[idx]));
+ }
+ }
+ }
+
+ /* WapiCaCertPath */
+ if (RTMPGetKeyParameter("WapiCaCertPath", tmpbuf, 128, buffer, TRUE))
+ {
+ if (strlen(tmpbuf) > 0)
+ {
+ NdisMoveMemory(pInfo->ca_cert_path, tmpbuf, strlen(tmpbuf));
+ pInfo->ca_cert_path_len = strlen(tmpbuf);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WapiCaCertPath=%s, len=%d\n",
+ pInfo->ca_cert_path,
+ pInfo->ca_cert_path_len));
+ }
+ }
+
+ /* WapiUserCertPath */
+ if (RTMPGetKeyParameter("WapiUserCertPath", tmpbuf, 128, buffer, TRUE))
+ {
+ if (strlen(tmpbuf) > 0)
+ {
+ NdisMoveMemory(pInfo->user_cert_path, tmpbuf, strlen(tmpbuf));
+ pInfo->user_cert_path_len = strlen(tmpbuf);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WapiUserCertPath=%s, len=%d\n",
+ pInfo->user_cert_path,
+ pInfo->user_cert_path_len));
+ }
+ }
+
+ /* WapiAsIpAddr */
+ if (RTMPGetKeyParameter("WapiAsIpAddr", tmpbuf, 32, buffer, TRUE))
+ {
+ if (rtinet_aton(tmpbuf, &ip_addr))
+ {
+ pInfo->wapi_as_ip = ip_addr;
+ DBGPRINT(RT_DEBUG_TRACE, ("WapiAsIpAddr=%s(%x)\n", tmpbuf, pInfo->wapi_as_ip));
+ }
+ }
+
+ /* WapiAsPort */
+ if (RTMPGetKeyParameter("WapiAsPort", tmpbuf, 32, buffer, TRUE))
+ {
+ pInfo->wapi_as_port = simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("WapiAsPort=%d\n", pInfo->wapi_as_port));
+ }
+
+ /* WapiUskRekeyMethod */
+ if (RTMPGetKeyParameter("WapiUskRekeyMethod", tmpbuf, 32, buffer, TRUE))
+ {
+ if ((strcmp(tmpbuf, "TIME") == 0) || (strcmp(tmpbuf, "time") == 0))
+ pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_TIME;
+ else if ((strcmp(tmpbuf, "PKT") == 0) || (strcmp(tmpbuf, "pkt") == 0))
+ pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_PKT;
+ else
+ pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_DISABLE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WapiUskRekeyMethod=%d\n", pAd->CommonCfg.wapi_usk_rekey_method));
+ }
+
+ /* WapiUskRekeyThreshold */
+ if (RTMPGetKeyParameter("WapiUskRekeyThreshold", tmpbuf, 32, buffer, TRUE))
+ {
+ pAd->CommonCfg.wapi_usk_rekey_threshold = simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("WapiUskRekeyThreshold=%d\n", pAd->CommonCfg.wapi_usk_rekey_threshold));
+ }
+
+ /* WapiMskRekeyMethod */
+ if (RTMPGetKeyParameter("WapiMskRekeyMethod", tmpbuf, 32, buffer, TRUE))
+ {
+ if ((strcmp(tmpbuf, "TIME") == 0) || (strcmp(tmpbuf, "time") == 0))
+ pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_TIME;
+ else if ((strcmp(tmpbuf, "PKT") == 0) || (strcmp(tmpbuf, "pkt") == 0))
+ pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_PKT;
+ else
+ pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_DISABLE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WapiMskRekeyMethod=%d\n", pAd->CommonCfg.wapi_msk_rekey_method));
+ }
+
+ /* WapiMskRekeyThreshold */
+ if (RTMPGetKeyParameter("WapiMskRekeyThreshold", tmpbuf, 32, buffer, TRUE))
+ {
+ pAd->CommonCfg.wapi_msk_rekey_threshold = simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("WapiMskRekeyThreshold=%d\n", pAd->CommonCfg.wapi_msk_rekey_threshold));
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ STRING tok_str[16];
+
+ /* WapiPskX */
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ snprintf(tok_str, sizeof(tok_str), "WapiPsk%d", apidx + 1);
+
+ NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].WAPIPassPhrase, 64);
+ pAd->ApCfg.MBSSID[apidx].WAPIPassPhraseLen = 0;
+ if(RTMPGetKeyParameter(tok_str, tmpbuf, 65, buffer, FALSE))
+ {
+ if (strlen(tmpbuf) >= 8 && strlen(tmpbuf) <= 64)
+ {
+ NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].WAPIPassPhrase, tmpbuf, strlen(tmpbuf));
+ pAd->ApCfg.MBSSID[apidx].WAPIPassPhraseLen = strlen(tmpbuf);
+ DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) WapiPsk=(%s), len=%d\n", apidx, tmpbuf, strlen(tmpbuf)));
+ }
+ else
+ {
+ if (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWAIPSK)
+ {
+ pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeOpen;
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11EncryptionDisabled;
+ }
+ DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) The length of WAPI PSKPassPhrase is invalid(len=%d). \n", apidx, strlen(tmpbuf)));
+ }
+ }
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+ /* WapiPskType */
+ if (RTMPGetKeyParameter("WapiPskType", tmpbuf, 32, buffer, TRUE))
+ {
+ INT err;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ PSTRING macptr;
+
+ for (apidx = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), apidx++)
+ {
+ err = 0;
+
+ if (apidx >= pAd->ApCfg.BssidNum)
+ break;
+
+ /* HEX */
+ if(simple_strtol(macptr, 0, 10) == 0)
+ {
+ pAd->ApCfg.MBSSID[apidx].WapiPskType = HEX_MODE;
+
+ if (pAd->ApCfg.MBSSID[apidx].WAPIPassPhraseLen % 2 != 0)
+ {
+ err = 1;
+ DBGPRINT(RT_DEBUG_ERROR, ("I/F(ra%d) The WAPI-PSK key length MUST be even in Hex mode\n", apidx));
+ }
+ }
+ /* ASCII */
+ else
+ {
+ pAd->ApCfg.MBSSID[apidx].WapiPskType = ASCII_MODE;
+ }
+
+ if (err)
+ {
+ pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeOpen;
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11EncryptionDisabled;
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WapiPskType=%s\n", apidx, (pAd->ApCfg.MBSSID[apidx].WapiPskType == HEX_MODE) ? "HEX" : "ASCII"));
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ }
+
+ /* Sanity check - USK rekey parameter */
+ if (pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_DISABLE ||
+ pAd->CommonCfg.wapi_usk_rekey_threshold == 0)
+ {
+ pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_DISABLE;
+ pAd->CommonCfg.wapi_usk_rekey_threshold = 0;
+ }
+
+ /* Sanity check - MSK rekey parameter */
+ if (pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_DISABLE ||
+ pAd->CommonCfg.wapi_msk_rekey_threshold == 0)
+ {
+ pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_DISABLE;
+ pAd->CommonCfg.wapi_msk_rekey_threshold = 0;
+ }
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ It only shall be queried by wapi daemon for querying the related
+ configuration. This routine process the WAPI configuration for per BSS.
+
+ ==========================================================================
+*/
+static VOID RTMPQueryWapiConfPerBss(
+ IN PRTMP_ADAPTER pAd,
+ IN PWAPI_CONF wapi_conf_ptr,
+ IN UCHAR apidx)
+{
+ PMBSS_WAPI_INFO pConf = &wapi_conf_ptr->mbss_wapi_info[apidx];
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx];
+
+ if (pMbss->MSSIDDev != NULL)
+ {
+ PNET_DEV dev = pMbss->MSSIDDev;
+
+ NdisMoveMemory(pConf->ifname, RtmpOsGetNetDevName(dev), strlen(RtmpOsGetNetDevName(dev)));
+ pConf->ifname_len = strlen(RtmpOsGetNetDevName(dev));
+ }
+ else
+ {
+ STRING slot_name[IFNAMSIZ];
+
+ snprintf(slot_name, sizeof(slot_name), "ra%d", apidx);
+ NdisMoveMemory(pConf->ifname, slot_name, strlen(slot_name));
+ pConf->ifname_len = strlen(slot_name);
+ }
+
+ /* Decide the authentication mode */
+ if (pMbss->AuthMode == Ndis802_11AuthModeWAICERT)
+ pConf->auth_mode = WAPI_AUTH_CERT;
+ else if (pMbss->AuthMode == Ndis802_11AuthModeWAIPSK)
+ pConf->auth_mode = WAPI_AUTH_PSK;
+ else
+ pConf->auth_mode = WAPI_AUTH_DISABLE;
+
+ /* Fill in WAI pre-shared key */
+ if (pMbss->WAPIPassPhraseLen > 0)
+ {
+ if (pMbss->WapiPskType == HEX_MODE)
+ {
+ pConf->psk_len = pMbss->WAPIPassPhraseLen / 2;
+ AtoH((PSTRING) pMbss->WAPIPassPhrase, (PUCHAR) pConf->psk, pConf->psk_len);
+ }
+ else
+ {
+ pConf->psk_len = pMbss->WAPIPassPhraseLen;
+ NdisMoveMemory(pConf->psk, pMbss->WAPIPassPhrase, pConf->psk_len);
+ }
+ }
+
+ /* Fill in WIE */
+ if (pMbss->RSNIE_Len[0] > 0)
+ {
+ pConf->wie_len = pMbss->RSNIE_Len[0] + 2;
+
+ pConf->wie[0] = IE_WAPI;
+ pConf->wie[1] = pMbss->RSNIE_Len[0];
+ NdisMoveMemory(&pConf->wie[2], pMbss->RSN_IE[0], pMbss->RSNIE_Len[0]);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ It only shall be queried by wapi daemon for querying the related
+ configuration.
+ Arguments:
+ pAd Pointer to our adapter
+ wrq Pointer to the ioctl argument
+ ==========================================================================
+*/
+VOID RTMPIoctlQueryWapiConf(
+ IN PRTMP_ADAPTER pAd,
+ IN RTMP_IOCTL_INPUT_STRUCT *wrq)
+{
+ UCHAR apidx;
+ UCHAR *buf = NULL;
+ PWAPI_CONF pConf;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlQueryWapiConf==>\n"));
+
+ /* Allocate memory for WAPI configuration */
+ os_alloc_mem(NULL, (PUCHAR *)&buf, sizeof(WAPI_CONF));
+
+ if (buf == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: allocate memory fail\n", __FUNCTION__));
+ return;
+ }
+
+ pConf = (PWAPI_CONF)buf;
+
+ NdisZeroMemory((PUCHAR)pConf, sizeof(WAPI_CONF));
+
+ /* get MBSS number */
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ pConf->mbss_num = pAd->ApCfg.BssidNum;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Set common configuration */
+ NdisMoveMemory(&pConf->comm_wapi_info, &pAd->CommonCfg.comm_wapi_info, sizeof(COMMON_WAPI_INFO));
+
+ for (apidx = 0; apidx < pConf->mbss_num; apidx++)
+ {
+ RTMPQueryWapiConfPerBss(pAd, pConf, apidx);
+ }
+
+ wrq->u.data.length = sizeof(WAPI_CONF);
+ if (copy_to_user(wrq->u.data.pointer, pConf, wrq->u.data.length))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: copy_to_user() fail\n", __FUNCTION__));
+ }
+
+ os_free_mem(NULL, buf);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Timer execution function for periodically updating WAPI key.
+ Return:
+ ==========================================================================
+*/
+VOID RTMPWapiUskRekeyPeriodicExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ UINT32 tmp_cnt = 0;
+ PMAC_TABLE_ENTRY pEntry = (PMAC_TABLE_ENTRY)FunctionContext;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd;
+
+
+ if (pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_TIME)
+ {
+ tmp_cnt = (++pEntry->wapi_usk_rekey_cnt);
+ }
+ else if (pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT)
+ {
+ /* the unit is 1K packets */
+ tmp_cnt = pEntry->wapi_usk_rekey_cnt/1000;
+ }
+ else
+ return;
+
+ /* Trigger rekey procedure */
+ if (tmp_cnt > pAd->CommonCfg.wapi_usk_rekey_threshold)
+ {
+ pEntry->wapi_usk_rekey_cnt = 0;
+ WAPI_InternalCmdAction(pAd,
+ pEntry->AuthMode,
+ pEntry->apidx,
+ pEntry->Addr,
+ WAI_MLME_UPDATE_USK);
+ }
+
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Timer execution function for periodically updating WAPI key.
+ Return:
+ ==========================================================================
+*/
+VOID RTMPWapiMskRekeyPeriodicExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ UINT i;
+ UINT32 tmp_cnt = 0;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
+
+
+ /* if no any WAPI STA associated, don't do anything. */
+ if (pAd->MacTab.fAnyWapiStation == FALSE)
+ return;
+
+ /* increase counter for TIME method */
+ if (pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_TIME)
+ {
+ tmp_cnt = (++pAd->CommonCfg.wapi_msk_rekey_cnt);
+ }
+ else if (pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_PKT)
+ {
+ /* the unit is 1K packets */
+ tmp_cnt = pAd->CommonCfg.wapi_msk_rekey_cnt/1000;
+ }
+ else
+ return;
+
+ if (tmp_cnt > pAd->CommonCfg.wapi_msk_rekey_threshold)
+ {
+ pAd->CommonCfg.wapi_msk_rekey_cnt = 0;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ INT apidx = 0;
+ UINT cnt;
+
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ UINT m_wcid;
+
+ pAd->ApCfg.MBSSID[apidx].DefaultKeyId = pAd->ApCfg.MBSSID[apidx].DefaultKeyId == 0 ? 1 : 0;
+ inc_iv_byte(pAd->ApCfg.MBSSID[apidx].key_announce_flag, LEN_WAPI_TSC, 1);
+
+ /* Generate NMK randomly */
+ for (cnt = 0; cnt < 16; cnt++)
+ pAd->ApCfg.MBSSID[apidx].NMK[cnt] = RandomByte(pAd);
+
+ RTMPDeriveWapiGTK(pAd->ApCfg.MBSSID[apidx].NMK, pAd->ApCfg.MBSSID[apidx].GTK);
+
+ GET_GroupKey_WCID(pAd, m_wcid, apidx);
+ /* Install Shared key */
+ WAPIInstallSharedKey(pAd,
+ pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus,
+ apidx,
+ pAd->ApCfg.MBSSID[apidx].DefaultKeyId,
+ m_wcid,
+ pAd->ApCfg.MBSSID[apidx].GTK);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ MAC_TABLE_ENTRY *pEntry;
+
+ pEntry = &pAd->MacTab.Content[i];
+ if (IS_ENTRY_CLIENT(pEntry) &&
+ (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled) &&
+ (pEntry->PortSecured == WPA_802_1X_PORT_SECURED))
+ {
+ WAPI_InternalCmdAction(pAd,
+ pEntry->AuthMode,
+ pEntry->apidx,
+ pEntry->Addr,
+ WAI_MLME_UPDATE_MSK);
+ }
+ }
+ }
+
+}
+
+
+VOID RTMPInitWapiRekeyTimerAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry)
+{
+ if (pEntry)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, (" RTMPInitWapiRekeyTimerAction : WAPI USK rekey timer (wcid-%d) \n", pEntry->Aid));
+ RTMPInitTimer(pAd, &pEntry->WapiUskRekeyTimer, GET_TIMER_FUNCTION(RTMPWapiUskRekeyPeriodicExec), pEntry, TRUE);
+ pEntry->WapiUskRekeyTimerRunning = FALSE;
+ }
+ else
+ {
+ RTMPInitTimer(pAd, &pAd->CommonCfg.WapiMskRekeyTimer, GET_TIMER_FUNCTION(RTMPWapiMskRekeyPeriodicExec), pAd, TRUE);
+ pAd->CommonCfg.WapiMskRekeyTimerRunning = FALSE;
+ }
+}
+
+VOID RTMPStartWapiRekeyTimerAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry)
+{
+ if (pEntry)
+ {
+ if ((pAd->CommonCfg.wapi_usk_rekey_method != REKEY_METHOD_DISABLE) &&
+ (pAd->CommonCfg.wapi_usk_rekey_threshold > 0))
+ {
+ /* Regularly check the timer */
+ if (pEntry->WapiUskRekeyTimerRunning == FALSE)
+ {
+ RTMPSetTimer(&pEntry->WapiUskRekeyTimer, WAPI_KEY_UPDATE_EXEC_INTV);
+
+ pEntry->WapiUskRekeyTimerRunning = TRUE;
+ pEntry->wapi_usk_rekey_cnt = 0;
+ DBGPRINT(RT_DEBUG_TRACE, (" RTMPStartWapiRekeyTimerAction : WAPI USK rekey timer is started (%d) \n", pAd->CommonCfg.wapi_usk_rekey_threshold));
+ }
+ }
+ }
+ else
+ {
+ if ((pAd->CommonCfg.wapi_msk_rekey_method != REKEY_METHOD_DISABLE) &&
+ (pAd->CommonCfg.wapi_msk_rekey_threshold > 0))
+ {
+ /* Regularly check the timer */
+ if (pAd->CommonCfg.WapiMskRekeyTimerRunning == FALSE)
+ {
+ RTMPSetTimer(&pAd->CommonCfg.WapiMskRekeyTimer, WAPI_KEY_UPDATE_EXEC_INTV);
+
+ pAd->CommonCfg.WapiMskRekeyTimerRunning = TRUE;
+ pAd->CommonCfg.wapi_msk_rekey_cnt = 0;
+ DBGPRINT(RT_DEBUG_TRACE, (" RTMPStartWapiRekeyTimerAction : WAPI MSK rekey timer is started \n"));
+ }
+ }
+ }
+
+}
+
+VOID RTMPCancelWapiRekeyTimerAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry)
+{
+ if(pEntry)
+ {
+ if (pEntry->WapiUskRekeyTimerRunning == TRUE)
+ {
+ BOOLEAN Cancelled;
+
+ RTMPCancelTimer(&pEntry->WapiUskRekeyTimer, &Cancelled);
+ pEntry->wapi_usk_rekey_cnt = 0;
+ pEntry->WapiUskRekeyTimerRunning = FALSE;
+ }
+ }
+ else
+ {
+ if (pAd->CommonCfg.WapiMskRekeyTimerRunning == TRUE)
+ {
+ BOOLEAN Cancelled;
+
+ RTMPCancelTimer(&pAd->CommonCfg.WapiMskRekeyTimer, &Cancelled);
+ pAd->CommonCfg.wapi_msk_rekey_cnt = 0;
+ pAd->CommonCfg.WapiMskRekeyTimerRunning = FALSE;
+ }
+ }
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Prepare a L2 frame to wapi daemon to trigger WAPI state machine
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+BOOLEAN WAPI_InternalCmdAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR AuthMode,
+ IN UCHAR apidx,
+ IN PUCHAR pAddr,
+ IN UCHAR flag)
+{
+ if ((AuthMode == Ndis802_11AuthModeWAICERT) ||
+ (AuthMode == Ndis802_11AuthModeWAIPSK))
+ {
+ UCHAR WAPI_IE[] = {0x88, 0xb4};
+ UINT8 frame_len = LENGTH_802_3 + 12; /* 12 indicates the WAPI internal command length */
+ UCHAR FrameBuf[frame_len];
+ UINT8 offset = 0;
+
+ /* Init the frame buffer */
+ NdisZeroMemory(FrameBuf, frame_len);
+
+ /* Prepare the 802.3 header */
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ MAKE_802_3_HEADER(FrameBuf, pAd->ApCfg.MBSSID[apidx].Bssid, pAddr, WAPI_IE);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ offset += LENGTH_802_3;
+
+ /* Prepare the specific WAPI header */
+ NdisMoveMemory(&FrameBuf[offset], RALINK_OUI, 3);
+ offset += 3;
+
+ /* Set the state of this command */
+ FrameBuf[offset] = flag;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Trigger WAPI for this sta(%02x:%02x:%02x:%02x:%02x:%02x)\n", PRINT_MAC(pAddr)));
+
+ /* Report to upper layer */
+ if (RTMP_L2_FRAME_TX_ACTION(pAd, apidx, FrameBuf, frame_len) == FALSE)
+ return FALSE;
+
+ }
+
+ return TRUE;
+}
+
+
+VOID RTMPGetWapiTxTscFromAsic(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT Wcid,
+ OUT UCHAR *tx_tsc)
+{
+ USHORT offset;
+ int i;
+
+ if (IS_HW_WAPI_SUPPORT(pAd))
+ {
+ NdisZeroMemory(tx_tsc, LEN_WAPI_TSC);
+
+ /* Read IVEIV from Asic */
+ offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE);
+ for (i=0 ; i < HW_IVEIV_ENTRY_SIZE; i++)
+ RTMP_IO_READ8(pAd, offset+i, &tx_tsc[i]);
+
+ /* Read WAPI PM from Asic */
+ offset = WAPI_PN_TABLE_BASE + (Wcid * WAPI_PN_ENTRY_SIZE);
+ for (i=0 ; i < WAPI_PN_ENTRY_SIZE; i++)
+ RTMP_IO_READ8(pAd, offset+i, &tx_tsc[HW_IVEIV_ENTRY_SIZE + i]);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s : WCID(%d) ", __FUNCTION__, Wcid));
+ hex_dump("TxTsc", tx_tsc, LEN_WAPI_TSC);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("%s : Not support HW_WAPI_PN_TABLE\n",
+ __FUNCTION__));
+ }
+
+}
+
+
+VOID WAPIInstallPairwiseKey(
+ PRTMP_ADAPTER pAd,
+ PMAC_TABLE_ENTRY pEntry,
+ BOOLEAN bAE)
+{
+ PCIPHER_KEY pKey;
+
+ pKey = &pEntry->PairwiseKey;
+ NdisZeroMemory(pKey, sizeof(CIPHER_KEY));
+
+ /* Assign the pairwise cipher algorithm */
+ if (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled)
+ pKey->CipherAlg = CIPHER_SMS4;
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (wcid-%d)\n",
+ __FUNCTION__, pEntry->Aid));
+ return;
+ }
+
+ /* Prepare pair-wise key material */
+ pKey->KeyLen = LEN_TK;
+ NdisMoveMemory(pKey->Key, &pEntry->PTK[0], 16);
+ NdisMoveMemory(pKey->TxMic, &pEntry->PTK[16], 8);
+ NdisMoveMemory(pKey->RxMic, &pEntry->PTK[24], 8);
+
+ /* Initial TSC for unicast */
+ if (bAE)
+ NdisMoveMemory(pKey->TxTsc, AE_UCAST_PN, LEN_WAPI_TSC);
+ else
+ NdisMoveMemory(pKey->TxTsc, ASUE_UCAST_PN, LEN_WAPI_TSC);
+ NdisZeroMemory(pKey->RxTsc, LEN_WAPI_TSC);
+
+ /* HW_WAPI is supported in RT3883 or later */
+ if (IS_HW_WAPI_SUPPORT(pAd))
+ {
+ UINT32 CONST_WAPI_PN = 0x5C365C36;
+
+ /* Set unicast packet's PN to Asic. */
+ if (bAE)
+ AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, CONST_WAPI_PN + 1, CONST_WAPI_PN);
+ else
+ AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, CONST_WAPI_PN, CONST_WAPI_PN);
+ AsicUpdateWAPIPN(pAd, pEntry->Aid, CONST_WAPI_PN, CONST_WAPI_PN);
+
+ /* Add Pair-wise key to Asic */
+ AsicAddPairwiseKeyEntry(
+ pAd,
+ (UCHAR)pEntry->Aid,
+ &pEntry->PairwiseKey);
+
+ /* update WCID attribute table and IVEIV table for this entry */
+ AsicUpdateWcidAttributeEntry(
+ pAd,
+ pEntry->apidx,
+ pEntry->usk_id,
+ pEntry->PairwiseKey.CipherAlg,
+ (UCHAR)pEntry->Aid,
+ PAIRWISEKEYTABLE);
+ }
+
+}
+
+
+VOID WAPIInstallSharedKey(
+ PRTMP_ADAPTER pAd,
+ UINT8 GroupCipher,
+ UINT8 BssIdx,
+ UINT8 KeyIdx,
+ UINT8 Wcid,
+ PUINT8 pGtk)
+{
+ UINT32 CONST_WAPI_PN = 0x5C365C36;
+ PCIPHER_KEY pSharedKey;
+
+ if (BssIdx >= MAX_MBSSID_NUM(pAd) + MAX_P2P_NUM)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The BSS-index(%d) is out of range for MBSSID link. \n",
+ __FUNCTION__, BssIdx));
+ return;
+ }
+
+ pSharedKey = &pAd->SharedKey[BssIdx][KeyIdx];
+ NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY));
+
+ if (GroupCipher == Ndis802_11EncryptionSMS4Enabled)
+ pSharedKey->CipherAlg = CIPHER_SMS4;
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (IF/ra%d) \n",
+ __FUNCTION__, BssIdx));
+ return;
+ }
+
+ /* Assign key material into SW key table */
+ pSharedKey->KeyLen = LEN_TK;
+ NdisMoveMemory(pSharedKey->Key, pGtk, LEN_TK);
+ NdisMoveMemory(pSharedKey->TxMic, pGtk + 16, LEN_TKIP_MIC);
+ NdisMoveMemory(pSharedKey->RxMic, pGtk + 24, LEN_TKIP_MIC);
+
+ /* Initial TSC for B/Mcast */
+ NdisMoveMemory(pSharedKey->TxTsc, AE_BCAST_PN, LEN_WAPI_TSC);
+ NdisZeroMemory(pSharedKey->RxTsc, LEN_WAPI_TSC);
+
+ /* HW_WAPI is supported in RT3883 or later */
+ if (IS_HW_WAPI_SUPPORT(pAd))
+ {
+ /* Install Group Key to MAC ASIC */
+ AsicAddSharedKeyEntry(
+ pAd,
+ BssIdx,
+ KeyIdx,
+ pSharedKey);
+
+ /* When Wcid isn't zero, it means that this is a Authenticator Role.
+ Only Authenticator entity needs to set HW IE/EIV table (0x6000),
+ WAPI PN table (0x7800)
+ and WCID attribute table (0x6800) for group key. */
+ if (Wcid != 0)
+ {
+ /* Set 16-bytes PN to Asic. */
+ AsicUpdateWCIDIVEIV(pAd, Wcid, CONST_WAPI_PN, CONST_WAPI_PN);
+ AsicUpdateWAPIPN(pAd, Wcid, CONST_WAPI_PN, CONST_WAPI_PN);
+
+ /* update Group key information to ASIC */
+ AsicUpdateWcidAttributeEntry(
+ pAd,
+ BssIdx,
+ KeyIdx,
+ pSharedKey->CipherAlg,
+ Wcid,
+ SHAREDKEYTABLE);
+ }
+ }
+}
+
+#endif /* WAPI_SUPPORT */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/wfd.c b/cleopatre/devkit/mt7601udrv/common/wfd.c
new file mode 100644
index 0000000000..6e612323f9
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/wfd.c
@@ -0,0 +1,823 @@
+/****************************************************************************
+ * Ralink Tech Inc.
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************/
+
+
+#ifdef WFD_SUPPORT
+
+#ifdef OS_ABL_SUPPORT
+#ifdef RT_CFG80211_SUPPORT
+#include <linux/version.h>
+#include <net/cfg80211.h>
+#endif /* RT_CFG80211_SUPPORT */
+#endif /* OS_ABL_SUPPORT */
+
+#include "rt_config.h"
+#include "wfd_cmm.h"
+#ifdef OS_ABL_SUPPORT
+#ifdef RT_CFG80211_SUPPORT
+#include "cfg80211.h"
+#endif /* RT_CFG80211_SUPPORT */
+#endif /* OS_ABL_SUPPORT */
+
+UCHAR WIFIDISPLAY_OUI[] = {0x50, 0x6f, 0x9a, 0x0a};
+
+INT Set_WfdEnable_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ BOOLEAN bEnable;
+
+ bEnable = simple_strtol(arg, 0, 10);
+
+ if (bEnable == TRUE)
+ {
+ pAd->StaCfg.WfdCfg.bWfdEnable = TRUE;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: Enable WFD Support!\n", __FUNCTION__));
+ }
+ else
+ {
+ pAd->StaCfg.WfdCfg.bWfdEnable = FALSE;
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:: Disable WFD Support!\n", __FUNCTION__));
+ }
+
+ return TRUE;
+}
+
+#ifdef RT_CFG80211_SUPPORT
+INT Set_WfdInsertIe_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ BOOLEAN bEnable;
+ CFG80211_CB *pCfg80211_CB = NULL;
+
+ pAd->StaCfg.WfdCfg.bSuppInsertWfdIe = FALSE;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+ if (pAd->pCfg80211_CB != NULL)
+ {
+ pCfg80211_CB = (CFG80211_CB *)pAd->pCfg80211_CB;
+ if (pCfg80211_CB->pCfg80211_Wdev != NULL)
+ {
+ if ((pCfg80211_CB->pCfg80211_Wdev->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) ||
+ (pCfg80211_CB->pCfg80211_Wdev->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO)))
+ {
+ bEnable = simple_strtol(arg, 0, 10);
+
+ if (bEnable == TRUE)
+ {
+ pAd->StaCfg.WfdCfg.bSuppInsertWfdIe = TRUE;
+ pAd->StaCfg.WfdCfg.bWfdEnable = TRUE;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: Enable Insert WFD IE Support for wpa_supplicant!\n", __FUNCTION__));
+ }
+ else
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:: Disable Insert WFD IE Support for wpa_supplicant!\n", __FUNCTION__));
+ }
+ else
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:: Interface mode not support Insert WFD IE for wpa_supplicant!\n", __FUNCTION__));
+
+ }
+ else
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:: pCfg80211_CB->pCfg80211_Wdev is NULL. Not Support Insert WFD IE for wpa_supplicant!\n", __FUNCTION__));
+
+ }
+ else
+#endif
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:: pAd->pCfg80211_CB is NULL. Not Support Insert WFD IE for wpa_supplicant!\n", __FUNCTION__));
+
+ return TRUE;
+}
+#endif /* RT_CFG80211_SUPPORT */
+
+INT Set_WfdDeviceType_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR DeviceType;
+
+ DeviceType = simple_strtol(arg, 0, 10);
+
+ if (DeviceType <= WFD_SOURCE_PRIMARY_SINK)
+ {
+ pAd->StaCfg.WfdCfg.DeviceType = DeviceType;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:: Device Type Not Support!!\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: Device Type = %d\n", __FUNCTION__, pAd->StaCfg.WfdCfg.DeviceType));
+
+ return TRUE;
+}
+
+
+INT Set_WfdCouple_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR coupled;
+
+ if (simple_strtol(arg, 0, 10) == 0)
+ coupled = WFD_COUPLED_NOT_SUPPORT;
+ else if (simple_strtol(arg, 0, 10) == 1)
+ coupled = WFD_COUPLED_SUPPORT;
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:: Coupled out of range!!\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ switch (pAd->StaCfg.WfdCfg.DeviceType)
+ {
+ case WFD_SOURCE:
+ pAd->StaCfg.WfdCfg.SourceCoupled = coupled;
+ break;
+ case WFD_PRIMARY_SINK:
+ case WFD_SECONDARY_SINK:
+ pAd->StaCfg.WfdCfg.SinkCoupled = coupled;
+ break;
+ case WFD_SOURCE_PRIMARY_SINK:
+ pAd->StaCfg.WfdCfg.SourceCoupled = coupled;
+ pAd->StaCfg.WfdCfg.SinkCoupled = coupled;
+ break;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: Device Type = %d, Source Coupled = %d, Sink Coupled = %d\n", __FUNCTION__,
+ pAd->StaCfg.WfdCfg.DeviceType, pAd->StaCfg.WfdCfg.SourceCoupled, pAd->StaCfg.WfdCfg.SinkCoupled));
+
+ return TRUE;
+}
+
+INT Set_WfdSessionAvailable_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ if (simple_strtol(arg, 0, 10) == 0)
+ pAd->StaCfg.WfdCfg.SessionAvail= WFD_SESSION_NOT_AVAILABLE;
+ else if (simple_strtol(arg, 0, 10) == 1)
+ pAd->StaCfg.WfdCfg.SessionAvail = WFD_SESSION_AVAILABLE;
+ else
+ {
+ pAd->StaCfg.WfdCfg.SessionAvail = WFD_SESSION_NOT_AVAILABLE;
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:: Session Available out of range, using default\n", __FUNCTION__, pAd->StaCfg.WfdCfg.SessionAvail));
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: Session Available = %d\n", __FUNCTION__, pAd->StaCfg.WfdCfg.SessionAvail));
+
+ return TRUE;
+}
+
+INT Set_WfdCP_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ if (simple_strtol(arg, 0, 10) == 0)
+ pAd->StaCfg.WfdCfg.CP = WFD_CP_NOT_SUPPORT;
+ else if (simple_strtol(arg, 0, 10) == 1)
+ pAd->StaCfg.WfdCfg.CP = WFD_CP_HDCP20;
+ else
+ {
+ pAd->StaCfg.WfdCfg.CP = WFD_CP_NOT_SUPPORT;
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:: Content Protection out of range, using default\n", __FUNCTION__, pAd->StaCfg.WfdCfg.CP));
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: Content Protection = %d\n", __FUNCTION__, pAd->StaCfg.WfdCfg.CP));
+
+ return TRUE;
+}
+
+
+INT Set_WfdRtspPort_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ INT32 RtspPort;
+
+ RtspPort = simple_strtol(arg, 0, 10);
+
+ if ((RtspPort < 0) || (65535 < RtspPort))
+ {
+ pAd->StaCfg.WfdCfg.RtspPort = WFD_RTSP_DEFAULT_PORT;
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:: RTSP Port out of range, using default\n", __FUNCTION__, pAd->StaCfg.WfdCfg.RtspPort));
+ }
+ else
+ pAd->StaCfg.WfdCfg.RtspPort = RtspPort;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: RTSP Port = %d\n", __FUNCTION__, pAd->StaCfg.WfdCfg.RtspPort));
+
+ return TRUE;
+}
+
+
+INT Set_WfdMaxThroughput_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ INT32 Throughput;
+
+ Throughput = simple_strtol(arg, 0, 10);
+
+ if ((Throughput <= 0)|| (65535 < Throughput))
+ {
+ pAd->StaCfg.WfdCfg.MaxThroughput = WFD_MAX_THROUGHPUT_DEFAULT;
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:: Max Throughput out of range, using default\n", __FUNCTION__, pAd->StaCfg.WfdCfg.MaxThroughput));
+ }
+ else
+ pAd->StaCfg.WfdCfg.MaxThroughput = Throughput;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: Max Throughput = %d\n", __FUNCTION__, pAd->StaCfg.WfdCfg.MaxThroughput));
+
+ return TRUE;
+}
+
+INT Set_WfdLocalIp_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PRT_WFD_CONFIG pWFDCtrl = &pAd->StaCfg.WfdCfg;
+ UINT32 ip_addr;
+
+ rtinet_aton(arg, &ip_addr);
+ printk("IP = %04x\n", ip_addr);
+ pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie[0] = WFD_LOCAL_IP_ADDR_VERSION_IPV4;
+ RTMPMoveMemory(&pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie[1], &ip_addr, sizeof(UINT32));
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: local IP Address = %d.%d.%d.%d\n", __FUNCTION__,
+ pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie[1],
+ pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie[2],
+ pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie[3],
+ pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie[4]));
+
+ return TRUE;
+}
+
+INT Set_PeerRtspPort_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ PRT_WFD_CONFIG pWFDCtrl = &pAd->StaCfg.WfdCfg;
+ UINT32 ip_addr;
+
+ MAC_TABLE_ENTRY *pEntry;
+ USHORT RtspPort = WFD_RTSP_DEFAULT_PORT;
+ UCHAR P2pIdx = P2P_NOT_FOUND;
+ PRT_P2P_CONFIG pP2PCtrl = &pAd->P2pCfg;
+ INT i;
+
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s - P2P peer rtsp port get...\n", __FUNCTION__));
+ if (P2P_GO_ON(pAd) || P2P_CLI_ON(pAd))
+ {
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ pEntry = &pAd->MacTab.Content[i];
+ if (IS_P2P_GO_ENTRY(pEntry) || IS_P2P_CLI_ENTRY(pEntry))
+ {
+ P2pIdx = P2pGroupTabSearch(pAd, pEntry->Addr);
+ DBGPRINT(RT_DEBUG_TRACE, ("P2P Entry[%d][%02x:%02x:%02x:%02x:%02x:%02x]\n", pEntry->P2pInfo.p2pIndex, PRINT_MAC(pEntry->Addr)));
+ DBGPRINT(RT_DEBUG_TRACE, ("RTSP_PORT = %d.\n", pAd->P2pTable.Client[pEntry->P2pInfo.p2pIndex].WfdEntryInfo.rtsp_port));
+ if (P2pIdx != P2P_NOT_FOUND)
+ RtspPort = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.rtsp_port;
+ else
+ {
+ RtspPort = WFD_RTSP_DEFAULT_PORT;
+ DBGPRINT(RT_DEBUG_ERROR, ("OID_802_11_P2P_PEER_RTSP_PORT::P2P not found, use default RTSP port\n"));
+ }
+ if (pEntry->P2pInfo.p2pIndex < MAX_P2P_GROUP_SIZE)
+ P2PPrintP2PEntry(pAd, pEntry->P2pInfo.p2pIndex);
+ break;
+ }
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("OID_802_11_P2P_PEER_RTSP_PORT bssid: %02x:%02x:%02x:%02x:%02x:%02x.\n", PRINT_MAC(pP2PCtrl->CurrentAddress)));
+ }
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_P2P_PEER_RTSP_PORT (=%d)\n", RtspPort));
+
+ return TRUE;
+}
+
+
+VOID WfdMakeWfdIE(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG WfdIeBitmap,
+ OUT PUCHAR pOutBuf,
+ OUT PULONG pIeLen)
+{
+ PRT_WFD_CONFIG pWFDCtrl = &pAd->StaCfg.WfdCfg;
+ UCHAR WfdIEFixed[6] = {0xdd, 0x0c, 0x50, 0x6f, 0x9a, 0x0a}; /* Length will be modified later */
+ PUCHAR pData, pBuf;
+ ULONG TempLen;
+ ULONG Len = 0;
+ INT index, i = 0;
+
+ pData = pOutBuf;
+ *pIeLen = 0;
+
+ if (!pWFDCtrl->bWfdEnable)
+ return;
+
+ RTMPMoveMemory(pData, &WfdIEFixed[0], 6);
+ pData += 6;
+ Len += 6;
+
+ for (index = 0; index < SUBID_WFD_END; index++)
+ {
+ if (WfdIeBitmap & (0x1 << index))
+ {
+ /* To append to WFD Subelement */
+ TempLen = 0;
+ TempLen = InsertWfdSubelmtTlv(pAd, index, NULL, pData, ACTION_WIFI_DIRECT);
+ DBGPRINT(RT_DEBUG_INFO, ("%s(%d) ---->\n", __FUNCTION__, TempLen));
+ for (i=0; i<TempLen; i++)
+ DBGPRINT(RT_DEBUG_INFO, ("%02x ", *(pData+i)));
+ DBGPRINT(RT_DEBUG_INFO, ("\n"));
+
+ Len += TempLen;
+ pData += TempLen;
+ }
+
+ }
+
+ *(pOutBuf+1) = (Len-2);
+ *pIeLen = Len;
+
+ return;
+}
+
+
+ULONG InsertWfdSubelmtTlv(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR SubId,
+ IN PUCHAR pInBuffer,
+ IN PUCHAR pOutBuffer,
+ IN UINT Action)
+{
+ PRT_WFD_CONFIG pWFDCtrl = &pAd->StaCfg.WfdCfg;
+ PUCHAR pDest;
+ ULONG Length, tmpValue = 0;
+ USHORT EidLen = 0;
+
+ pDest = pOutBuffer;
+ RTMPZeroMemory(pDest, 255);
+ *pDest = SubId;
+ pDest += 1;
+ Length = 0;
+
+ switch (SubId)
+ {
+ case SUBID_WFD_DEVICE_INFO:
+ {
+ WFD_DEVICE_INFO DevInfo;
+ PUSHORT pDevInfo = &DevInfo;
+
+ RTMPZeroMemory(&DevInfo, sizeof(WFD_DEVICE_INFO));
+
+ EidLen = SUBID_WFD_DEVICE_INFO_LEN;
+ tmpValue = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest, &tmpValue, 2);
+ DevInfo.DeviceType = pWFDCtrl->DeviceType;
+ DevInfo.SourceCoupled = pWFDCtrl->SourceCoupled;
+ DevInfo.SinkCoupled = pWFDCtrl->SinkCoupled;
+ DevInfo.SessionAvail = pWFDCtrl->SessionAvail;
+ DevInfo.WSD = pWFDCtrl->WSD;
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd)))
+ DevInfo.PC = pWFDCtrl->PC;
+ else
+ DevInfo.PC = WFD_PC_P2P;
+ DevInfo.CP = pWFDCtrl->CP;
+ DevInfo.TimeSync = pWFDCtrl->TimeSync;
+ /* RTMPMoveMemory(pDest + 1, &DevInfo, sizeof(WFD_DEVICE_INFO)); */
+ tmpValue = cpu2be16(*pDevInfo);
+ RTMPMoveMemory((pDest + 2), &tmpValue, 2);
+ tmpValue = cpu2be16(pWFDCtrl->RtspPort);
+ RTMPMoveMemory((pDest + 4), &tmpValue, 2);
+ tmpValue = cpu2be16(pWFDCtrl->MaxThroughput);
+ RTMPMoveMemory((pDest + 6), &tmpValue, 2);
+ Length = 9;
+ break;
+ }
+ case SUBID_WFD_ASSOCIATED_BSSID:
+ {
+ UCHAR AllZero[MAC_ADDR_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+
+ if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP))
+ {
+ EidLen = SUBID_WFD_ASSOCIATED_BSSID_LEN;
+ tmpValue = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest, &tmpValue, 2);
+ Length = EidLen + 3;
+ if (!NdisEqualMemory(AllZero, pAd->CommonCfg.Bssid, MAC_ADDR_LEN) &&
+ (Action == ACTION_GAS_INITIAL_RSP))
+ {
+ RTMPMoveMemory(pDest + 2, pAd->CommonCfg.Bssid, MAC_ADDR_LEN);
+ }
+ }
+ else
+ {
+ if (!NdisEqualMemory(AllZero, pAd->CommonCfg.Bssid, MAC_ADDR_LEN))
+ {
+ EidLen = SUBID_WFD_ASSOCIATED_BSSID_LEN;
+ tmpValue = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest, &tmpValue, 2);
+ RTMPMoveMemory(pDest + 2, pAd->CommonCfg.Bssid, MAC_ADDR_LEN);
+ Length = EidLen + 3;
+ }
+ }
+ break;
+ }
+ case SUBID_WFD_AUDIO_FORMATS:
+ {
+ if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP))
+ {
+ EidLen = SUBID_WFD_AUDIO_FORMATS_LEN;
+ tmpValue = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest, &tmpValue, 2);
+ Length = EidLen + 3;
+ }
+ break;
+ }
+ case SUBID_WFD_VIDEO_FORMATS:
+ {
+ if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP))
+ {
+ EidLen = SUBID_WFD_VIDEO_FORMATS_LEN;
+ tmpValue = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest, &tmpValue, 2);
+ Length = EidLen + 3;
+ }
+ break;
+ }
+ case SUBID_WFD_3D_VIDEO_FORMATS:
+ {
+ if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP))
+ {
+ EidLen = SUBID_WFD_3D_VIDEO_FORMATS_LEN;
+ tmpValue = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest, &tmpValue, 2);
+ Length = EidLen + 3;
+ }
+ break;
+ }
+ case SUBID_WFD_CONTENT_PROTECTION:
+ {
+ if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP))
+ {
+ EidLen = SUBID_WFD_CONTENT_PROTECTION_LEN;
+ tmpValue = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest, &tmpValue, 2);
+ Length = EidLen + 3;
+ }
+ break;
+ }
+ case SUBID_WFD_COUPLED_SINK_INFO:
+ {
+// if ((pWFDCtrl->DeviceType != WFD_SOURCE ) && (pWFDCtrl->SinkCoupled == WFD_COUPLED_SUPPORT))
+ {
+ WFD_COUPLED_SINK_INFO SinkInfo;
+
+ RTMPZeroMemory(&SinkInfo, sizeof(WFD_COUPLED_SINK_INFO));
+ EidLen = SUBID_WFD_COUPLED_SINK_INFO_LEN;
+ tmpValue = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest, &tmpValue, 2);
+ SinkInfo.CoupledStat = pWFDCtrl->CoupledSinkStatus.CoupledStat;
+ RTMPMoveMemory(pDest + 2, &SinkInfo, sizeof(WFD_COUPLED_SINK_INFO));
+ Length = EidLen + 3;
+ }
+ break;
+ }
+ case SUBID_WFD_EXTENDED_CAP:
+ {
+ if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP))
+ {
+ EidLen = SUBID_WFD_EXTENDED_CAP_LEN;
+ tmpValue = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest, &tmpValue, 2);
+ Length = EidLen + 3;
+ }
+ break;
+ }
+ case SUBID_WFD_LOCAL_IP_ADDR:
+ {
+ if ((Action == ACTION_GAS_INITIAL_REQ) || (Action == ACTION_GAS_INITIAL_RSP))
+ {
+ EidLen = SUBID_WFD_LOCAL_IP_ADDR_LEN;
+ tmpValue = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest, &tmpValue, 2);
+ Length = EidLen + 3;
+ }
+ else
+ {
+ EidLen = SUBID_WFD_LOCAL_IP_ADDR_LEN;
+ tmpValue = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest, &tmpValue, 2);
+ RTMPMoveMemory(pDest + 2, &pWFDCtrl->wfd_serv_disc_query_info.wfd_local_ip_ie, SUBID_WFD_LOCAL_IP_ADDR_LEN);
+ Length = EidLen + 3;
+ }
+ break;
+ }
+ case SUBID_WFD_SESSION_INFO:
+ {
+ INT i = 0, NumOfDev = 0;
+ UCHAR P2pIdx = P2P_NOT_FOUND;
+ PRT_P2P_TABLE Tab = &pAd->P2pTable;
+
+ if (P2P_GO_ON(pAd)
+#ifdef RT_CFG80211_SUPPORT
+ || (pWFDCtrl->bSuppGoOn)
+#endif /* RT_CFG80211_SUPPORT */
+ )
+ {
+ for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
+ P2pIdx = P2pGroupTabSearch(pAd, pEntry->Addr);
+
+ if ((P2pIdx < MAX_P2P_GROUP_SIZE) && (Tab->Client[P2pIdx].WfdEntryInfo.bWfdClient == TRUE))
+ NumOfDev++;
+ }
+
+ EidLen = 24*NumOfDev;
+ tmpValue = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest, &tmpValue, 2);
+ DBGPRINT(RT_DEBUG_INFO, ("%s:: NumOfDev = %d, Len = %d\n", __FUNCTION__, NumOfDev, *pDest));
+
+ pDest+=2;
+ for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
+ P2pIdx = P2pGroupTabSearch(pAd, pEntry->Addr);
+
+ if ((P2pIdx < MAX_P2P_GROUP_SIZE) && (Tab->Client[P2pIdx].WfdEntryInfo.bWfdClient == TRUE))
+ {
+ INT j = 0;
+ WFD_SESSION_INFO SessionInfo;
+
+ RTMPZeroMemory(&SessionInfo, sizeof(WFD_SESSION_INFO));
+
+ SessionInfo.Length = 23;
+ RTMPMoveMemory(&SessionInfo.DeviceAddr[0], &pAd->P2pTable.Client[P2pIdx].addr[0], MAC_ADDR_LEN);
+ RTMPMoveMemory(&SessionInfo.Bssid[0], &pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.assoc_addr[0], MAC_ADDR_LEN);
+ /* Below is the WFD Device Information */
+ SessionInfo.WfdDevInfo.DeviceType = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.wfd_devive_type;
+ SessionInfo.WfdDevInfo.SourceCoupled = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.source_coupled;
+ SessionInfo.WfdDevInfo.SinkCoupled = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.sink_coupled;
+ SessionInfo.WfdDevInfo.SessionAvail = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.session_avail;
+ SessionInfo.WfdDevInfo.WSD = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.wfd_service_discovery;
+ SessionInfo.WfdDevInfo.PC = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.wfd_PC;
+ SessionInfo.WfdDevInfo.TimeSync = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.wfd_time_sync;
+ SessionInfo.MaxThroughput = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.max_throughput;
+ SessionInfo.CoupledSinkInfo = pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.coupled_sink_status;
+
+ /*
+ So far we cannot know the address of coupled devices,
+ the coupled address will be filled "0" until WiFi Display spec. is ready for this part.
+ */
+ RTMPMoveMemory(&SessionInfo.CoupledPeerAddr[0], &pAd->P2pTable.Client[P2pIdx].WfdEntryInfo.coupled_peer_addr[0], MAC_ADDR_LEN);
+ RTMPMoveMemory(pDest, &SessionInfo, sizeof(WFD_SESSION_INFO));
+
+ for (j = 0; j < 24; j++)
+ DBGPRINT(RT_DEBUG_INFO, ("%02x ", *(pDest+j)));
+ DBGPRINT(RT_DEBUG_INFO, ("\n"));
+
+ pDest += 24;
+ }
+ }
+
+ Length = 24*NumOfDev + 3;
+ }
+ break;
+ }
+ case SUBID_WFD_ALTERNATE_MAC_ADDR:
+ {
+ UCHAR AllZero[MAC_ADDR_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+
+ if (!NdisEqualMemory(AllZero, pAd->CurrentAddress, MAC_ADDR_LEN))
+ {
+ EidLen = SUBID_WFD_ALTERNATE_MAC_ADDR_LEN;
+ *((PUSHORT) (pDest)) = cpu2be16(EidLen);
+ RTMPMoveMemory(pDest + 2, pAd->CurrentAddress, MAC_ADDR_LEN);
+ Length = EidLen + 3;
+ }
+
+ break;
+ }
+ default:
+ *pDest = 0;
+ Length = 0;
+ break;
+ }
+
+ return Length;
+}
+
+VOID WfdParseSubElmt(
+ IN PRTMP_ADAPTER pAd,
+ IN PWFD_ENTRY_INFO pWfdEntryInfo,
+ IN VOID *Msg,
+ IN ULONG MsgLen)
+{
+ PWFD_COUPLED_SINK_INFO pSinkInfo;
+ PWFD_DEVICE_INFO pWfd_info;
+ WFD_DEVICE_INFO DevInfo;
+ PP2PEID_STRUCT pWfdEid;
+ PEID_STRUCT pEid;
+ PUCHAR pWfdIe = NULL;
+ ULONG AccuWfdIELen;
+ ULONG AccuIeLen = 0;
+ ULONG Length = 0;
+ ULONG AttriLen;
+ UCHAR offset;
+ BOOLEAN bTdlsEntry = FALSE;
+
+ DBGPRINT(RT_DEBUG_INFO, ("%s ----->\n", __FUNCTION__));
+
+//QQ TBD, p2p widi need to parse rtsp port!
+ {
+ if ((!pAd->StaCfg.WfdCfg.bWfdEnable) || (MsgLen == 0))
+ return;
+ }
+
+// hex_dump("WfdParseSubElmt::", Msg, MsgLen);
+ pEid = (PEID_STRUCT)Msg;
+ AccuIeLen = pEid->Len + 2;
+// printk("MsgLen = %d. AccuIeLen = %d.\n", MsgLen, AccuIeLen);
+ while ((ULONG)(AccuIeLen) <= MsgLen)
+ {
+ if (RTMPEqualMemory(&pEid->Octet[0], WIFIDISPLAY_OUI, 4))
+ {
+ /* Get Request content capability */
+ pWfdIe = pWfdEid = (PP2PEID_STRUCT) &pEid->Octet[4];
+ AccuWfdIELen = pEid->Len;
+// printk("AccuWfdIeLen = %d. EidLen = %04x\n", AccuWfdIELen, pEid->Len);
+ /* The value of AccuP2PIELen shall reduce the length of OUI (4) */
+ AccuWfdIELen -= 4;
+
+ AttriLen = pWfdEid->Len[1] + (pWfdEid->Len[0] << 8);
+ Length = 0;
+// printk("AttriLen = %d. WfdEid = %d. WfdEidLen = %x %x\n", AttriLen, pWfdEid->Eid, pWfdEid->Len[1], pWfdEid->Len[0]);
+ pWfdEntryInfo->bWfdClient = TRUE; /* Set the P2P client as the WFD device */
+
+// while (Length <=(Length + 3 + AttriLen) <= AccuWfdIELen)
+ while (Length <= AccuWfdIELen)
+ {
+// printk(">> Eid = %d.\n", pWfdEid->Eid);
+ switch (pWfdEid->Eid)
+ {
+ case SUBID_WFD_DEVICE_INFO:
+ {
+ pWfd_info = &(pWfdEid->Octet[0]);
+ RTMPMoveMemory(&DevInfo, pWfdIe, sizeof(WFD_DEVICE_INFO));
+ RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_device_info_ie, pWfdEid->Octet, SUBID_WFD_DEVICE_INFO_LEN);
+ cpu2le16(&DevInfo);
+
+ pWfdEntryInfo->wfd_devive_type = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 0) & 0x3);
+ pWfdEntryInfo->source_coupled = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 2) & 0x1);
+ pWfdEntryInfo->sink_coupled = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 3) & 0x1);
+ pWfdEntryInfo->session_avail = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 4) & 0x3);
+ pWfdEntryInfo->wfd_service_discovery = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 6) & 0x1);
+ pWfdEntryInfo->wfd_PC = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 7) & 0x1);
+ pWfdEntryInfo->wfd_CP = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 8) & 0x1);
+ pWfdEntryInfo->wfd_time_sync = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 9) & 0x1);
+ pWfdEntryInfo->sink_audio_unsupport = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 10) & 0x1);
+ pWfdEntryInfo->source_audio_only= ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 11) & 0x1);
+ pWfdEntryInfo->tdls_persistent_group = ((be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[0]))) >> 12) & 0x1);
+ pWfdEntryInfo->rtsp_port = be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[2])));
+ pWfdEntryInfo->max_throughput = be2cpu16(get_unaligned((PUSHORT)(&pWfdEid->Octet[4])));
+
+ DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_DEVICE_INFO\n", __FUNCTION__));
+ break;
+ }
+ case SUBID_WFD_ASSOCIATED_BSSID:
+ {
+ RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_associate_bssid_ie, pWfdEid->Octet, SUBID_WFD_ASSOCIATED_BSSID_LEN);
+ RTMPMoveMemory(&pWfdEntryInfo->assoc_addr, pWfdEid->Octet, MAC_ADDR_LEN);
+ DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_ASSOCIATED_BSSID\n", __FUNCTION__));
+ break;
+ }
+ case SUBID_WFD_AUDIO_FORMATS:
+ {
+ RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_audio_format_ie, pWfdEid->Octet, SUBID_WFD_AUDIO_FORMATS_LEN);
+ DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_AUDIO_FORMATS\n", __FUNCTION__));
+ break;
+ }
+ case SUBID_WFD_VIDEO_FORMATS:
+ {
+ RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_video_format_ie, pWfdEid->Octet, SUBID_WFD_VIDEO_FORMATS_LEN);
+ DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_VIDEO_FORMATS\n", __FUNCTION__));
+ break;
+ }
+ case SUBID_WFD_3D_VIDEO_FORMATS:
+ {
+ RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_3d_video_format_ie, pWfdEid->Octet, SUBID_WFD_3D_VIDEO_FORMATS_LEN);
+ DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_3D_VIDEO_FORMATS\n", __FUNCTION__));
+ break;
+ }
+ case SUBID_WFD_CONTENT_PROTECTION:
+ {
+ RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_content_proctection, pWfdEid->Octet, SUBID_WFD_CONTENT_PROTECTION_LEN);
+ DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_CONTENT_PROTECTION\n", __FUNCTION__));
+ break;
+ }
+ case SUBID_WFD_COUPLED_SINK_INFO:
+ {
+ RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_couple_sink_info_ie, pWfdEid->Octet, SUBID_WFD_COUPLED_SINK_INFO_LEN);
+ RTMPMoveMemory(&pWfdEntryInfo->coupled_sink_status, pWfdEid->Octet, SUBID_WFD_COUPLED_SINK_INFO_LEN);
+ DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_COUPLED_SINK_INFO\n", __FUNCTION__));
+ break;
+ }
+ case SUBID_WFD_EXTENDED_CAP:
+ {
+ RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_extent_capability_ie, &pWfdEid->Octet, SUBID_WFD_EXTENDED_CAP_LEN);
+ DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_EXTENDED_CAP\n", __FUNCTION__));
+ break;
+ }
+ case SUBID_WFD_LOCAL_IP_ADDR:
+ {
+ RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_local_ip_ie, &pWfdEid->Octet, SUBID_WFD_LOCAL_IP_ADDR_LEN);
+ DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_LOCAL_IP_ADDR\n", __FUNCTION__));
+ break;
+ }
+ case SUBID_WFD_SESSION_INFO:
+ {
+ /* TODO : allocate memory to store the parsed WFD device tables */
+ RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_session_info_ie, &pWfdEid->Octet, SUBID_WFD_DEVICE_INFO_LEN);
+ DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_SESSION_INFO\n", __FUNCTION__));
+ break;
+ }
+ case SUBID_WFD_ALTERNATE_MAC_ADDR:
+ {
+ RTMPMoveMemory(&pWfdEntryInfo->wfd_serv_disc_query_info.wfd_alternate_mac_addr_ie, &pWfdEid->Octet, SUBID_WFD_ALTERNATE_MAC_ADDR_LEN);
+ DBGPRINT(RT_DEBUG_INFO, ("%s::SUBID_WFD_ALTERNATE_MAC_ADDR\n", __FUNCTION__));
+ break;
+ }
+ default:
+ DBGPRINT(RT_DEBUG_ERROR, (" SUBID_WFD_ unknown Eid = %x \n", pWfdEid->Eid));
+ hex_dump("WfdParseSubElement::", Msg, MsgLen);
+ break;
+ }
+// printk("<< Length = %d. AttriLen = %d. AccuWfdIELen = %d.\n", Length, AttriLen, AccuWfdIELen);
+ Length = Length + 3 + AttriLen; /* Eid[1] + Len[2] + content[Len] */
+// printk(">> Length = %d. AttriLen = %d. AccuWfdIELen = %d.\n", Length, AttriLen, AccuWfdIELen);
+ if (Length >= AccuWfdIELen)
+ break;
+
+ pWfdEid = (PP2PEID_STRUCT)((UCHAR*)pWfdEid + 3 + AttriLen);
+ AttriLen = pWfdEid->Len[1] + (pWfdEid->Len[0] << 8);
+ }
+
+ }
+ /* Already reach the final IE and stop finding next Eid. */
+ if (AccuIeLen >= MsgLen)
+ break;
+
+ /* Forward buffer to next pEid */
+ if (RTMPEqualMemory(&pEid->Octet[0], WIFIDISPLAY_OUI, 4))
+ {
+ pEid = (PEID_STRUCT)((UCHAR*)pEid + pEid->Len + 2);
+ }
+
+ /*
+ Since we get the next pEid,
+ Predict the accumulated IeLen after adding the next pEid's length.
+ The accumulated IeLen is for checking length.
+ */
+ if (RTMPEqualMemory(&pEid->Octet[0], WIFIDISPLAY_OUI, 4))
+ {
+ AccuIeLen += (pEid->Len + 2);
+ }
+ }
+ return;
+}
+
+VOID WfdCfgInit(
+
+ IN PRTMP_ADAPTER pAd)
+{
+ PRT_WFD_CONFIG pWfdcfg = &pAd->StaCfg.WfdCfg;
+
+ RTMPZeroMemory(&pAd->StaCfg.WfdCfg, sizeof(RT_WFD_CONFIG));
+ pWfdcfg->bWfdEnable = TRUE;
+#ifdef RT_CFG80211_SUPPORT
+ pWfdcfg->bSuppInsertWfdIe = FALSE;
+ pWfdcfg->bSuppGoOn = FALSE;
+#endif /* RT_CFG80211_SUPPORT */
+ pWfdcfg->DeviceType = WFD_PRIMARY_SINK;
+ pWfdcfg->SessionAvail = WFD_SESSION_AVAILABLE;
+ pWfdcfg->PeerSessionAvail = WFD_SESSION_AVAILABLE;
+ pWfdcfg->PeerPC = WFD_PC_TDLS;
+ pWfdcfg->TdlsSecurity = WFD_TDLS_STRONG_SECURITY;
+ pWfdcfg->RtspPort = WFD_RTSP_DEFAULT_PORT;
+}
+#endif /* WFD_SUPPORT */
diff --git a/cleopatre/devkit/mt7601udrv/common/wsc.c b/cleopatre/devkit/mt7601udrv/common/wsc.c
new file mode 100644
index 0000000000..ec738598ef
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/wsc.c
@@ -0,0 +1,9058 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2006, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ wsc.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Lin 06-08-08 Initial
+ Snowpin Lee 06-09-12 Do modifications and Add APIs for AP
+ Snowpin Lee 07-04-19 Do modifications and Add APIs for STA
+ Snowpin Lee 07-05-17 Do modifications and Add APIs for AP Client
+*/
+
+#include "rt_config.h"
+
+#ifdef WSC_INCLUDED
+#include "wsc_tlv.h"
+/*#ifdef LINUX */
+/*#include <net/iw_handler.h> */
+/*#endif*/
+
+#define WSC_UPNP_MSG_TIMEOUT (150 * OS_HZ)
+#define RTMP_WSC_NLMSG_SIGNATURE_LEN 8
+#define MAX_WEPKEYNAME_LEN 20
+#define MAX_WEPKEYTYPE_LEN 20
+
+#ifndef PF_NOFREEZE
+#define PF_NOFREEZE 0
+#endif
+
+char WSC_MSG_SIGNATURE[]={"RAWSCMSG"};
+
+extern UCHAR WPS_OUI[];
+extern UCHAR RALINK_OUI[];
+
+
+#if defined(__ECOS) && defined(BRANCH_ADV)
+extern int CFG_set(int id, void *val);
+extern int CFG_str2id(char * var);
+extern int CFG_commit(int id);
+#else
+#define CFG_set(a, b) {}
+#define CFG_str2id(a) {}
+#define CFG_commit(a) {}
+#endif /*__ECOS && BRANCH_ADV */
+
+UINT8 WPS_DH_G_VALUE[1] = {0x02};
+UINT8 WPS_DH_P_VALUE[192] =
+{
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+/* General used field */
+UCHAR STA_Wsc_Pri_Dev_Type[8] = {0x00, 0x01, 0x00, 0x50, 0xf2, 0x04, 0x00, 0x01};
+
+#ifdef CONFIG_AP_SUPPORT
+UCHAR AP_Wsc_Pri_Dev_Type[8] = {0x00, 0x06, 0x00, 0x50, 0xf2, 0x04, 0x00, 0x01};
+
+VOID WscDelWPARetryTimer(
+ IN PRTMP_ADAPTER pAd);
+
+#ifdef APCLI_SUPPORT
+
+VOID WscApCliLinkDown(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWscControl);
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+BOOLEAN WscCheckNonce(
+ IN PRTMP_ADAPTER pAdapter,
+ IN MLME_QUEUE_ELEM *Elem,
+ IN BOOLEAN bFlag,
+ IN PWSC_CTRL pWscControl);
+
+VOID WscEapActionDisabled(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl);
+
+VOID WscGetConfigErrFromNack(
+ IN PRTMP_ADAPTER pAdapter,
+ IN MLME_QUEUE_ELEM *pElem,
+ OUT USHORT *pConfigError);
+
+INT WscSetAuthMode(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR CurOpMode,
+ IN UCHAR apidx,
+ IN PSTRING arg);
+
+INT WscSetEncrypType(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR CurOpMode,
+ IN UCHAR apidx,
+ IN PSTRING arg);
+
+VOID WscSendNACK(
+ IN PRTMP_ADAPTER pAdapter,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN PWSC_CTRL pWscControl);
+
+static INT wsc_write_dat_file_thread(IN ULONG data);
+
+
+VOID WscDelListEntryByMAC(
+ PLIST_HEADER pWscEnList,
+ IN PUCHAR pMacAddr);
+
+NDIS_802_11_AUTHENTICATION_MODE WscGetAuthMode(
+ IN USHORT authFlag);
+
+NDIS_802_11_WEP_STATUS WscGetWepStatus(
+ IN USHORT encryFlag);
+
+/*
+ Standard UUID generation procedure. The UUID format generated by this function is base on UUID std. version 1.
+ It's a 16 bytes, one-time global unique number. and can show in string format like this:
+ 550e8400-e29b-41d4-a716-446655440000
+
+ The format of uuid is:
+ uuid = <time_low> "-"
+ <time_mid> "-"
+ <time_high_and_version> "-"
+ <clock_seq_high_and_reserved>
+ <clock_seq_low> "-"
+ <node>
+ time_low = 4*<hex_octet>
+ time_mid = 2*<hex_octet>
+ time_high_and_version = 2*<hex_octet>
+ clock_seq_high_and_reserved = <hex_octet>
+ clock_seq_low = <hex_octet>
+ node = 6*<hex_octet>
+ hex_octet = <hex_digit> <hex_digit>
+ hex_digit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
+ |"a"|"b"|"c"|"d"|"e"|"f"
+ |"A"|"B"|"C"|"D"|"E"|"F"
+ Note:
+ Actually, to IOT with JumpStart, we fix the first 10 bytes of UUID string!!!!
+*/
+INT WscGenerateUUID(
+ RTMP_ADAPTER *pAd,
+ UCHAR *uuidHexStr,
+ UCHAR *uuidAscStr,
+ int apIdx,
+ BOOLEAN bUseCurrentTime)
+{
+
+ WSC_UUID_T uuid_t;
+ unsigned long long uuid_time;
+ int i;
+ UINT16 clkSeq;
+ char uuidTmpStr[UUID_LEN_STR+2];
+
+
+ /* Get the current time. */
+ if (bUseCurrentTime)
+ {
+ NdisGetSystemUpTime((ULONG *)&uuid_time);
+ }
+ else
+ uuid_time = 2860; /*xtime.tv_sec; // Well, we fix this to make JumpStart happy! */
+ uuid_time *= 10000000;
+ uuid_time += 0x01b21dd213814000LL;
+
+
+
+ uuid_t.timeLow = (UINT32)uuid_time & 0xFFFFFFFF;
+ uuid_t.timeMid = (UINT16)((uuid_time >>32) & 0xFFFF);
+ uuid_t.timeHi_Version = (UINT16)((uuid_time >> 48) & 0x0FFF);
+ uuid_t.timeHi_Version |= (1 << 12);
+
+ /* Get the clock sequence. */
+ clkSeq = (UINT16)(0x0601/*jiffies*/ & 0xFFFF); /* Again, we fix this to make JumpStart happy! */
+
+ uuid_t.clockSeqLow = clkSeq & 0xFF;
+ uuid_t.clockSeqHi_Var = (clkSeq & 0x3F00) >> 8;
+ uuid_t.clockSeqHi_Var |= 0x80;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ /* copy the Mac address as the value of node */
+ NdisMoveMemory(&uuid_t.node[0], &pAd->ApCfg.MBSSID[apIdx].Bssid[0], sizeof(uuid_t.node));
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /* Create the UUID ASCII string. */
+ memset(uuidTmpStr, 0, sizeof(uuidTmpStr));
+ snprintf(uuidTmpStr, sizeof(uuidTmpStr), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (unsigned int)uuid_t.timeLow, uuid_t.timeMid, uuid_t.timeHi_Version, uuid_t.clockSeqHi_Var, uuid_t.clockSeqLow,
+ uuid_t.node[0], uuid_t.node[1], uuid_t.node[2], uuid_t.node[3], uuid_t.node[4], uuid_t.node[5]);
+ if (strlen(uuidTmpStr) > UUID_LEN_STR)
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR:UUID String size too large!\n"));
+ strncpy((PSTRING)uuidAscStr, uuidTmpStr, UUID_LEN_STR);
+
+ /* Create the UUID Hex format number */
+ uuid_t.timeLow = cpu2be32(uuid_t.timeLow);
+ NdisMoveMemory(&uuidHexStr[0], &uuid_t.timeLow, 4);
+ uuid_t.timeMid = cpu2be16(uuid_t.timeMid);
+ NdisMoveMemory(&uuidHexStr[4], &uuid_t.timeMid, 2);
+ uuid_t.timeHi_Version = cpu2be16(uuid_t.timeHi_Version);
+ NdisMoveMemory(&uuidHexStr[6], &uuid_t.timeHi_Version, 2);
+ NdisMoveMemory(&uuidHexStr[8], &uuid_t.clockSeqHi_Var, 1);
+ NdisMoveMemory(&uuidHexStr[9], &uuid_t.clockSeqLow, 1);
+ NdisMoveMemory(&uuidHexStr[10], &uuid_t.node[0], 6);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("The UUID Hex string is:"));
+ for (i=0; i< 16; i++)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%02x", (uuidHexStr[i] & 0xff)));
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("The UUID ASCII string is:%s!\n", uuidAscStr));
+ return 0;
+}
+
+VOID WscInitCommonTimers(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl)
+{
+ WSC_TIMER_INIT(pAdapter, pWscControl, &pWscControl->EapolTimer, pWscControl->EapolTimerRunning, WscEAPOLTimeOutAction);
+ WSC_TIMER_INIT(pAdapter, pWscControl, &pWscControl->Wsc2MinsTimer, pWscControl->Wsc2MinsTimerRunning, Wsc2MinsTimeOutAction);
+ WSC_TIMER_INIT(pAdapter, pWscControl, &pWscControl->WscUPnPNodeInfo.UPnPMsgTimer, pWscControl->WscUPnPNodeInfo.bUPnPMsgTimerRunning, WscUPnPMsgTimeOutAction);
+ pWscControl->WscUPnPNodeInfo.bUPnPMsgTimerPending = FALSE;
+ WSC_TIMER_INIT(pAdapter, pWscControl, &pWscControl->M2DTimer, pWscControl->bM2DTimerRunning, WscM2DTimeOutAction);
+
+#ifdef WSC_LED_SUPPORT
+ WSC_TIMER_INIT(pAdapter, pWscControl, &pWscControl->WscLEDTimer, pWscControl->WscLEDTimerRunning, WscLEDTimer);
+ WSC_TIMER_INIT(pAdapter, pWscControl, &pWscControl->WscSkipTurnOffLEDTimer, pWscControl->WscSkipTurnOffLEDTimerRunning, WscSkipTurnOffLEDTimer);
+#endif /* WSC_LED_SUPPORT */
+}
+
+VOID WscInitClientTimers(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWScControl)
+{
+ WSC_TIMER_INIT(pAdapter, pWScControl, &pWScControl->WscPBCTimer, pWScControl->WscPBCTimerRunning, WscPBCTimeOutAction);
+ WSC_TIMER_INIT(pAdapter, pWScControl, &pWScControl->WscScanTimer, pWScControl->WscScanTimerRunning, WscScanTimeOutAction);
+ WSC_TIMER_INIT(pAdapter, pWScControl, &pWScControl->WscProfileRetryTimer, pWScControl->WscProfileRetryTimerRunning, WscProfileRetryTimeout); /* add by johnli, fix WPS test plan 5.1.1 */
+}
+
+/*
+ ==========================================================================
+ Description:
+ wps state machine init, including state transition and timer init
+ Parameters:
+ S - pointer to the association state machine
+ ==========================================================================
+ */
+VOID WscStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ OUT STATE_MACHINE_FUNC Trans[])
+{
+ PWSC_CTRL pWScControl;
+ StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_WSC_STATE, MAX_WSC_MSG, (STATE_MACHINE_FUNC)Drop, WSC_IDLE, WSC_MACHINE_BASE);
+ StateMachineSetAction(S, WSC_IDLE, WSC_EAPOL_START_MSG, (STATE_MACHINE_FUNC)WscEAPOLStartAction);
+ StateMachineSetAction(S, WSC_IDLE, WSC_EAPOL_PACKET_MSG, (STATE_MACHINE_FUNC)WscEAPAction);
+ StateMachineSetAction(S, WSC_IDLE, WSC_EAPOL_UPNP_MSG, (STATE_MACHINE_FUNC)WscEAPAction);
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ UCHAR apidx;
+
+ for (apidx = 0; apidx < MAX_MBSSID_NUM(pAd); apidx++)
+ {
+ pWScControl = &pAd->ApCfg.MBSSID[apidx].WscControl;
+ pWScControl->EntryIfIdx= (MIN_NET_DEVICE_FOR_MBSSID | apidx);
+ WscInitCommonTimers(pAd, pWScControl);
+ pWScControl->WscUpdatePortCfgTimerRunning = FALSE;
+ WSC_TIMER_INIT(pAd, pWScControl, &pWScControl->WscUpdatePortCfgTimer, pWScControl->WscUpdatePortCfgTimerRunning, WscUpdatePortCfgTimeout);
+#ifdef WSC_V2_SUPPORT
+ WSC_TIMER_INIT(pAd, pWScControl, &pWScControl->WscSetupLockTimer, pWScControl->WscSetupLockTimerRunning, WscSetupLockTimeout);
+#endif /* WSC_V2_SUPPORT */
+ }
+
+#ifdef APCLI_SUPPORT
+ for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++)
+ {
+ pWScControl = &pAd->ApCfg.ApCliTab[apidx].WscControl;
+ pWScControl->EntryIfIdx= (MIN_NET_DEVICE_FOR_APCLI | apidx);
+ WscInitCommonTimers(pAd, pWScControl);
+ WscInitClientTimers(pAd, pWScControl);
+ }
+#endif /* APCLI_SUPPORT */
+ }
+
+#endif /* CONFIG_AP_SUPPORT */
+
+}
+
+void WscM2DTimeOutAction(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ /* For each state, we didn't care about the retry issue, we just send control message
+ to notify the UPnP deamon that some error happened in STATE MACHINE.
+ */
+ PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pWscControl->pAd;
+ WSC_UPNP_NODE_INFO *pWscNodeInfo;
+#ifdef CONFIG_AP_SUPPORT
+ MAC_TABLE_ENTRY *pEntry = NULL;
+/* UCHAR apidx = MAIN_MBSSID; */
+#endif /* CONFIG_AP_SUPPORT */
+ BOOLEAN Cancelled;
+ UCHAR CurOpMode = 0xFF;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ pEntry = MacTableLookup(pAd, pWscControl->EntryAddr);
+#endif /* CONFIG_AP_SUPPORT */
+ pWscNodeInfo = &pWscControl->WscUPnPNodeInfo;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("UPnP StateMachine TimeOut(State=%d!)\n", pWscControl->WscState));
+
+ if(
+#ifdef CONFIG_AP_SUPPORT
+ (((pEntry == NULL) || (pWscNodeInfo->registrarID != 0)) && (CurOpMode == AP_MODE)) ||
+#endif /* CONFIG_AP_SUPPORT */
+ (0))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():pEntry maybe gone or already received M2 Packet!\n", __FUNCTION__));
+ goto done;
+ }
+
+ if (pWscControl->M2DACKBalance != 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): waiting for M2DACK balance, extend the time!\n", __FUNCTION__));
+ /* Waiting for M2DACK balance. */
+ RTMPModTimer(&pWscControl->M2DTimer, WSC_EAP_ID_TIME_OUT);
+ pWscControl->M2DACKBalance = 0;
+ goto done;
+ }
+ else
+ {
+ RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled);
+ pWscControl->EapolTimerRunning = FALSE;
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): send EAP-Fail to wireless Station!\n", __FUNCTION__));
+ /* Send EAPFail to Wireless Station and reset the status of Wsc. */
+ WscSendEapFail(pAd, pWscControl, TRUE);
+ /*pEntry->bWscCapable = FALSE; */
+ if (pEntry != NULL)
+ pEntry->Receive_EapolStart_EapRspId = 0;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ pWscControl->EapMsgRunning = FALSE;
+ pWscControl->WscState = WSC_STATE_OFF;
+ }
+
+done:
+ pWscControl->bM2DTimerRunning = FALSE;
+ pWscControl->M2DACKBalance = 0;
+ pWscNodeInfo->registrarID = 0;
+
+
+}
+
+
+VOID WscUPnPMsgTimeOutAction(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext;
+ PRTMP_ADAPTER pAd;
+ WSC_UPNP_NODE_INFO *pWscNodeInfo;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscUPnPMsgTimeOutAction\n"));
+
+ /*It shouldn't happened! */
+ if (!pWscControl)
+ return;
+
+ pAd = (PRTMP_ADAPTER)pWscControl->pAd;
+ pWscNodeInfo = &pWscControl->WscUPnPNodeInfo;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("UPnP StateMachine TimeOut(State=%d!)\n", pWscControl->WscState));
+
+ if (pWscNodeInfo->bUPnPMsgTimerPending)
+ {
+#define WSC_UPNP_TIMER_PENDIND_WAIT 2000
+
+ RTMPModTimer(&pWscNodeInfo->UPnPMsgTimer, WSC_UPNP_TIMER_PENDIND_WAIT);
+ DBGPRINT(RT_DEBUG_TRACE, ("UPnPMsgTimer Pending......\n"));
+ }
+ else
+ {
+ int dataLen;
+ UCHAR *pWscData;
+
+ os_alloc_mem(NULL, (UCHAR **)&pWscData, WSC_MAX_DATA_LEN);
+/* if( (pWscData = kmalloc(WSC_MAX_DATA_LEN, GFP_ATOMIC)) != NULL) */
+ if (pWscData != NULL)
+ {
+ memset(pWscData, 0, WSC_MAX_DATA_LEN);
+ dataLen = BuildMessageNACK(pAd, pWscControl, pWscData);
+ WscSendUPnPMessage(pAd, (pWscControl->EntryIfIdx & 0x0F),
+ WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_NORMAL,
+ pWscData, dataLen, 0, 0, &pAd->CurrentAddress[0], AP_MODE);
+/* kfree(pWscData); */
+ os_free_mem(NULL, pWscData);
+ }
+
+ pWscNodeInfo->bUPnPInProgress = FALSE;
+ pWscNodeInfo->bUPnPMsgTimerPending = FALSE;
+ pWscNodeInfo->bUPnPMsgTimerRunning = FALSE;
+ pWscControl->WscState = WSC_STATE_OFF;
+ pWscControl->WscStatus = STATUS_WSC_FAIL;
+
+ RTMPSendWirelessEvent(pAd, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscUPnPMsgTimeOutAction\n"));
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ This function processes EapolStart packets from wps stations
+ or enqueued by self.
+
+ Return:
+ None
+ ==========================================================================
+*/
+VOID WscEAPOLStartAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ MAC_TABLE_ENTRY *pEntry;
+ PWSC_CTRL pWpsCtrl = NULL;
+ PHEADER_802_11 pHeader;
+ PWSC_PEER_ENTRY pWscPeer = NULL;
+ UCHAR CurOpMode = 0xFF;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscEAPOLStartAction\n"));
+
+ pHeader = (PHEADER_802_11)Elem->Msg;
+ pEntry = MacTableLookup(pAd, pHeader->Addr2);
+
+ /* Cannot find this wps station in MacTable of WPS AP. */
+ if (pEntry == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("pEntry is NULL.\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLStartAction\n"));
+ return;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ pWpsCtrl = &pAd->ApCfg.MBSSID[pEntry->apidx].WscControl;
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pWpsCtrl == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pWpsCtrl == NULL!\n", __FUNCTION__));
+ return;
+ }
+
+ RTMP_SEM_LOCK(&pWpsCtrl->WscPeerListSemLock);
+ WscInsertPeerEntryByMAC(&pWpsCtrl->WscPeerList, pEntry->Addr);
+ RTMP_SEM_UNLOCK(&pWpsCtrl->WscPeerListSemLock);
+
+ WscMaintainPeerList(pAd, pWpsCtrl);
+
+ /*
+ Check this STA is first one or not
+ */
+ if (pWpsCtrl->WscPeerList.size != 0)
+ {
+ pWscPeer = (PWSC_PEER_ENTRY)pWpsCtrl->WscPeerList.pHead;
+ if (NdisEqualMemory(pEntry->Addr, pWscPeer->mac_addr, MAC_ADDR_LEN) == FALSE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("This is not first WSC peer, ignore this EAPOL_Start!\n"));
+ hex_dump("pEntry->Addr", pEntry->Addr, MAC_ADDR_LEN);
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ WscApShowPeerList(pAd, NULL);
+#endif /* CONFIG_AP_SUPPORT */
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLStartAction\n"));
+ return;
+ }
+ }
+
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscState = %d\n", pWpsCtrl->WscState));
+ if ((pEntry->Receive_EapolStart_EapRspId == 0) ||
+ (pWpsCtrl->WscState <= WSC_STATE_WAIT_REQ_ID))
+ {
+ /* Receive the first EapolStart packet of this wps station. */
+ pEntry->Receive_EapolStart_EapRspId |= WSC_ENTRY_GET_EAPOL_START;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEAPOLStartAction - receive EAPOL-Start from %02x:%02x:%02x:%02x:%02x:%02x\n",
+ pEntry->Addr[0],
+ pEntry->Addr[1],
+ pEntry->Addr[2],
+ pEntry->Addr[3],
+ pEntry->Addr[4],
+ pEntry->Addr[5]));
+
+ /* EapolStart packet is sent by station means this station wants to do wps process with AP. */
+ pWpsCtrl->EapMsgRunning = TRUE;
+ /* Update EntryAddr again */
+ NdisMoveMemory(pWpsCtrl->EntryAddr, pEntry->Addr, MAC_ADDR_LEN);
+
+ if (pEntry->bWscCapable == FALSE)
+ pEntry->bWscCapable = TRUE;
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEAPOLStartAction(ra%d) - send EAP-Req(Id) to %02x:%02x:%02x:%02x:%02x:%02x\n",
+ pEntry->apidx,
+ pEntry->Addr[0],
+ pEntry->Addr[1],
+ pEntry->Addr[2],
+ pEntry->Addr[3],
+ pEntry->Addr[4],
+ pEntry->Addr[5]));
+
+ /* Send EAP-Request/Id to station */
+ WscSendEapReqId(pAd, pEntry, CurOpMode);
+ if (!pWpsCtrl->EapolTimerRunning)
+ {
+ pWpsCtrl->EapolTimerRunning = TRUE;
+ /* Set WPS_EAP Messages timeout function. */
+ RTMPSetTimer(&pWpsCtrl->EapolTimer, WSC_EAP_ID_TIME_OUT);
+ }
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("Ignore EAPOL-Start.\n"));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLStartAction\n"));
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ This is state machine function when receiving EAP packets
+ which is WPS Registration Protocol.
+
+ There are two roles at our AP, as an
+ 1. Enrollee
+ 2. Internal Registrar
+ 3. Proxy
+
+ There are two roles at our Station, as an
+ 1. Enrollee
+ 2. External Registrar
+
+ Running Scenarios:
+ -----------------------------------------------------------------
+ 1a. Adding an AP as an Enrollee to a station as an External Registrar (EAP)
+ [External Registrar]<----EAP--->[Enrollee_AP]
+ -----------------------------------------------------------------
+ 2a. Adding a station as an Enrollee to an AP with built-in Registrar (EAP)
+ [Registrar_AP]<----EAP--->[Enrollee_STA]
+ -----------------------------------------------------------------
+ 3a. Adding an Enrollee with External Registrar (UPnP/EAP)
+ [External Registrar]<----UPnP--->[Proxy_AP]<---EAP--->[Enrollee_STA]
+ -----------------------------------------------------------------
+
+ Return:
+ None
+ ==========================================================================
+*/
+VOID WscEAPAction(
+ IN PRTMP_ADAPTER pAdapter,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR MsgType;
+ BOOLEAN bUPnPMsg, Cancelled;
+ MAC_TABLE_ENTRY *pEntry = NULL;
+ UCHAR MacAddr[MAC_ADDR_LEN] = {0};
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR apidx = MAIN_MBSSID;
+#endif /* CONFIG_AP_SUPPORT */
+ PWSC_CTRL pWscControl = NULL;
+ PWSC_UPNP_NODE_INFO pWscUPnPNodeInfo = NULL;
+ UCHAR CurOpMode = 0xFF;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscEAPAction\n"));
+
+ /* The first 6 bytes in Elem->Msg is the MAC address of wps peer. */
+ memmove(MacAddr, Elem->Msg, MAC_ADDR_LEN);
+ memmove(Elem->Msg, Elem->Msg+6, Elem->MsgLen);
+
+#ifdef DBG
+ hex_dump("(WscEAPAction)Elem->MsgLen", Elem->Msg, Elem->MsgLen);
+#endif /* DBG */
+
+ MsgType = WscRxMsgType(pAdapter, Elem);
+ bUPnPMsg = Elem->MsgType == WSC_EAPOL_UPNP_MSG ? TRUE : FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: Addr: %02x:%02x:%02x:%02x:%02x:%02x, MsgType: 0x%02X, bUPnPMsg: %s\n",
+ PRINT_MAC(MacAddr), MsgType, bUPnPMsg ? "TRUE" : "FALSE"));
+
+ if (!bUPnPMsg)
+ pEntry = MacTableLookup(pAdapter, MacAddr);
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (!bUPnPMsg)
+ {
+ if (pEntry)
+ {
+ if (IS_ENTRY_CLIENT(pEntry) && pEntry->apidx >= pAdapter->ApCfg.BssidNum)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: Unknow apidex(=%d).\n", pEntry->apidx));
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPAction\n"));
+ return;
+ }
+ else
+ {
+ apidx = pEntry->apidx;
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: apidex=%d.\n", pEntry->apidx));
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: pEntry is NULL.\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPAction\n"));
+ return;
+ }
+#ifdef APCLI_SUPPORT
+ /* for ap-client packets */
+ if (pEntry && IS_ENTRY_APCLI(pEntry))
+ pWscControl = &pAdapter->ApCfg.ApCliTab[apidx].WscControl;
+ else
+#endif /* APCLI_SUPPORT */
+ pWscControl = &pAdapter->ApCfg.MBSSID[apidx].WscControl;
+ }
+ else
+ {
+ int i;
+ for (i = 0 ; i < MAX_MBSSID_NUM(pAdapter); i++)
+ {
+ if(NdisEqualMemory(pAdapter->ApCfg.MBSSID[i].Bssid, MacAddr, MAC_ADDR_LEN))
+ {
+ apidx = i;
+ break;
+ }
+ }
+ pWscControl = &pAdapter->ApCfg.MBSSID[apidx].WscControl;
+ pWscUPnPNodeInfo = &pAdapter->ApCfg.MBSSID[apidx].WscControl.WscUPnPNodeInfo;
+ pWscUPnPNodeInfo->bUPnPMsgTimerPending = TRUE;
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ if (pWscControl == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pWscControl == NULL!\n", __FUNCTION__));
+ return;
+ }
+
+ if (pEntry && IS_ENTRY_CLIENT(pEntry))
+ {
+ if ((MsgType == WSC_MSG_EAP_REG_RSP_ID) || (MsgType == WSC_MSG_EAP_ENR_RSP_ID))
+ {
+ if (((pEntry->Receive_EapolStart_EapRspId & WSC_ENTRY_GET_EAP_RSP_ID) == WSC_ENTRY_GET_EAP_RSP_ID)
+ && (pWscControl->WscState > WSC_STATE_WAIT_M1))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: Already receive EAP_RSP(Identitry) from this STA, ignore it.\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPAction\n"));
+ return;
+ }
+ else
+ pEntry->Receive_EapolStart_EapRspId |= WSC_ENTRY_GET_EAP_RSP_ID;
+ }
+ }
+
+ pWscControl->EapolTimerPending = TRUE;
+
+#ifdef WSC_V2_SUPPORT
+ if (MsgType == WSC_MSG_EAP_FRAG_ACK)
+ {
+ WscSendEapFragData(pAdapter, pWscControl, pEntry);
+ return;
+ }
+ else
+#endif /* WSC_V2_SUPPORT */
+ if (MsgType == WSC_MSG_EAP_REG_RSP_ID)
+ {
+ /* Receive EAP-Response/Id from external registrar, so the role of AP is enrollee. */
+ if (((pWscControl->WscConfMode & WSC_ENROLLEE) != 0) ||
+ (((pWscControl->WscConfMode & WSC_PROXY) != 0) && bUPnPMsg))
+ {
+ pWscControl->WscActionMode= WSC_ENROLLEE;
+ pWscControl->WscUseUPnP = bUPnPMsg ? 1 : 0;
+ MsgType = WSC_MSG_EAP_RSP_ID;
+ WscEapEnrolleeAction(pAdapter, Elem, WSC_MSG_EAP_RSP_ID, pEntry, pWscControl);
+ }
+ }
+ else if (MsgType == WSC_MSG_EAP_ENR_RSP_ID)
+ {
+ /* Receive EAP-Response/Id from wps enrollee station, so the role of AP is Registrar or Proxy. */
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: Rx Identity\n"));
+ pWscControl->WscActionMode = WSC_REGISTRAR;
+ if (bUPnPMsg)
+ {
+ /* Receive enrollee identity from UPnP */
+ }
+ else
+ {
+#ifdef CONFIG_AP_SUPPORT
+ /* Receive enrollee identity from EAP */
+ if ((pWscControl->WscMode == WSC_PBC_MODE)
+ )
+ {
+ /*
+ Some WPS PBC Station select AP from UI directly; doesn't do PBC scan.
+ Need to check DPID from STA again here.
+ */
+ WscPBC_DPID_FromSTA(pAdapter, pWscControl->EntryAddr);
+ WscPBCSessionOverlapCheck(pAdapter);
+ if ((pAdapter->CommonCfg.WscStaPbcProbeInfo.WscPBCStaProbeCount == 1) &&
+ !NdisEqualMemory(pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[0], &ZERO_MAC_ADDR[0], MAC_ADDR_LEN) &&
+ (NdisEqualMemory(pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[0], &pWscControl->EntryAddr[0], 6) == FALSE))
+ {
+ pAdapter->CommonCfg.WscPBCOverlap = TRUE;
+ }
+ if (pAdapter->CommonCfg.WscPBCOverlap)
+ {
+ hex_dump("EntryAddr", pWscControl->EntryAddr, 6);
+ hex_dump("StaMacAddr0", pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[0], 6);
+ hex_dump("StaMacAddr1", pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[1], 6);
+ hex_dump("StaMacAddr2", pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[2], 6);
+ hex_dump("StaMacAddr3", pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[3], 6);
+ }
+ }
+
+ if ((pWscControl->WscMode == WSC_PBC_MODE) &&
+ (pAdapter->CommonCfg.WscPBCOverlap == TRUE))
+ {
+ /* PBC session overlap */
+ pWscControl->WscStatus = STATUS_WSC_PBC_SESSION_OVERLAP;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_PBC_SESSION_OVERLAP, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: PBC Session Overlap!\n"));
+ }
+ else
+#endif /* CONFIG_AP_SUPPORT */
+ if ((pWscControl->WscConfMode & WSC_PROXY_REGISTRAR) != 0)
+ {
+ /* Notify UPnP daemon before send Eap-Req(wsc-start) */
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: pEntry->Addr=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ __FUNCTION__, PRINT_MAC(pEntry->Addr)));
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ WscSendUPnPConfReqMsg(pAdapter, (pWscControl->EntryIfIdx & 0x0F),
+ (PUCHAR)pAdapter->ApCfg.MBSSID[pEntry->apidx].Ssid, pEntry->Addr, 2, 0, CurOpMode);
+ /* Reset the UPnP timer and status. */
+ if (pWscControl->bM2DTimerRunning == TRUE)
+ {
+ RTMPCancelTimer(&pWscControl->M2DTimer, &Cancelled);
+ pWscControl->bM2DTimerRunning = FALSE;
+ }
+ pWscControl->WscUPnPNodeInfo.registrarID = 0;
+ pWscControl->M2DACKBalance = 0;
+ WscDelWPARetryTimer(pAdapter);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ pWscControl->EapMsgRunning = TRUE;
+ /* Change the state to next one */
+ pWscControl->WscState = WSC_STATE_WAIT_M1;
+ /* send EAP WSC_START */
+ if (pEntry && IS_ENTRY_CLIENT(pEntry))
+ {
+ pWscControl->bWscLastOne = TRUE;
+ if (CurOpMode == AP_MODE)
+ WscSendMessage(pAdapter, WSC_OPCODE_START, NULL, 0, pWscControl, AP_MODE, EAP_CODE_REQ);
+ else
+ {
+ if (ADHOC_ON(pAdapter) && (pWscControl->WscConfMode == WSC_REGISTRAR))
+ WscSendMessage(pAdapter, WSC_OPCODE_START, NULL, 0, pWscControl, STA_MODE, EAP_CODE_REQ);
+ else
+ WscSendMessage(pAdapter, WSC_OPCODE_START, NULL, 0, pWscControl, STA_MODE, EAP_CODE_RSP);
+ }
+ }
+ }
+ }
+ }
+ else if (MsgType == WSC_MSG_EAP_REQ_ID)
+ {
+ /* Receive EAP_Req/Identity from WPS AP or WCN */
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP_Req/Identity from WPS AP or WCN\n"));
+ if (bUPnPMsg && (pWscControl->WscConfMode == WSC_ENROLLEE))
+ {
+ pWscControl->WscActionMode = WSC_ENROLLEE;
+ pWscControl->WscUseUPnP = 1;
+ WscEapEnrolleeAction(pAdapter, Elem, WSC_MSG_EAP_REQ_START, pEntry, pWscControl);
+ }
+ else
+ {
+ /* Receive EAP_Req/Identity from WPS AP */
+ if (pEntry != NULL)
+ WscSendEapRspId(pAdapter, pEntry, pWscControl);
+ }
+
+ if (!bUPnPMsg)
+ {
+ if ((pWscControl->WscState < WSC_STATE_WAIT_M1) ||
+ (pWscControl->WscState > WSC_STATE_WAIT_ACK))
+ {
+ if (pWscControl->WscConfMode == WSC_REGISTRAR)
+ pWscControl->WscState = WSC_STATE_WAIT_M1;
+ else
+ pWscControl->WscState = WSC_STATE_WAIT_WSC_START;
+ }
+ }
+ }
+ else if (MsgType == WSC_MSG_EAP_REQ_START)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP_Req(Wsc_Start) from WPS AP\n"));
+
+ /* Receive EAP_Req(Wsc_Start) from WPS AP */
+ if (pWscControl->WscConfMode == WSC_ENROLLEE)
+ {
+ pWscControl->WscActionMode = WSC_ENROLLEE;
+ pWscControl->WscUseUPnP = bUPnPMsg ? 1 : 0;
+ WscEapEnrolleeAction(pAdapter, Elem, WSC_MSG_EAP_REQ_START, pEntry, pWscControl);
+
+ if (!pWscControl->EapolTimerRunning)
+ {
+ pWscControl->EapolTimerRunning = TRUE;
+ RTMPSetTimer(&pWscControl->EapolTimer, WSC_EAP_ID_TIME_OUT);
+ }
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("Ignore EAP_Req(Wsc_Start) from WPS AP\n"));
+ }
+ else if (MsgType == WSC_MSG_EAP_FAIL)
+ {
+ /* Receive EAP_Fail from WPS AP */
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP_Fail from WPS AP\n"));
+
+ if (pWscControl->WscState >= WSC_STATE_WAIT_EAPFAIL)
+ {
+ pWscControl->WscState = WSC_STATE_OFF;
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ pWscControl->WscConfMode = WSC_DISABLE;
+ /* Bring apcli interface down first */
+ if(pEntry && IS_ENTRY_APCLI(pEntry) && pAdapter->ApCfg.ApCliTab[BSS0].Enable == TRUE )
+ {
+ pAdapter->ApCfg.ApCliTab[pEntry->apidx].Enable = FALSE;
+ ApCliIfDown(pAdapter);
+ pAdapter->ApCfg.ApCliTab[pEntry->apidx].Enable = TRUE;
+ }
+ }
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ else if (pWscControl->WscState == WSC_STATE_RX_M2D)
+ {
+ /* Wait M2; */
+ }
+ else if ((pWscControl->WscState <= WSC_STATE_WAIT_REQ_ID) &&
+ (pWscControl->WscState != WSC_STATE_FAIL))
+ {
+ /* Ignore. D-Link DIR-628 AP sometimes would send EAP_Fail to station after Link UP first then send EAP_Req/Identity. */
+ }
+ else
+ {
+ pWscControl->WscStatus = STATUS_WSC_FAIL;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+
+
+ pWscControl->WscConfMode = WSC_DISABLE;
+ /* Change the state to next one */
+ pWscControl->WscState = WSC_STATE_OFF;
+
+ }
+ }
+ else if (MsgType == WSC_MSG_M1)
+ {
+ UINT32 rv = 0;
+ /*
+ If Buffalo WPS STA doesn't receive M2D from AP, Buffalo WPS STA will stop to do WPS.
+ Therefore we need to receive M1 and send M2D without trigger.
+ */
+ if ((pWscControl->WscConfMode & WSC_REGISTRAR) != 0)
+ {
+ pWscControl->WscActionMode = WSC_REGISTRAR;
+ /* If Message is from EAP, but UPnP Registrar is in progress now, ignore EAP_M1 */
+ if (!bUPnPMsg && pWscControl->WscUPnPNodeInfo.bUPnPInProgress)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("UPnP Registrar is working now, ignore EAP M1.\n"));
+ goto out;
+ }
+ else
+ WscEapRegistrarAction(pAdapter, Elem, MsgType, pEntry, pWscControl);
+ rv = 1;
+ }
+#ifdef CONFIG_AP_SUPPORT
+ if (((pWscControl->WscConfMode & WSC_PROXY) != 0) && (!bUPnPMsg) && (CurOpMode == AP_MODE))
+ {
+ if ((pWscControl->bWscTrigger
+ )
+ && (pWscControl->WscState >= WSC_STATE_WAIT_M3))
+ ;
+ else
+ {
+ pWscControl->WscActionMode = WSC_PROXY;
+ WscEapApProxyAction(pAdapter, Elem, MsgType, pEntry, pWscControl);
+ }
+ }
+ else if ((!pWscControl->bWscTrigger) && ((pWscControl->WscConfMode & WSC_PROXY) == 0) && (pAdapter->OpMode == OPMODE_AP))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscTrigger is FALSE, ignore EAP M1.\n"));
+ goto out;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ else if (MsgType == WSC_MSG_M3 ||
+ MsgType == WSC_MSG_M5 ||
+ MsgType == WSC_MSG_M7 ||
+ MsgType == WSC_MSG_WSC_DONE)
+ {
+ BOOLEAN bNonceMatch = WscCheckNonce(pAdapter, Elem, TRUE, pWscControl);
+ if (((pWscControl->WscConfMode & WSC_REGISTRAR) != 0) &&
+ (pWscControl->bWscTrigger
+ ) &&
+ bNonceMatch)
+ {
+ /* If Message is from EAP, but UPnP Registrar is in progress now, ignore EAP Messages */
+ if (!bUPnPMsg && pWscControl->WscUPnPNodeInfo.bUPnPInProgress)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("UPnP Registrar is working now, ignore EAP Messages.\n"));
+ goto out;
+ }
+ else
+ {
+ pWscControl->WscActionMode = WSC_REGISTRAR;
+ WscEapRegistrarAction(pAdapter, Elem, MsgType, pEntry, pWscControl);
+ }
+ }
+#ifdef CONFIG_AP_SUPPORT
+ else if (((pWscControl->WscConfMode & WSC_PROXY) != 0) && (!bUPnPMsg) && (CurOpMode == AP_MODE))
+ {
+ pWscControl->WscActionMode = WSC_PROXY;
+ WscEapApProxyAction(pAdapter, Elem, MsgType, pEntry, pWscControl);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ else if (MsgType == WSC_MSG_M2 ||
+ MsgType == WSC_MSG_M2D ||
+ MsgType == WSC_MSG_M4 ||
+ MsgType == WSC_MSG_M6 ||
+ MsgType == WSC_MSG_M8)
+ {
+ BOOLEAN bNonceMatch = WscCheckNonce(pAdapter, Elem, FALSE, pWscControl);
+ BOOLEAN bGoWPS = FALSE;
+
+ if ((CurOpMode == AP_MODE) ||
+ ((CurOpMode == STA_MODE) &&
+ (pWscControl->bWscTrigger
+ )))
+ bGoWPS = TRUE;
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef WSC_V2_SUPPORT
+ if ((CurOpMode == AP_MODE) &&
+ ((pWscControl->WscV2Info.bWpsEnable == FALSE) && (pWscControl->WscV2Info.bEnableWpsV2)))
+ bGoWPS = FALSE;
+#endif /* WSC_V2_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (((pWscControl->WscConfMode & WSC_ENROLLEE) != 0) &&
+ bGoWPS &&
+ bNonceMatch)
+ {
+ pWscControl->WscActionMode = WSC_ENROLLEE;
+ pWscControl->WscUseUPnP = bUPnPMsg ? 1 : 0;
+ if (MsgType == WSC_MSG_M2)
+ {
+ BOOLEAN bReadOwnPIN = TRUE;
+#ifdef CONFIG_AP_SUPPORT
+ /* WPS Enrollee AP only supports PIN without trigger */
+ if (CurOpMode == AP_MODE)
+ {
+ if (pWscControl->bWscTrigger == FALSE)
+ {
+ pWscControl->WscMode = 1;
+ WscGetConfWithoutTrigger(pAdapter, pWscControl, FALSE);
+ }
+ else
+ {
+ WscBuildBeaconIE(pAdapter,
+ pWscControl->WscConfStatus,
+ TRUE,
+ pWscControl->WscMode,
+ pWscControl->WscConfigMethods,
+ (pWscControl->EntryIfIdx & 0x0F),
+ NULL,
+ 0,
+ AP_MODE);
+ WscBuildProbeRespIE(pAdapter,
+ WSC_MSGTYPE_AP_WLAN_MGR,
+ pWscControl->WscConfStatus,
+ TRUE,
+ pWscControl->WscMode,
+ pWscControl->WscConfigMethods,
+ pWscControl->EntryIfIdx,
+ NULL,
+ 0,
+ AP_MODE);
+ APUpdateBeaconFrame(pAdapter, pWscControl->EntryIfIdx & 0x0F);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ if (bReadOwnPIN)
+ {
+ pWscControl->WscPinCodeLen = pWscControl->WscEnrolleePinCodeLen;
+ WscGetRegDataPIN(pAdapter, pWscControl->WscEnrolleePinCode, pWscControl);
+ DBGPRINT(RT_DEBUG_TRACE, ("(%d) WscEnrolleePinCode: %08u\n", bReadOwnPIN, pWscControl->WscEnrolleePinCode));
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("WscPinCode: %08u\n", pWscControl->WscPinCode));
+ }
+ /* If Message is from EAP, but UPnP Registrar is in progress now, ignore EAP Messages */
+ if (!bUPnPMsg && pWscControl->WscUPnPNodeInfo.bUPnPInProgress)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("UPnP Registrar is working now, ignore EAP Messages.\n"));
+ goto out;
+ }
+ else
+ WscEapEnrolleeAction(pAdapter, Elem, MsgType, pEntry, pWscControl);
+ }
+#ifdef CONFIG_AP_SUPPORT
+ else if (((pWscControl->WscConfMode & WSC_PROXY) != 0) && (bUPnPMsg) && (CurOpMode == AP_MODE))
+ {
+ pWscControl->WscActionMode = WSC_PROXY;
+ WscEapApProxyAction(pAdapter, Elem, MsgType, pEntry, pWscControl);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ else if (MsgType == WSC_MSG_WSC_ACK)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscState: %d\n", pWscControl->WscState));
+ if (((pWscControl->WscConfMode & WSC_REGISTRAR) != 0) &&
+ pWscControl->WscState <= WSC_STATE_SENT_M2D)
+ {
+ if (WscCheckNonce(pAdapter, Elem, TRUE, pWscControl))
+ {
+ if (pWscControl->M2DACKBalance > 0)
+ pWscControl->M2DACKBalance--;
+ pWscControl->WscState = WSC_STATE_INIT;
+ pWscControl->EapMsgRunning = FALSE;
+ }
+ }
+ else
+ {
+ if (((pWscControl->WscConfMode & WSC_ENROLLEE) != 0) &&
+ WscCheckNonce(pAdapter, Elem, FALSE, pWscControl))
+ {
+ pWscControl->WscActionMode = WSC_ENROLLEE;
+ pWscControl->WscUseUPnP = bUPnPMsg ? 1 : 0;
+ WscEapEnrolleeAction(pAdapter, Elem, MsgType, pEntry, pWscControl);
+ }
+#ifdef CONFIG_AP_SUPPORT
+ else if (((pWscControl->WscConfMode & WSC_PROXY) != 0) && (CurOpMode == AP_MODE))
+ {
+ pWscControl->WscActionMode = WSC_PROXY;
+ WscEapApProxyAction(pAdapter, Elem, MsgType, pEntry, pWscControl);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ }
+ else if (MsgType == WSC_MSG_WSC_NACK)
+ {
+ BOOLEAN bReSetWscIE = FALSE;
+ if (bUPnPMsg && (pWscControl->WscState == WSC_STATE_WAIT_M8) &&
+ (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED))
+ {
+ // Some external sta will send NACK when AP is configured.
+ // bWscTrigger should be set FALSE, otherwise Proxy will send NACK to enrollee.
+ pWscControl->bWscTrigger = FALSE;
+ pWscControl->WscStatus = STATUS_WSC_CONFIGURED;
+ bReSetWscIE = TRUE;
+ }
+ if (!bUPnPMsg &&
+ (WscCheckNonce(pAdapter, Elem, FALSE, pWscControl) || WscCheckNonce(pAdapter, Elem, TRUE, pWscControl)))
+ {
+ USHORT config_error = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive NACK from WPS client.\n"));
+ WscGetConfigErrFromNack(pAdapter, Elem, &config_error);
+ /*
+ If a PIN authentication or communication error occurs,
+ the Registrar MUST warn the user and MUST NOT automatically reuse the PIN.
+ Furthermore, if the Registrar detects this situation and prompts the user for a new PIN from the Enrollee device,
+ it MUST NOT accept the same PIN again without warning the user of a potential attack.
+ */
+ if ((pWscControl->WscState >= WSC_STATE_WAIT_M5) && (config_error != WSC_ERROR_SETUP_LOCKED))
+ {
+ pWscControl->WscRejectSamePinFromEnrollee = TRUE;
+ pWscControl->WscPinCode = 0;
+
+ if (pWscControl->WscState < WSC_STATE_WAIT_M8)
+ {
+ pWscControl->WscStatus = STATUS_WSC_FAIL;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ bReSetWscIE = TRUE;
+ }
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ if ((pWscControl->WscState == WSC_STATE_OFF)
+ && (CurOpMode == AP_MODE)
+ && (pWscControl->RegData.SelfInfo.ConfigError != WSC_ERROR_NO_ERROR))
+ {
+ bReSetWscIE = TRUE;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if ((pWscControl->WscState == WSC_STATE_WAIT_M8) &&
+ (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED))
+ {
+ /* Some external sta will send NACK when AP is configured. */
+ /* bWscTrigger should be set FALSE, otherwise Proxy will send NACK to enrollee. */
+ pWscControl->bWscTrigger = FALSE;
+ bReSetWscIE = TRUE;
+ pWscControl->WscStatus = STATUS_WSC_CONFIGURED;
+ pWscControl->WscRejectSamePinFromEnrollee = FALSE;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_SUCCESS, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ }
+#ifdef CONFIG_AP_SUPPORT
+ else if ((CurOpMode == AP_MODE) &&
+ (pWscControl->WscState == WSC_STATE_WAIT_DONE) &&
+ (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED) &&
+ (pAdapter->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11WEPEnabled))
+ {
+ bReSetWscIE = TRUE;
+ pWscControl->WscStatus = STATUS_WSC_FAIL;
+ }
+
+ if ((CurOpMode == AP_MODE) && bReSetWscIE)
+ {
+ WscBuildBeaconIE(pAdapter, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode);
+ WscBuildProbeRespIE(pAdapter, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, pWscControl->EntryIfIdx, NULL, 0, CurOpMode);
+ APUpdateBeaconFrame(pAdapter, pWscControl->EntryIfIdx & 0x0F);
+ if (pWscControl->Wsc2MinsTimerRunning)
+ {
+ RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled);
+ pWscControl->Wsc2MinsTimerRunning = FALSE;
+ }
+ if (pWscControl->bWscTrigger)
+ pWscControl->bWscTrigger = FALSE;
+ }
+#endif // CONFIG_AP_SUPPORT //
+
+ if ((CurOpMode == AP_MODE)
+ || ((ADHOC_ON(pAdapter)) && (pWscControl->WscConfMode == WSC_REGISTRAR))
+ )
+ {
+ WscSendEapFail(pAdapter, pWscControl, TRUE);
+ pWscControl->WscState = WSC_STATE_FAIL;
+ }
+
+ RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled);
+ pWscControl->EapolTimerRunning = FALSE;
+ pWscControl->RegData.ReComputePke = 1;
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Unsupported Msg Type (%02X)\n", MsgType));
+ //sync by 7610
+ pWscControl->WscStatus = STATUS_WSC_FAIL;
+ pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_NO_ERROR;
+ WscSendNACK(pAdapter, pEntry, pWscControl);
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, BSS0, 0);
+ goto out;
+ }
+
+ if (bUPnPMsg)
+ {
+ /* Messages from UPnP */
+ if (pWscUPnPNodeInfo->bUPnPMsgTimerRunning)
+ RTMPModTimer(&pWscUPnPNodeInfo->UPnPMsgTimer, WSC_UPNP_MSG_TIME_OUT);
+ }
+ else
+ {
+ if ((pWscControl->EapMsgRunning == TRUE) &&
+ (!RTMP_TEST_FLAG(pAdapter, fRTMP_ADAPTER_HALT_IN_PROGRESS |
+ fRTMP_ADAPTER_NIC_NOT_EXIST)))
+ {
+ /* Messages from EAP */
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ pWscControl->EapolTimerRunning = TRUE;
+ }
+ }
+
+ if (bUPnPMsg && pWscControl->EapolTimerRunning)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if ((pWscControl->WscActionMode == WSC_PROXY) && (CurOpMode == AP_MODE))
+ {
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ else
+#endif /* CONFIG_AP_SUPPORT */
+ {
+ RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled);
+ pWscControl->EapolTimerRunning = FALSE;
+ }
+ }
+
+out:
+ if (bUPnPMsg)
+ pWscUPnPNodeInfo->bUPnPMsgTimerPending = FALSE;
+
+ pWscControl->EapolTimerPending = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPAction\n"));
+}
+
+/*
+ ============================================================================
+ Enrollee Enrollee Enrollee
+ ============================================================================
+*/
+VOID WscEapEnrolleeAction(
+ IN PRTMP_ADAPTER pAdapter,
+ IN MLME_QUEUE_ELEM *Elem,
+ IN UCHAR MsgType,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN PWSC_CTRL pWscControl)
+{
+ INT DataLen = 0, rv = 0, DH_Len = 0;
+ UCHAR OpCode, bssIdx;
+ PUCHAR WscData = NULL;
+ BOOLEAN bUPnPMsg, bUPnPStatus = FALSE, Cancelled;
+ WSC_UPNP_NODE_INFO *pWscUPnPInfo = &pWscControl->WscUPnPNodeInfo;
+ UINT MaxWscDataLen = WSC_MAX_DATA_LEN;
+ UCHAR CurOpMode = 0xFF;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction Enter!\n"));
+
+ bUPnPMsg = Elem->MsgType == WSC_EAPOL_UPNP_MSG ? TRUE : FALSE;
+ OpCode = bUPnPMsg ? WSC_OPCODE_UPNP_MASK : 0;
+ bssIdx = 0;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ CurOpMode = AP_MODE;
+#endif // CONFIG_AP_SUPPORT //
+
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ /* Early check. */
+ if ((pWscControl->WscActionMode != WSC_ENROLLEE) ||
+ (pWscControl->WscUseUPnP && pEntry) ||
+ ((pWscControl->WscUseUPnP == 0) && (!pEntry)))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("EarlyCheckFailed: pWscControl->WscActionMode=%d, Configured=%d, WscUseUPnP=%d, pEntry=%p!\n",
+ pWscControl->WscActionMode, pWscControl->WscConfStatus, pWscControl->WscUseUPnP, pEntry));
+ goto Fail;
+ }
+ bssIdx = (pWscControl->EntryIfIdx & 0x0F);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ DBGPRINT(RT_DEBUG_TRACE, ("MsgType=0x%x, WscState=%d, bUPnPMsg=%d!\n", MsgType, pWscControl->WscState, bUPnPMsg));
+
+ if (bUPnPMsg)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if ((MsgType == WSC_MSG_EAP_RSP_ID) && (CurOpMode == AP_MODE))
+ {
+ /* let it pass */
+ } else
+#endif /* CONFIG_AP_SUPPORT */
+ if(MsgType ==WSC_MSG_M2 && pWscUPnPInfo->bUPnPInProgress == FALSE)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ MAC_TABLE_ENTRY *tempEntry;
+ tempEntry = MacTableLookup(pAdapter, &pWscControl->EntryAddr[0]);
+ if (tempEntry)
+ {
+ if((tempEntry->Receive_EapolStart_EapRspId & WSC_ENTRY_GET_EAP_RSP_ID) == WSC_ENTRY_GET_EAP_RSP_ID)
+ {
+ goto Done;
+ }
+ }
+ /* else cannot find the pEntry, so we need to handle this msg. */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ pWscUPnPInfo->bUPnPInProgress = TRUE;
+ /* Set the WscState as "WSC_STATE_WAIT_RESP_ID" because UPnP start from this state. */
+ /* pWscControl->WscState = WSC_STATE_WAIT_RESP_ID; */
+ RTMPSetTimer(&pWscUPnPInfo->UPnPMsgTimer, WSC_UPNP_MSG_TIME_OUT);
+ pWscUPnPInfo->bUPnPMsgTimerRunning = TRUE;
+ }
+ else
+ {
+ /* For other messages, we must make sure pWscUPnPInfo->bUPnPInProgress== TRUE */
+ if (pWscUPnPInfo->bUPnPInProgress == FALSE)
+ {
+ goto Done;
+ }
+ }
+ }
+
+#ifdef WSC_V2_SUPPORT
+ MaxWscDataLen = MaxWscDataLen + (UINT)pWscControl->WscV2Info.ExtraTlv.TlvLen;
+#endif /* WSC_V2_SUPPORT */
+ os_alloc_mem(NULL, (UCHAR **)&WscData, MaxWscDataLen);
+/* if( (WscData = kmalloc(WSC_MAX_DATA_LEN, GFP_ATOMIC)) == NULL) */
+ if (WscData == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscData Allocate failed!\n"));
+ goto Fail;
+ }
+ NdisZeroMemory(WscData, MaxWscDataLen);
+
+ switch (MsgType)
+ {
+ case WSC_MSG_EAP_RSP_ID:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx Identity(ReComputePke=%d)\n", pWscControl->RegData.ReComputePke));
+ case WSC_MSG_EAP_REQ_START:
+ if (MsgType == WSC_MSG_EAP_REQ_START)
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx Wsc_Start(ReComputePke=%d)\n", pWscControl->RegData.ReComputePke));
+
+ if (pWscControl->RegData.ReComputePke == 1)
+ {
+ INT idx;
+ DH_Len = sizeof(pWscControl->RegData.Pke);
+ /* Enrollee 192 random bytes for DH key generation */
+ for (idx = 0; idx < 192; idx++)
+ pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAdapter);
+ RT_DH_PublicKey_Generate (
+ WPS_DH_G_VALUE, sizeof(WPS_DH_G_VALUE),
+ WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE),
+ pWscControl->RegData.EnrolleeRandom, sizeof(pWscControl->RegData.EnrolleeRandom),
+ pWscControl->RegData.Pke, (UINT *) &DH_Len);
+
+ pWscControl->RegData.ReComputePke = 0;
+ }
+
+ OpCode |= WSC_OPCODE_MSG;
+
+ DataLen = BuildMessageM1(pAdapter, pWscControl, WscData);
+ if(!bUPnPMsg)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (pEntry && IS_ENTRY_CLIENT(pEntry))
+ WscDelWPARetryTimer(pAdapter);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ pWscControl->EapMsgRunning = TRUE;
+ pWscControl->WscStatus = STATUS_WSC_EAP_M1_SENT;
+ }
+ else
+ /* Sometime out-of-band registrars (ex: Vista) get M1 for collecting information of device. */
+ pWscControl->WscStatus = STATUS_WSC_IDLE;
+
+ /* Change the state to next one */
+ if (pWscControl->WscState < WSC_STATE_SENT_M1)
+ pWscControl->WscState = WSC_STATE_SENT_M1;
+
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M1, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ break;
+
+ case WSC_MSG_M2:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M2\n"));
+
+ /* Receive M2, if we are at WSC_STATE_WAIT_M2 start, process it immediately */
+ if (pWscControl->WscState == WSC_STATE_SENT_M1 ||
+ pWscControl->WscState == WSC_STATE_RX_M2D)
+ {
+ /* Process M2 */
+ pWscControl->WscStatus = STATUS_WSC_EAP_M2_RECEIVED;
+
+ NdisMoveMemory(pWscControl->RegData.PeerInfo.MacAddr, pWscControl->EntryAddr, 6);
+ if ((rv = ProcessMessageM2(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, (pWscControl->EntryIfIdx & 0x0F), &pWscControl->RegData)))
+ {
+ goto Fail;
+ }
+ else
+ {
+#ifdef CONFIG_AP_SUPPORT
+#ifdef WSC_V2_SUPPORT
+ if ((CurOpMode == AP_MODE) && pWscControl->bSetupLock)
+ {
+ rv = WSC_ERROR_SETUP_LOCKED;
+ goto Fail;
+ }
+#endif /* WSC_V2_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ OpCode |= WSC_OPCODE_MSG;
+ DataLen = BuildMessageM3(pAdapter, pWscControl, WscData);
+ pWscControl->WscStatus = STATUS_WSC_EAP_M3_SENT;
+
+ /* Change the state to next one */
+ pWscControl->WscState = WSC_STATE_WAIT_M4;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M3, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ }
+ }
+ break;
+
+ case WSC_MSG_M2D:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M2D\n"));
+
+ /* Receive M2D, if we are at WSC_STATE_WAIT_M2 start, process it immediately */
+ if (pWscControl->WscState == WSC_STATE_SENT_M1 ||
+ pWscControl->WscState == WSC_STATE_RX_M2D)
+ {
+ if ((rv = ProcessMessageM2D(pAdapter, Elem->Msg, Elem->MsgLen, &pWscControl->RegData)))
+ goto Fail;
+
+ pWscControl->WscStatus = STATUS_WSC_EAP_M2D_RECEIVED;
+
+ if ((CurOpMode == STA_MODE)
+ )
+ {
+ /* When external registrar is Marvell station, */
+ /* wps station sends NACK may confuse or reset Marvell wps state machine. */
+ OpCode |= WSC_OPCODE_ACK;
+ DataLen = BuildMessageACK(pAdapter, pWscControl, WscData);
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_ACK, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ }
+ else
+ {
+
+ /* For VISTA SP1 internal registrar test */
+ OpCode |= WSC_OPCODE_NACK;
+ pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_NO_ERROR;
+ DataLen = BuildMessageNACK(pAdapter, pWscControl, WscData);
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_NACK, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ }
+
+ /* Change the state to next one */
+ pWscControl->WscState = WSC_STATE_RX_M2D;
+ }
+ break;
+
+ case WSC_MSG_M4:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M4\n"));
+
+ /* Receive M4, if we are at WSC_STATE_WAIT_M4 start, process it immediately */
+ if (pWscControl->WscState == WSC_STATE_WAIT_M4)
+ {
+ /* Process M4 */
+ pWscControl->WscStatus = STATUS_WSC_EAP_M4_RECEIVED;
+ if ((rv = ProcessMessageM4(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData)))
+ {
+#ifdef CONFIG_AP_SUPPORT
+#ifdef WSC_V2_SUPPORT
+ if (CurOpMode == AP_MODE)
+ WscCheckPinAttackCount(pAdapter, pWscControl);
+#endif /* WSC_V2_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ goto Fail;
+ }
+ else
+ {
+ OpCode |= WSC_OPCODE_MSG;
+ DataLen = BuildMessageM5(pAdapter, pWscControl, WscData);
+ pWscControl->WscStatus = STATUS_WSC_EAP_M5_SENT;
+
+ /* Change the state to next one */
+ pWscControl->WscState = WSC_STATE_WAIT_M6;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M5, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ }
+ }
+ break;
+
+ case WSC_MSG_M6:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M6\n"));
+
+ /* Receive M6, if we are at WSC_STATE_WAIT_M6 start, process it immediately */
+ if (pWscControl->WscState == WSC_STATE_WAIT_M6)
+ {
+ /* Process M6 */
+ pWscControl->WscStatus = STATUS_WSC_EAP_M6_RECEIVED;
+ if ((rv=ProcessMessageM6(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData)))
+ {
+#ifdef CONFIG_AP_SUPPORT
+#ifdef WSC_V2_SUPPORT
+ if (CurOpMode == AP_MODE)
+ WscCheckPinAttackCount(pAdapter, pWscControl);
+#endif /* WSC_V2_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ goto Fail;
+ }
+ else
+ {
+ OpCode |= WSC_OPCODE_MSG;
+
+ DataLen = BuildMessageM7(pAdapter, pWscControl, WscData);
+ pWscControl->WscStatus = STATUS_WSC_EAP_M7_SENT;
+ /* Change the state to next one */
+ pWscControl->WscState = WSC_STATE_WAIT_M8;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M7, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ /*
+ Complete WPS with this STA. Delete it from WscPeerList for others STA to do WSC with AP
+ */
+ if (pEntry)
+ {
+ RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock);
+ WscDelListEntryByMAC(&pWscControl->WscPeerList, pEntry->Addr);
+ RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock);
+ }
+ }
+ }
+ break;
+
+ case WSC_MSG_M8:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M8\n"));
+
+ /* Receive M8, if we are at WSC_STATE_WAIT_M6 start, process it immediately */
+ if (pWscControl->WscState == WSC_STATE_WAIT_M8)
+ {
+ /* Process M8 */
+ pWscControl->WscStatus = STATUS_WSC_EAP_M8_RECEIVED;
+ if ((rv=ProcessMessageM8(pAdapter, Elem->Msg, Elem->MsgLen, pWscControl)))
+ goto Fail;
+ else
+ {
+ OpCode |= WSC_OPCODE_DONE;
+ DataLen = BuildMessageDONE(pAdapter, pWscControl, WscData);
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ /* Change the state to next one */
+#ifdef APCLI_SUPPORT
+ /* Ap Client only supports Inband(EAP)-Enrollee. */
+ if (!bUPnPMsg && pEntry && IS_ENTRY_APCLI(pEntry))
+ pWscControl->WscState = WSC_STATE_WAIT_EAPFAIL;
+ else
+#endif /* APCLI_SUPPORT */
+ pWscControl->WscState = WSC_STATE_WAIT_ACK;
+ //sync by 7610
+ //pWscControl->RegData.ReComputePke = 0;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_DONE, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ }
+ }
+ break;
+
+#ifdef CONFIG_AP_SUPPORT
+ case WSC_MSG_WSC_ACK:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx ACK\n"));
+
+ /* Receive ACK */
+ if (pWscControl->WscState == WSC_STATE_WAIT_ACK)
+ {
+ /* Process ACK */
+ pWscControl->WscStatus = STATUS_WSC_EAP_RAP_RSP_ACK;
+ /* Send out EAP-Fail */
+ WscSendEapFail(pAdapter, pWscControl, FALSE);
+ pWscControl->WscState = WSC_STATE_CONFIGURED;
+ pWscControl->WscStatus = STATUS_WSC_CONFIGURED;
+ }
+ break;
+#endif /* CONFIG_AP_SUPPORT */
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Unsupported Msg Type\n"));
+ break;
+ }
+
+ if (bUPnPMsg)
+ {
+ if ((MsgType == WSC_MSG_M8) && (pWscControl->WscState == WSC_STATE_WAIT_ACK))
+ {
+ pWscControl->EapMsgRunning = FALSE;
+ pWscControl->WscState = WSC_STATE_CONFIGURED;
+ pWscControl->WscStatus = STATUS_WSC_CONFIGURED;
+ if(pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE)
+ {
+ RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled);
+ pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE;
+ }
+ pWscUPnPInfo->bUPnPInProgress = FALSE;
+ pWscUPnPInfo->registrarID = 0;
+ }
+ }
+ else
+ {
+ if (((MsgType == WSC_MSG_WSC_ACK) && (pWscControl->WscState == WSC_STATE_CONFIGURED)) ||
+ ((MsgType == WSC_MSG_M8) && (pWscControl->WscState == WSC_STATE_WAIT_ACK)))
+ {
+ RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled);
+ pWscControl->EapolTimerRunning = FALSE;
+ pWscControl->EapMsgRunning = FALSE;
+ /*NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); */
+ }
+ }
+
+ if(OpCode > WSC_OPCODE_UPNP_MASK)
+ bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), WSC_OPCODE_UPNP_DATA,
+ WSC_UPNP_DATA_SUB_NORMAL, WscData, DataLen,
+ Elem->TimeStamp.u.LowPart, Elem->TimeStamp.u.HighPart,
+ &pAdapter->CurrentAddress[0], CurOpMode);
+ else if(OpCode > 0 && OpCode < WSC_OPCODE_UPNP_MASK)
+ {
+ if (pWscControl->WscState != WSC_STATE_CONFIGURED)
+ {
+#ifdef WSC_V2_SUPPORT
+ pWscControl->WscTxBufLen = 0;
+ pWscControl->pWscCurBufIdx = NULL;
+ pWscControl->bWscLastOne = TRUE;
+ if (pWscControl->bWscFragment && (DataLen > pWscControl->WscFragSize))
+ {
+ ASSERT(DataLen < MGMT_DMA_BUFFER_SIZE);
+ NdisMoveMemory(pWscControl->pWscTxBuf, WscData, DataLen);
+ pWscControl->WscTxBufLen = DataLen;
+ NdisZeroMemory(WscData, DataLen);
+ pWscControl->bWscLastOne = FALSE;
+ pWscControl->bWscFirstOne = TRUE;
+ NdisMoveMemory(WscData, pWscControl->pWscTxBuf, pWscControl->WscFragSize);
+ DataLen = pWscControl->WscFragSize;
+ pWscControl->WscTxBufLen -= pWscControl->WscFragSize;
+ pWscControl->pWscCurBufIdx = (pWscControl->pWscTxBuf + pWscControl->WscFragSize);
+ }
+#endif /* WSC_V2_SUPPORT */
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (pEntry && IS_ENTRY_APCLI(pEntry))
+ WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP);
+ else
+ WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ }
+ else
+ bUPnPStatus = TRUE;
+
+Fail:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : rv = %d\n", rv));
+ if (rv)
+ {
+#ifdef CONFIG_AP_SUPPORT
+#ifdef WSC_V2_SUPPORT
+ if ((CurOpMode == AP_MODE) && pWscControl->bSetupLock)
+ rv = WSC_ERROR_SETUP_LOCKED;
+#endif /* WSC_V2_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (rv <= WSC_ERROR_DEV_PWD_AUTH_FAIL)
+ pWscControl->RegData.SelfInfo.ConfigError = rv;
+ else if ((rv == WSC_ERROR_HASH_FAIL) || (rv == WSC_ERROR_HMAC_FAIL))
+ pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_DECRYPT_CRC_FAIL;
+
+ switch(rv)
+ {
+ case WSC_ERROR_DEV_PWD_AUTH_FAIL:
+ pWscControl->WscStatus = STATUS_WSC_ERROR_DEV_PWD_AUTH_FAIL;
+ break;
+ default:
+ pWscControl->WscStatus = STATUS_WSC_FAIL;
+ break;
+ }
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ if (bUPnPMsg)
+ {
+ if (pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE)
+ {
+ RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled);
+ pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE;
+ }
+ pWscUPnPInfo->bUPnPInProgress = FALSE;
+ }
+ else
+ WscSendNACK(pAdapter, pEntry, pWscControl);
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ pWscControl->WscState = WSC_STATE_OFF;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /*NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); */
+ /*pWscControl->WscMode = 1; */
+
+ bUPnPStatus = FALSE;
+ }
+
+Done:
+ if(WscData)
+ os_free_mem(NULL, WscData);
+ if(bUPnPMsg && (bUPnPStatus == FALSE))
+ WscUPnPErrHandle(pAdapter, pWscControl, Elem->TimeStamp.u.LowPart);
+
+ rv = 0;
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (((bUPnPMsg || (pEntry && IS_ENTRY_CLIENT(pEntry)))
+ && (pWscControl->WscState == WSC_STATE_CONFIGURED || pWscControl->WscState == WSC_STATE_WAIT_ACK))
+#ifdef APCLI_SUPPORT
+ ||((!bUPnPMsg && pEntry && IS_ENTRY_APCLI(pEntry)) && (pWscControl->WscState == WSC_STATE_WAIT_EAPFAIL || pWscControl->WscState == WSC_STATE_CONFIGURED))
+#endif /* APCLI_SUPPORT */
+ )
+ {
+ rv = 1;
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (rv == 1)
+ {
+#ifdef WSC_LED_SUPPORT
+ UCHAR WPSLEDStatus;
+#endif /* WSC_LED_SUPPORT */
+
+ pWscControl->bWscTrigger = FALSE;
+ pWscControl->RegData.ReComputePke = 1;
+ RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled);
+ if (pWscControl->Wsc2MinsTimerRunning)
+ {
+ pWscControl->Wsc2MinsTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled);
+ }
+ if ((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED)
+#ifdef CONFIG_AP_SUPPORT
+ || (pWscControl->bWCNTest == TRUE)
+#ifdef WSC_V2_SUPPORT
+ || (pWscControl->WscV2Info.bEnableWpsV2 && ((CurOpMode == AP_MODE) && !pWscControl->bSetupLock))
+#endif /* WSC_V2_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ )
+ {
+ pWscControl->WscStatus = STATUS_WSC_CONFIGURED;
+ pWscControl->WscConfStatus = WSC_SCSTATE_CONFIGURED;
+ pWscControl->WscMode = 1;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_SUCCESS, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+
+
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ pWscControl->RegData.SelfInfo.ScState = pWscControl->WscConfStatus;
+#ifdef APCLI_SUPPORT
+ if (!bUPnPMsg && pEntry && IS_ENTRY_APCLI(pEntry))
+ {
+ POS_COOKIE pObj = (POS_COOKIE) pAdapter->OS_Cookie;
+ INT old_if_type = pObj->ioctl_if_type;
+ pObj->ioctl_if_type = INT_APCLI;
+ WscWriteConfToApCliCfg(pAdapter, pWscControl, &pWscControl->WscProfile.Profile[0], TRUE);
+ pObj->ioctl_if_type = old_if_type;
+/*#ifdef KTHREAD_SUPPORT */
+/* WAKE_UP(&(pAdapter->wscTask)); */
+/*#else */
+/* RTMP_SEM_EVENT_UP(&(pAdapter->wscTask.taskSema)); */
+/*#endif */
+ RtmpOsTaskWakeUp(&(pAdapter->wscTask));
+ }
+ else
+#endif /* APCLI_SUPPORT */
+ {
+ RTMPSetTimer(&pWscControl->WscUpdatePortCfgTimer, 1000);
+ pWscControl->WscUpdatePortCfgTimerRunning = TRUE;
+ }
+
+ if (bUPnPMsg || (pEntry && IS_ENTRY_CLIENT(pEntry)))
+ {
+ WscBuildBeaconIE(pAdapter, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode);
+ WscBuildProbeRespIE(pAdapter, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode);
+ APUpdateBeaconFrame(pAdapter, pWscControl->EntryIfIdx & 0x0F);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ }
+#ifdef WSC_LED_SUPPORT
+ /* The protocol is finished. */
+ WPSLEDStatus = LED_WPS_SUCCESS;
+ RTMPSetLED(pAdapter, WPSLEDStatus);
+#endif /* WSC_LED_SUPPORT */
+ }
+}
+
+#ifdef CONFIG_AP_SUPPORT
+/*
+ ============================================================================
+ Proxy Proxy Proxy
+ ============================================================================
+*/
+VOID WscEapApProxyAction(
+ IN PRTMP_ADAPTER pAdapter,
+ IN MLME_QUEUE_ELEM *Elem,
+ IN UCHAR MsgType,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN PWSC_CTRL pWscControl)
+{
+ PUCHAR WscData = NULL;
+ BOOLEAN sendToUPnP = FALSE, bUPnPStatus = FALSE, Cancelled;
+ int reqID = 0;
+ WSC_UPNP_NODE_INFO *pWscUPnPInfo = &pWscControl->WscUPnPNodeInfo;
+ UINT MaxWscDataLen = WSC_MAX_DATA_LEN;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction Enter!\n"));
+
+ if (Elem->MsgType == WSC_EAPOL_UPNP_MSG)
+ {
+ reqID = Elem->TimeStamp.u.LowPart;
+ if(reqID > 0)
+ sendToUPnP = TRUE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction():pEntry=%p, ElemMsgType=%ld, MsgType=%d!\n", pEntry, Elem->MsgType, MsgType));
+
+ if ((pWscControl->WscActionMode != WSC_PROXY) ||
+ ((Elem->MsgType == WSC_EAPOL_PACKET_MSG) && (pEntry == NULL)))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("EarlyCheckFailed: gWscActionMode=%d, pEntry=%p!\n", pWscControl->WscActionMode, pEntry));
+ goto Fail;
+ }
+
+#ifdef WSC_V2_SUPPORT
+ MaxWscDataLen = MaxWscDataLen + (UINT)pWscControl->WscV2Info.ExtraTlv.TlvLen;
+#endif /* WSC_V2_SUPPORT */
+ os_alloc_mem(NULL, (UCHAR **)&WscData, MaxWscDataLen);
+/* if ((WscData = kmalloc(WSC_MAX_DATA_LEN, GFP_ATOMIC)) == NULL) */
+ if (WscData == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscData Allocate failed!\n"));
+ goto Fail;
+ }
+ NdisZeroMemory(WscData, MaxWscDataLen);
+
+ /* Base on state doing the Msg, State change diagram */
+ if (Elem->MsgType == WSC_EAPOL_UPNP_MSG)
+ { /* WSC message send from UPnP. */
+ switch (MsgType)
+ {
+ case WSC_MSG_M2:
+ case WSC_MSG_M4:
+ case WSC_MSG_M6:
+ case WSC_MSG_M8:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WscMsg(%d) from UPnP, eventID=0x%x!\n", MsgType, reqID));
+ WscSendMessage(pAdapter, WSC_OPCODE_MSG, Elem->Msg, Elem->MsgLen, pWscControl, AP_MODE, EAP_CODE_REQ);
+
+ /*Notify the UPnP daemon which remote registar is negotiating with enrollee. */
+ if (MsgType == WSC_MSG_M2)
+ {
+ pWscUPnPInfo->registrarID = Elem->TimeStamp.u.HighPart;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s():registrarID=0x%x!\n", __FUNCTION__, pWscUPnPInfo->registrarID));
+ bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F),
+ WSC_OPCODE_UPNP_MGMT, WSC_UPNP_MGMT_SUB_REG_SELECT,
+ (PUCHAR)(&pWscUPnPInfo->registrarID), sizeof(UINT), 0, 0, NULL, AP_MODE);
+
+ /*Reset the UPnP timer and status. */
+ if (pWscControl->bM2DTimerRunning == TRUE)
+ {
+ RTMPCancelTimer(&pWscControl->M2DTimer, &Cancelled);
+ pWscControl->bM2DTimerRunning = FALSE;
+ }
+ pWscControl->M2DACKBalance = 0;
+ pWscUPnPInfo->registrarID = 0;
+ }
+ if (MsgType == WSC_MSG_M8)
+ {
+ WscBuildBeaconIE(pAdapter, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, AP_MODE);
+ WscBuildProbeRespIE(pAdapter, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, pWscControl->EntryIfIdx, NULL, 0, AP_MODE);
+ APUpdateBeaconFrame(pAdapter, pWscControl->EntryIfIdx & 0x0F);
+ }
+ break;
+
+ case WSC_MSG_M2D:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WscMsg M2D(%d) from UPnP, eventID=0x%x!\n", MsgType, reqID));
+
+ /*If it's send by UPnP Action, response ok directly to remote UPnP Control Point! */
+ if (reqID > 0)
+ bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F),
+ WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_ACK,
+ 0, 0, reqID, 0, NULL, AP_MODE);
+
+ /*Send M2D to wireless station. */
+ WscSendMessage(pAdapter, WSC_OPCODE_MSG, Elem->Msg, Elem->MsgLen, pWscControl, AP_MODE, EAP_CODE_REQ);
+ pWscControl->M2DACKBalance++;
+ if ((pWscUPnPInfo->registrarID == 0) && (pWscControl->bM2DTimerRunning == FALSE))
+ {
+ /* Add M2D timer used to trigger the EAPFail Packet! */
+ RTMPSetTimer(&pWscControl->M2DTimer, WSC_UPNP_M2D_TIME_OUT);
+ pWscControl->bM2DTimerRunning = TRUE;
+ }
+ break;
+
+ case WSC_MSG_WSC_NACK:
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("Recv WscMsg(%d) from UPnP, request EventID=%d! drop it!\n", MsgType, reqID));
+ break;
+ }
+ }
+ else
+ { /*WSC msg send from EAP. */
+ switch (MsgType)
+ {
+ case WSC_MSG_M1:
+ case WSC_MSG_M3:
+ case WSC_MSG_M5:
+ case WSC_MSG_M7:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WscMsg(%d) from EAP\n", MsgType));
+ /*This msg send to event-based external registrar */
+ if (MsgType == WSC_MSG_M1)
+ {
+ bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F),
+ WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_TO_ALL,
+ Elem->Msg, Elem->MsgLen, 0, 0, &pWscControl->EntryAddr[0], AP_MODE);
+ pWscControl->WscState = WSC_STATE_SENT_M1;
+ }
+ else
+ bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F),
+ WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_TO_ALL,
+ Elem->Msg, Elem->MsgLen, 0, pWscUPnPInfo->registrarID,
+ &pWscControl->EntryAddr[0], AP_MODE);
+
+ break;
+
+ case WSC_MSG_WSC_ACK:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WSC_ACK from EAP\n"));
+
+ /* The M2D must appeared before the ACK, so we just need sub it when (pWscUPnPInfo->M2DACKBalance > 0) */
+ if (pWscControl->M2DACKBalance > 0)
+ pWscControl->M2DACKBalance--;
+ break;
+
+ case WSC_MSG_WSC_DONE:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WSC_DONE from EAP\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: send WSC_DONE to UPnP Registrar!\n"));
+ /*Send msg to event-based external registrar */
+ bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F),
+ WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_TO_ONE,
+ Elem->Msg, Elem->MsgLen, 0,
+ pWscUPnPInfo->registrarID, &pWscControl->EntryAddr[0], AP_MODE);
+
+ /*Send EAPFail to wireless station to finish the whole process. */
+ WscSendEapFail(pAdapter, pWscControl, FALSE);
+
+ RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled);
+ pWscControl->EapolTimerRunning = FALSE;
+
+ pEntry->bWscCapable = FALSE;
+ pWscControl->EapMsgRunning = FALSE;
+ NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN);
+
+ if (pWscControl->Wsc2MinsTimerRunning)
+ {
+ pWscControl->Wsc2MinsTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled);
+ }
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("Recv WSC Msg(%d) from EAP , it's impossible, drop it!\n", MsgType));
+ break;
+ }
+ }
+
+Fail:
+ if (WscData)
+ os_free_mem(NULL, WscData);
+ if (sendToUPnP && (bUPnPStatus == FALSE))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Need to send UPnP but bUPnPStatus is false!MsgType=%d, regID=0x%x!\n", MsgType, reqID));
+ WscUPnPErrHandle(pAdapter, pWscControl, reqID);
+ }
+
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+/*
+ ============================================================================
+ Registrar Registrar Registrar
+ ============================================================================
+*/
+VOID WscEapRegistrarAction(
+ IN PRTMP_ADAPTER pAdapter,
+ IN MLME_QUEUE_ELEM *Elem,
+ IN UCHAR MsgType,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN PWSC_CTRL pWscControl)
+{
+ INT DataLen = 0, rv = 0;
+ UCHAR OpCode = 0;
+ UCHAR *WscData = NULL;
+ BOOLEAN bUPnPMsg, bUPnPStatus = FALSE, Cancelled;
+ WSC_UPNP_NODE_INFO *pWscUPnPInfo = &pWscControl->WscUPnPNodeInfo;
+ UINT MaxWscDataLen = WSC_MAX_DATA_LEN;
+ UCHAR CurOpMode = 0xFF;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction Enter!\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ CurOpMode = AP_MODE;
+#endif // CONFIG_AP_SUPPORT //
+
+
+ bUPnPMsg = Elem->MsgType == WSC_EAPOL_UPNP_MSG ? TRUE : FALSE;
+
+ if(bUPnPMsg)
+ {
+ if(MsgType == WSC_MSG_M1)
+ { /* It's a M1 message, we may need to initialize our state machine. */
+ if ((pWscControl->WscActionMode == WSC_REGISTRAR)
+ && (pWscControl->EntryIfIdx == WSC_INIT_ENTRY_APIDX)
+ && (pWscControl->WscState < WSC_STATE_WAIT_M1)
+ && (pWscUPnPInfo->bUPnPInProgress == FALSE))
+ {
+ pWscUPnPInfo->bUPnPInProgress = TRUE;
+ /*Set the WscState as "WSC_STATE_WAIT_RESP_ID" because UPnP start from this state. */
+ pWscControl->WscState = WSC_STATE_WAIT_M1;
+ RTMPSetTimer(&pWscUPnPInfo->UPnPMsgTimer, WSC_UPNP_MSG_TIME_OUT);
+ pWscUPnPInfo->bUPnPMsgTimerRunning = TRUE;
+ }
+ }
+ OpCode = WSC_OPCODE_UPNP_MASK;
+
+ } else {
+ if (pWscControl->EapolTimerRunning)
+ pWscControl->EapolTimerRunning = FALSE;
+
+ }
+
+#ifdef WSC_V2_SUPPORT
+ MaxWscDataLen = MaxWscDataLen + (UINT)pWscControl->WscV2Info.ExtraTlv.TlvLen;
+#endif /* WSC_V2_SUPPORT */
+ os_alloc_mem(NULL, (UCHAR **)&WscData, MaxWscDataLen);
+/* if( (WscData = kmalloc(WSC_MAX_DATA_LEN, GFP_ATOMIC)) == NULL) */
+ if (WscData == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscData Allocate failed!\n"));
+ goto Fail;
+ }
+ NdisZeroMemory(WscData, MaxWscDataLen);
+
+ /* Base on state doing the Msg, State change diagram */
+ switch (MsgType)
+ {
+ case WSC_MSG_M1:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Rx M1\n"));
+
+ /* Receive M1, if we are at WSC_STATE_WAIT_M1 start, process it immediately */
+ pWscControl->WscStatus = STATUS_WSC_EAP_M1_RECEIVED;
+ if (pWscControl->WscState == WSC_STATE_WAIT_M1)
+ {
+ OpCode |= WSC_OPCODE_MSG;
+
+ /* Process M1 */
+ if ((rv=ProcessMessageM1(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData)))
+ goto Fail;
+ else
+ {
+ BOOLEAN bSendM2D = TRUE;
+
+
+ if (pWscControl->bWscTrigger && (!pWscControl->bWscAutoTigeer))
+ {
+ if (((pWscControl->WscMode == WSC_PBC_MODE) || (pWscControl->WscMode == WSC_SMPBC_MODE))
+ || (pWscControl->WscMode == WSC_PIN_MODE && pWscControl->WscPinCode != 0))
+ bSendM2D = FALSE;
+ }
+
+ if (bSendM2D)
+ {
+ DataLen = BuildMessageM2D(pAdapter, pWscControl, WscData);
+ pWscControl->WscState = WSC_STATE_SENT_M2D;
+ pWscControl->M2DACKBalance++;
+ if (pWscControl->bM2DTimerRunning == FALSE)
+ {
+ // Add M2D timer used to trigger the EAPFail Packet!
+ RTMPSetTimer(&pWscControl->M2DTimer, WSC_UPNP_M2D_TIME_OUT);
+ pWscControl->bM2DTimerRunning = TRUE;
+ }
+ }
+ else
+ {
+ pWscControl->WscStatus = STATUS_WSC_EAP_M2_SENT;
+ DataLen = BuildMessageM2(pAdapter, pWscControl, WscData);
+
+ /* Change the state to next one */
+ pWscControl->WscState = WSC_STATE_WAIT_M3;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M2, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ }
+ }
+ }
+ break;
+
+ case WSC_MSG_M3:
+ /* Receive M3 */
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Rx M3\n"));
+ if (pWscControl->WscState == WSC_STATE_WAIT_M3)
+ {
+ pWscControl->WscStatus = STATUS_WSC_EAP_M3_RECEIVED;
+
+ if((rv = ProcessMessageM3(pAdapter, Elem->Msg, Elem->MsgLen, &pWscControl->RegData)))
+ goto Fail;
+ else
+ {
+ OpCode |= WSC_OPCODE_MSG;
+ DataLen = BuildMessageM4(pAdapter, pWscControl, WscData);
+ pWscControl->WscStatus = STATUS_WSC_EAP_M4_SENT;
+ /* Change the state to next one */
+ pWscControl->WscState = WSC_STATE_WAIT_M5;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M4, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ }
+ }
+ break;
+
+ case WSC_MSG_M5:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Rx M5\n"));
+ if (pWscControl->WscState == WSC_STATE_WAIT_M5)
+ {
+ pWscControl->WscStatus = STATUS_WSC_EAP_M5_RECEIVED;
+
+ if ((rv=ProcessMessageM5(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData)))
+ goto Fail;
+ else
+ {
+ OpCode |= WSC_OPCODE_MSG;
+ DataLen = BuildMessageM6(pAdapter, pWscControl, WscData);
+ pWscControl->WscStatus = STATUS_WSC_EAP_M6_SENT;
+ /* Change the state to next one */
+ pWscControl->WscState = WSC_STATE_WAIT_M7;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M6, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ }
+ }
+ break;
+ case WSC_MSG_M7:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Rx M7\n"));
+ if (pWscControl->WscState == WSC_STATE_WAIT_M7)
+ {
+ pWscControl->WscStatus = STATUS_WSC_EAP_M7_RECEIVED;
+ if ((rv=ProcessMessageM7(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData)))
+ goto Fail;
+ else
+ {
+ if (
+#ifdef CONFIG_AP_SUPPORT
+ (CurOpMode == AP_MODE) ||
+#endif /* CONFIG_AP_SUPPORT */
+ (0))
+ {
+ OpCode |= WSC_OPCODE_MSG;
+ DataLen = BuildMessageM8(pAdapter, pWscControl, WscData);
+ pWscControl->WscStatus = STATUS_WSC_EAP_M8_SENT;
+ /* Change the state to next one */
+ pWscControl->WscState = WSC_STATE_WAIT_DONE;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M8, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+#ifdef CONFIG_AP_SUPPORT
+#ifdef WSC_V2_SUPPORT
+
+ if (pWscControl->WscV2Info.bEnableWpsV2 && (CurOpMode == AP_MODE))
+ WscAddEntryToAclList(pAdapter, pEntry->apidx, pEntry->Addr);
+#endif /* WSC_V2_SUPPORT */
+ /*
+ 1. Complete WPS with this STA. Delete it from WscPeerList for others STA to do WSC with AP
+ 2. Some WPS STA will send dis-assoc close to WSC_DONE
+ then AP will miss WSC_DONE from STA; hence we need to call WscDelListEntryByMAC here.
+ */
+ if (pEntry && (CurOpMode == AP_MODE))
+ {
+ RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock);
+ WscDelListEntryByMAC(&pWscControl->WscPeerList, pEntry->Addr);
+ RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ }
+ }
+ break;
+
+ case WSC_MSG_WSC_DONE:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Rx DONE\n"));
+ if (pWscControl->WscState == WSC_STATE_WAIT_DONE)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ pWscControl->WscStatus = STATUS_WSC_EAP_RAP_RSP_DONE_SENT;
+ /* Send EAP-Fail */
+ WscSendEapFail(pAdapter, pWscControl, FALSE);
+ pWscControl->WscStatus = STATUS_WSC_CONFIGURED;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ pWscControl->WscState = WSC_STATE_CONFIGURED;
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_SUCCESS, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ pWscControl->EapMsgRunning = FALSE;
+ }
+ break;
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Unsupported Msg Type\n"));
+ if (WscData)
+ os_free_mem(NULL, WscData);
+ return;
+ }
+
+ if(OpCode > WSC_OPCODE_UPNP_MASK)
+ bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F),
+ WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_NORMAL,
+ WscData, DataLen,
+ Elem->TimeStamp.u.LowPart, Elem->TimeStamp.u.HighPart, &pWscControl->EntryAddr[0], CurOpMode);
+ else if(OpCode > 0 && OpCode < WSC_OPCODE_UPNP_MASK)
+ {
+#ifdef WSC_V2_SUPPORT
+ pWscControl->WscTxBufLen = 0;
+ pWscControl->pWscCurBufIdx = NULL;
+ pWscControl->bWscLastOne = TRUE;
+ if (pWscControl->bWscFragment && (DataLen > pWscControl->WscFragSize))
+ {
+ ASSERT(DataLen < MGMT_DMA_BUFFER_SIZE);
+ NdisMoveMemory(pWscControl->pWscTxBuf, WscData, DataLen);
+ pWscControl->WscTxBufLen = DataLen;
+ NdisZeroMemory(WscData, DataLen);
+ pWscControl->bWscLastOne = FALSE;
+ pWscControl->bWscFirstOne = TRUE;
+ NdisMoveMemory(WscData, pWscControl->pWscTxBuf, pWscControl->WscFragSize);
+ DataLen = pWscControl->WscFragSize;
+ pWscControl->WscTxBufLen -= pWscControl->WscFragSize;
+ pWscControl->pWscCurBufIdx = (pWscControl->pWscTxBuf + pWscControl->WscFragSize);
+ }
+#endif /* WSC_V2_SUPPORT */
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (pWscControl->WscState != WSC_STATE_CONFIGURED)
+ WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ }
+ else
+ bUPnPStatus = TRUE;
+
+ if(bUPnPMsg)
+ {
+ if(pWscControl->WscState == WSC_STATE_SENT_M2D)
+ { /*After M2D, reset the status of State Machine. */
+ pWscControl->WscState = WSC_STATE_WAIT_UPNP_START;
+ pWscUPnPInfo->bUPnPInProgress = FALSE;
+ }
+ }
+Fail:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : rv = %d\n", rv));
+ if (rv)
+ {
+ if (rv <= WSC_ERROR_DEV_PWD_AUTH_FAIL)
+ {
+ pWscControl->RegData.SelfInfo.ConfigError = rv;
+ }
+ else if ((rv == WSC_ERROR_HASH_FAIL) || (rv == WSC_ERROR_HMAC_FAIL))
+ pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_DECRYPT_CRC_FAIL;
+
+ switch(rv)
+ {
+ case WSC_ERROR_HASH_FAIL:
+ pWscControl->WscStatus = STATUS_WSC_ERROR_HASH_FAIL;
+ break;
+ case WSC_ERROR_HMAC_FAIL:
+ pWscControl->WscStatus = STATUS_WSC_ERROR_HMAC_FAIL;
+ break;
+ default:
+ pWscControl->WscStatus = STATUS_WSC_FAIL;
+ break;
+ }
+ RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+ if (bUPnPMsg)
+ {
+ if (pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE)
+ {
+ RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled);
+ pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE;
+ }
+ pWscUPnPInfo->bUPnPInProgress = FALSE;
+ }
+ else
+ {
+ DataLen = BuildMessageNACK(pAdapter, pWscControl, WscData);
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ WscSendMessage(pAdapter, WSC_OPCODE_NACK, WscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ);
+ pEntry->bWscCapable = FALSE;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled);
+ pWscControl->EapolTimerRunning = FALSE;
+ }
+ /*
+ If a PIN authentication or communication error occurs after sending message M6,
+ the Registrar MUST warn the user and MUST NOT automatically reuse the PIN.
+ Furthermore, if the Registrar detects this situation and prompts the user for a new PIN from the Enrollee device,
+ it MUST NOT accept the same PIN again without warning the user of a potential attack.
+ */
+ if (pWscControl->WscState >= WSC_STATE_WAIT_M7)
+ {
+ pWscControl->WscRejectSamePinFromEnrollee = TRUE;
+ pWscControl->WscPinCode = 0;
+ }
+ pWscControl->WscState = WSC_STATE_OFF;
+ pWscControl->WscStatus = STATUS_WSC_IDLE;
+ /*NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); */
+ /*pWscControl->WscMode = 1; */
+ bUPnPStatus = FALSE;
+ }
+
+ if(WscData)
+ os_free_mem(NULL, WscData);
+
+ if(bUPnPMsg && (bUPnPStatus == FALSE))
+ WscUPnPErrHandle(pAdapter, pWscControl, Elem->TimeStamp.u.LowPart);
+
+ if (pWscControl->WscState == WSC_STATE_CONFIGURED)
+ {
+#ifdef WSC_LED_SUPPORT
+ UCHAR WPSLEDStatus;
+#endif /* WSC_LED_SUPPORT */
+
+ pWscControl->bWscTrigger = FALSE;
+ if (pWscControl->Wsc2MinsTimerRunning)
+ {
+ pWscControl->Wsc2MinsTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled);
+ }
+ if (bUPnPMsg)
+ {
+ if (pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE)
+ { RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled);
+ pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE;
+ }
+ pWscUPnPInfo->bUPnPInProgress = FALSE;
+ pWscUPnPInfo->registrarID = 0;
+ }
+#ifdef CONFIG_AP_SUPPORT
+ else
+ {
+ if (CurOpMode == AP_MODE)
+ {
+ WscBuildBeaconIE(pAdapter, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, pEntry->apidx, NULL, 0, CurOpMode);
+ WscBuildProbeRespIE(pAdapter, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, pWscControl->EntryIfIdx, NULL, 0, CurOpMode);
+ APUpdateBeaconFrame(pAdapter, pEntry->apidx);
+
+ }
+ }
+ NdisZeroMemory(&pAdapter->CommonCfg.WscStaPbcProbeInfo, sizeof(WSC_STA_PBC_PROBE_INFO));
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (INFRA_ON(pAdapter) ||
+ (
+ (pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) &&
+ ((CurOpMode == AP_MODE) || (ADHOC_ON(pAdapter)))
+ )
+ )
+ {
+ pWscControl->WscConfStatus = WSC_SCSTATE_CONFIGURED;
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ {
+ /*
+ Use ApplyProfileIdx to inform WscUpdatePortCfgTimer AP acts registrar.
+ */
+ pWscControl->WscProfile.ApplyProfileIdx |= 0x8000;
+ RTMPSetTimer(&pWscControl->WscUpdatePortCfgTimer, 1000);
+ pWscControl->WscUpdatePortCfgTimerRunning = TRUE;
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+#ifdef WSC_LED_SUPPORT
+ /* The protocol is finished. */
+ WPSLEDStatus = LED_WPS_SUCCESS;
+ RTMPSetLED(pAdapter, WPSLEDStatus);
+#endif /* WSC_LED_SUPPORT */
+ {
+ pWscControl->WscPinCode = 0;
+ pWscControl->WscMode = 1;
+ }
+ RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled);
+ pWscControl->EapolTimerRunning = FALSE;
+
+ return;
+ }
+}
+
+VOID WscTimeOutProcess(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN INT nWscState,
+ IN PWSC_CTRL pWscControl)
+{
+ INT WscMode;
+ UCHAR CurOpMode = 0xFF;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ CurOpMode = AP_MODE;
+#endif // CONFIG_AP_SUPPORT //
+
+
+ if (nWscState == WSC_STATE_WAIT_ACK)
+ pWscControl->WscState = WSC_STATE_CONFIGURED;
+ else if (nWscState == WSC_STATE_WAIT_RESP_ID)
+ pWscControl->WscState = WSC_STATE_OFF;
+ else if (nWscState == WSC_STATE_RX_M2D)
+ {
+ pWscControl->WscState = WSC_STATE_FAIL;
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (pEntry && IS_ENTRY_CLIENT(pEntry))
+ {
+ WscSendEapFail(pAd, pWscControl, TRUE);
+ }
+#ifdef APCLI_SUPPORT
+ if (pEntry && IS_ENTRY_APCLI(pEntry))
+ {
+ WscApCliLinkDown(pAd, pWscControl);
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ pWscControl->EapolTimerRunning = FALSE;
+ pWscControl->WscRetryCount = 0;
+
+
+ return;
+ }
+ else if (nWscState == WSC_STATE_WAIT_EAPFAIL)
+ {
+ pWscControl->WscState = WSC_STATE_OFF;
+ pWscControl->WscStatus = STATUS_WSC_CONFIGURED;
+ pWscControl->WscConfMode = WSC_DISABLE;
+ }
+ else
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if ((pWscControl->WscActionMode == WSC_PROXY) && (pAd->OpMode == OPMODE_AP))
+ {
+ pWscControl->WscState = WSC_STATE_OFF;
+ }
+ else
+#endif /* CONFIG_AP_SUPPORT */
+ pWscControl->WscState = WSC_STATE_FAIL;
+ }
+
+ if (nWscState == WSC_STATE_WAIT_M8)
+ pWscControl->bWscTrigger = FALSE;
+ pWscControl->WscRetryCount = 0;
+ NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN);
+ pWscControl->EapolTimerRunning = FALSE;
+ if (pWscControl->WscMode == 1)
+ WscMode = DEV_PASS_ID_PIN;
+ else
+ WscMode = DEV_PASS_ID_PBC;
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if ((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) &&
+ ((nWscState == WSC_STATE_WAIT_DONE) || (nWscState == WSC_STATE_WAIT_ACK)))
+ {
+ pWscControl->bWscTrigger = FALSE;
+ pWscControl->WscConfStatus = WSC_SCSTATE_CONFIGURED;
+ WscBuildBeaconIE(pAd, pWscControl->WscConfStatus, FALSE, WscMode, pWscControl->WscConfigMethods, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode);
+ WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, pWscControl->WscConfStatus, FALSE, WscMode, pWscControl->WscConfigMethods, pWscControl->EntryIfIdx, NULL, 0, CurOpMode);
+ pAd->WriteWscCfgToDatFile = pWscControl->EntryIfIdx;
+ WscWriteConfToPortCfg(pAd,
+ pWscControl,
+ &pWscControl->WscProfile.Profile[0],
+ FALSE);
+ {
+ APStop(pAd);
+ APStartUp(pAd);
+ }
+
+/*#ifdef KTHREAD_SUPPORT */
+/* WAKE_UP(&(pAd->wscTask)); */
+/*#else */
+/* RTMP_SEM_EVENT_UP(&(pAd->wscTask.taskSema)); */
+/*#endif */
+ RtmpOsTaskWakeUp(&(pAd->wscTask));
+ }
+ else
+ {
+ if (pEntry && IS_ENTRY_CLIENT(pEntry))
+ {
+ pEntry->bWscCapable = FALSE;
+ WscSendEapFail(pAd, pWscControl, TRUE);
+ }
+
+ WscBuildBeaconIE(pAd, pWscControl->WscConfStatus, FALSE, WscMode, pWscControl->WscConfigMethods, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode);
+ WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, pWscControl->WscConfStatus, FALSE, WscMode, pWscControl->WscConfigMethods, pWscControl->EntryIfIdx, NULL, 0, CurOpMode);
+ }
+#ifdef APCLI_SUPPORT
+ if (pEntry && IS_ENTRY_APCLI(pEntry))
+ {
+ WscApCliLinkDown(pAd, pWscControl);
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscTimeOutProcess\n"));
+}
+
+VOID WscEAPOLTimeOutAction(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ PUCHAR WscData = NULL;
+ PMAC_TABLE_ENTRY pEntry = NULL;
+ PWSC_CTRL pWscControl = NULL;
+ PRTMP_ADAPTER pAd = NULL;
+ UINT MaxWscDataLen = WSC_MAX_DATA_LEN;
+ UCHAR CurOpMode = 0xFF;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscEAPOLTimeOutAction\n"));
+
+ if (FunctionContext == 0)
+ {
+ return;
+ }
+ else
+ {
+ pWscControl = (PWSC_CTRL)FunctionContext;
+ pAd = (PRTMP_ADAPTER)pWscControl->pAd;
+ if (pAd == NULL)
+ {
+ return;
+ }
+ pEntry = MacTableLookup(pWscControl->pAd, pWscControl->EntryAddr);
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ CurOpMode = AP_MODE;
+#endif // CONFIG_AP_SUPPORT //
+
+
+ if ((CurOpMode == AP_MODE) || ADHOC_ON(pAd))
+ {
+ if (pEntry == NULL)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ /*
+ Some WPS Client will send dis-assoc close to WSC_DONE.
+ If AP misses WSC_DONE, WPS Client still sends dis-assoc to AP.
+ AP driver needs to check wsc_state here for considering WPS process with this client is completed.
+ */
+ if ((CurOpMode == AP_MODE) &&
+ ((pWscControl->WscState == WSC_STATE_WAIT_DONE) || (pWscControl->WscState == WSC_STATE_WAIT_ACK)))
+ {
+ pWscControl->WscStatus = STATUS_WSC_CONFIGURED;
+ pWscControl->bWscTrigger = FALSE;
+ pWscControl->RegData.ReComputePke = 1;
+ if (pWscControl->Wsc2MinsTimerRunning)
+ {
+ BOOLEAN Cancelled;
+ pWscControl->Wsc2MinsTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled);
+ }
+ WscTimeOutProcess(pAd, NULL, pWscControl->WscState, pWscControl);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ pWscControl->EapolTimerRunning = FALSE;
+ NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN);
+ DBGPRINT(RT_DEBUG_TRACE, ("sta is left.\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLTimeOutAction\n"));
+ return;
+ }
+ }
+
+ if (!pWscControl->EapolTimerRunning)
+ {
+ pWscControl->WscRetryCount = 0;
+ goto out;
+ }
+
+ if (pWscControl->EapolTimerPending)
+ {
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ DBGPRINT(RT_DEBUG_TRACE, ("EapolTimer Pending......\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLTimeOutAction\n"));
+ return;
+ }
+
+#ifdef WSC_V2_SUPPORT
+ MaxWscDataLen = MaxWscDataLen + (UINT)pWscControl->WscV2Info.ExtraTlv.TlvLen;
+#endif /* WSC_V2_SUPPORT */
+ os_alloc_mem(NULL, (UCHAR **)&WscData, MaxWscDataLen);
+/* if ((WscData = kmalloc(WSC_MAX_DATA_LEN, GFP_ATOMIC))!= NULL) */
+ if (WscData != NULL)
+ NdisZeroMemory(WscData, WSC_MAX_DATA_LEN);
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (pEntry && IS_ENTRY_CLIENT(pEntry) && (pWscControl->WscState <= WSC_STATE_CONFIGURED) && (pWscControl->WscActionMode != WSC_PROXY))
+ {
+ /* A timer in the AP should cause to be disconnected after 5 seconds if a */
+ /* valid EAP-Rsp/Identity indicating WPS is not received. */
+ /* << from WPS EAPoL and RSN handling.doc >> */
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_RESP_ID, pWscControl);
+
+ /* If do disassocation here, it will affect connection of non-WPS clients. */
+ goto out;
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscState = %d\n", pWscControl->WscState));
+ switch(pWscControl->WscState)
+ {
+ case WSC_STATE_WAIT_REQ_ID:
+ /* For IWSC case, keep sending EAPOL_START until 2 mins timeout */
+ if ((pWscControl->WscRetryCount >= 2)
+ )
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_REQ_ID, pWscControl);
+ else
+ {
+ pWscControl->WscRetryCount++;
+ WscSendEapolStart(pAd, pEntry->Addr, CurOpMode);
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+ case WSC_STATE_WAIT_WSC_START:
+ if (pWscControl->WscRetryCount >= 2)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_WSC_START, pWscControl);
+ else
+ {
+ pWscControl->WscRetryCount++;
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+ case WSC_STATE_WAIT_M1:
+ if (pWscControl->WscRetryCount >= 2)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M1, pWscControl);
+ else
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_START, NULL, 0, pWscControl, AP_MODE, EAP_CODE_REQ);
+#endif /* CONFIG_AP_SUPPORT */
+ pWscControl->WscRetryCount++;
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+ case WSC_STATE_SENT_M1:
+ if (pWscControl->WscRetryCount >= 2)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M2, pWscControl);
+ else
+ {
+ if (pWscControl->WscActionMode == WSC_ENROLLEE)
+ {
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (IS_ENTRY_CLIENT(pEntry))
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ);
+ else if (IS_ENTRY_APCLI(pEntry))
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ }
+ pWscControl->WscRetryCount++;
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+ case WSC_STATE_RX_M2D:
+ if (pWscControl->WscRetryCount >= 2)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_RX_M2D, pWscControl);
+ else
+ {
+ pWscControl->WscRetryCount++;
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+ case WSC_STATE_WAIT_PIN:
+ if (pWscControl->WscRetryCount >= 2)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_PIN, pWscControl);
+ else
+ {
+ pWscControl->WscRetryCount++;
+ DBGPRINT(RT_DEBUG_TRACE, ("No PIN CODE, cannot send M2 out!\n"));
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+ case WSC_STATE_WAIT_M3:
+ if (pWscControl->WscRetryCount >= 2)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M3, pWscControl);
+ else
+ {
+ if (pWscControl->WscActionMode == WSC_REGISTRAR)
+ {
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ);
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ }
+ pWscControl->WscRetryCount++;
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+ case WSC_STATE_WAIT_M4:
+ if (pWscControl->WscRetryCount >= 2)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M4, pWscControl);
+ else
+ {
+ if (pWscControl->WscActionMode == WSC_ENROLLEE)
+ {
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (IS_ENTRY_CLIENT(pEntry))
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ);
+ else if (IS_ENTRY_APCLI(pEntry))
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ }
+ pWscControl->WscRetryCount++;
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+ case WSC_STATE_WAIT_M5:
+ if (pWscControl->WscRetryCount >= 2)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M5, pWscControl);
+ else
+ {
+ if (pWscControl->WscActionMode == WSC_REGISTRAR)
+ {
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ);
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ }
+ pWscControl->WscRetryCount++;
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+ case WSC_STATE_WAIT_M6:
+ if (pWscControl->WscRetryCount >= 2)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M6, pWscControl);
+ else
+ {
+ if (pWscControl->WscActionMode == WSC_ENROLLEE)
+ {
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (IS_ENTRY_CLIENT(pEntry))
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ);
+ else if (IS_ENTRY_APCLI(pEntry))
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ }
+ pWscControl->WscRetryCount++;
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+ case WSC_STATE_WAIT_M7:
+ if (pWscControl->WscRetryCount >= 2)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M7, pWscControl);
+ else
+ {
+ if (pWscControl->WscActionMode == WSC_REGISTRAR)
+ {
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ);
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ }
+ pWscControl->WscRetryCount++;
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+ case WSC_STATE_WAIT_M8:
+ if (pWscControl->WscRetryCount >= 2)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_M8, pWscControl);
+ else
+ {
+ if (pWscControl->WscActionMode == WSC_ENROLLEE)
+ {
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (IS_ENTRY_CLIENT(pEntry))
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ);
+ else if (IS_ENTRY_APCLI(pEntry))
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ }
+ pWscControl->WscRetryCount++;
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+ case WSC_STATE_WAIT_DONE:
+ if (pWscControl->WscRetryCount >= 2)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_DONE, pWscControl);
+ else
+ {
+ if (pWscControl->WscActionMode == WSC_REGISTRAR)
+ {
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ WscSendMessage(pWscControl->pAd, WSC_OPCODE_MSG, pWscControl->RegData.LastTx.Data, pWscControl->RegData.LastTx.Length, pWscControl, AP_MODE, EAP_CODE_REQ);
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ }
+ pWscControl->WscRetryCount++;
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT);
+ }
+ break;
+#ifdef CONFIG_AP_SUPPORT
+ /* Only AP_Enrollee needs to wait EAP_ACK */
+ case WSC_STATE_WAIT_ACK:
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_ACK, pWscControl);
+ break;
+#endif /* CONFIG_AP_SUPPORT */
+ case WSC_STATE_WAIT_EAPFAIL:
+ /* Wait 2 seconds */
+ if (pWscControl->WscRetryCount >= 1)
+ WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_EAPFAIL, pWscControl);
+ else
+ {
+ RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_EAP_FAIL_TIME_OUT);
+ pWscControl->WscRetryCount++;
+ }
+ break;
+ default:
+ break;
+ }
+
+out:
+ if (WscData)
+ os_free_mem(NULL, WscData);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLTimeOutAction\n"));
+}
+
+VOID Wsc2MinsTimeOutAction(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext;
+ PRTMP_ADAPTER pAd = NULL;
+#ifdef CONFIG_AP_SUPPORT
+ INT IsAPConfigured = 0;
+#endif /* CONFIG_AP_SUPPORT */
+ BOOLEAN Cancelled;
+ UCHAR CurOpMode = 0xFF;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> Wsc2MinsTimeOutAction\n"));
+ if (pWscControl != NULL)
+ {
+ pAd = (PRTMP_ADAPTER)pWscControl->pAd;
+
+ if (pAd == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("pAd is NULL!\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- Wsc2MinsTimeOutAction\n"));
+ return;
+ }
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Wsc2MinsTimerRunning is %s\n",
+ pWscControl->Wsc2MinsTimerRunning ? "TRUE, reset WscState to WSC_STATE_OFF":"FALSE"));
+
+#ifdef WSC_LED_SUPPORT
+ /* 120 seconds WPS walk time expiration. */
+ pWscControl->bWPSWalkTimeExpiration = TRUE;
+#endif /* WSC_LED_SUPPORT */
+
+ if (pWscControl->Wsc2MinsTimerRunning)
+ {
+ pWscControl->bWscTrigger = FALSE;
+ pWscControl->EapolTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled);
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ IsAPConfigured = pWscControl->WscConfStatus;
+ if ((pWscControl->EntryIfIdx & 0x0F) < pAd->ApCfg.BssidNum)
+ {
+ WscBuildBeaconIE(pWscControl->pAd, IsAPConfigured, FALSE, 0, 0, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode);
+ WscBuildProbeRespIE(pWscControl->pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, pWscControl->EntryIfIdx, NULL, 0, CurOpMode);
+ APUpdateBeaconFrame(pWscControl->pAd, pWscControl->EntryIfIdx & 0x0F);
+ }
+ if ((pWscControl->WscConfMode & WSC_PROXY) == 0)
+ { /* Proxy mechanism is disabled */
+ pWscControl->WscState = WSC_STATE_OFF;
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ pWscControl->WscMode = 1;
+ pWscControl->WscRetryCount = 0;
+ pWscControl->Wsc2MinsTimerRunning = FALSE;
+
+ pWscControl->WscSelReg = 0;
+ pWscControl->WscStatus = STATUS_WSC_IDLE;
+
+ RTMPSendWirelessEvent(pAd, IW_WSC_2MINS_TIMEOUT, NULL, (pWscControl->EntryIfIdx & 0x0F), 0);
+
+ if (pWscControl->WscScanTimerRunning)
+ {
+ pWscControl->WscScanTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->WscScanTimer, &Cancelled);
+ }
+ if (pWscControl->WscPBCTimerRunning)
+ {
+ pWscControl->WscPBCTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->WscPBCTimer, &Cancelled);
+ }
+ }
+
+#ifdef WSC_LED_SUPPORT
+ /* if link is up, there shall be nothing wrong */
+ /* perhaps we will set another flag to do it */
+ if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) &&
+ (pWscControl->WscState == WSC_STATE_OFF) &&
+ (pWscControl->WscStatus == STATUS_WSC_CONFIGURED))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscConnectTimeout --> Connection OK\n"));
+ }
+ else
+ {
+ UCHAR WPSLEDStatus;
+
+ pWscControl->WscStatus = STATUS_WSC_FAIL;
+ pWscControl->WscState = WSC_STATE_OFF;
+
+ /* WPS LED mode 7, 8, 11 or 12. */
+ if ((LED_MODE(pAd) == WPS_LED_MODE_7) ||
+ (LED_MODE(pAd) == WPS_LED_MODE_8) ||
+ (LED_MODE(pAd) == WPS_LED_MODE_11) ||
+ (LED_MODE(pAd) == WPS_LED_MODE_12))
+ {
+ pWscControl->bSkipWPSTurnOffLED = FALSE;
+
+ /* Turn off the WPS LED modoe due to the maximum WPS processing time is expired (120 seconds). */
+ WPSLEDStatus = LED_WPS_TURN_LED_OFF;
+ RTMPSetLED(pAd, WPSLEDStatus);
+ }
+ else if ((LED_MODE(pAd) == WPS_LED_MODE_9) /* WPS LED mode 9. */
+ )
+ {
+ if (pWscControl->WscMode == WSC_PIN_MODE) /* PIN method. */
+ {
+ /* The NIC using PIN method fails to finish the WPS handshaking within 120 seconds. */
+ WPSLEDStatus = LED_WPS_ERROR;
+ RTMPSetLED(pAd, WPSLEDStatus);
+ /* Turn off the WPS LED after 15 seconds. */
+ RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_FAIL_LED_PATTERN_TIMEOUT);
+
+ /* The Ralink UI would make RT_OID_DISCONNECT_REQUEST request while it receive STATUS_WSC_EAP_FAILED. */
+ /* Allow the NIC to turn off the WPS LED after WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT seconds. */
+ pWscControl->bSkipWPSTurnOffLED = TRUE;
+ RTMPSetTimer(&pWscControl->WscSkipTurnOffLEDTimer, WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: The NIC using PIN method fails to finish the WPS handshaking within 120 seconds.\n", __FUNCTION__));
+ }
+ else if (pWscControl->WscMode == WSC_PBC_MODE) /* PBC method. */
+ {
+ switch (pWscControl->WscLastWarningLEDMode) /* Based on last WPS warning LED mode. */
+ {
+ case 0:
+ case LED_WPS_ERROR:
+ case LED_WPS_SESSION_OVERLAP_DETECTED:
+ /* Failed to find any partner. */
+ WPSLEDStatus = LED_WPS_ERROR;
+ RTMPSetLED(pAd, WPSLEDStatus);
+
+ /* Turn off the WPS LED after 15 seconds. */
+ RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_FAIL_LED_PATTERN_TIMEOUT);
+
+ /* The Ralink UI would make RT_OID_DISCONNECT_REQUEST request while it receive STATUS_WSC_EAP_FAILED. */
+ /* Allow the NIC to turn off the WPS LED after WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT seconds. */
+ pWscControl->bSkipWPSTurnOffLED = TRUE;
+ RTMPSetTimer(&pWscControl->WscSkipTurnOffLEDTimer, WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Last WPS LED status is LED_WPS_ERROR.\n", __FUNCTION__));
+ break;
+
+ default:
+ /* do nothing. */
+ break;
+ }
+ }
+ else
+ {
+ /* do nothing. */
+ }
+ }
+ else
+ {
+ /* do nothing. */
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscConnectTimeout --> Fail to connect\n"));
+ }
+#endif /* WSC_LED_SUPPORT */
+ }
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- Wsc2MinsTimeOutAction\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Classify EAP message type for enrolee
+
+ Arguments:
+ pAd - NIC Adapter pointer
+ Elem - The EAP packet
+
+ Return Value:
+ Received EAP message type
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+UCHAR WscRxMsgType(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PMLME_QUEUE_ELEM pElem)
+{
+ USHORT Length;
+ PUCHAR pData;
+ USHORT WscType, WscLen;
+ STRING id_data[] = {"hello"};
+ STRING fail_data[] = {"EAP_FAIL"};
+ STRING wsc_start[] = {"WSC_START"};
+#ifdef WSC_V2_SUPPORT
+ STRING wsc_frag_ack[] = "WSC_FRAG_ACK";
+#endif /* WSC_V2_SUPPORT */
+ STRING regIdentity[] = {"WFA-SimpleConfig-Registrar"};
+ STRING enrIdentity[] = {"WFA-SimpleConfig-Enrollee"};
+
+ if (pElem->Msg[0] == 'W' && pElem->Msg[1] == 'F' && pElem->Msg[2] == 'A')
+ {
+ /* Eap-Rsp(Identity) */
+ if (memcmp(regIdentity, pElem->Msg, strlen(regIdentity)) == 0)
+ return WSC_MSG_EAP_REG_RSP_ID;
+ else if (memcmp(enrIdentity, pElem->Msg, strlen(enrIdentity)) == 0)
+ return WSC_MSG_EAP_ENR_RSP_ID;
+ }
+ else if (NdisEqualMemory(id_data, pElem->Msg, pElem->MsgLen))
+ {
+ /* Eap-Req/Identity(hello) */
+ return WSC_MSG_EAP_REQ_ID;
+ }
+ else if (NdisEqualMemory(fail_data, pElem->Msg, pElem->MsgLen))
+ {
+ /* Eap-Fail */
+ return WSC_MSG_EAP_FAIL;
+ }
+ else if (NdisEqualMemory(wsc_start, pElem->Msg, pElem->MsgLen))
+ {
+ /* Eap-Req(Wsc_Start) */
+ return WSC_MSG_EAP_REQ_START;
+ }
+#ifdef WSC_V2_SUPPORT
+ else if (NdisEqualMemory(wsc_frag_ack, pElem->Msg, pElem->MsgLen))
+ {
+ /* WSC FRAG ACK */
+ return WSC_MSG_EAP_FRAG_ACK;
+ }
+#endif /* WSC_V2_SUPPORT */
+ else
+ { /* Eap-Esp(Messages) */
+ pData = pElem->Msg;
+ Length = (USHORT)pElem->MsgLen;
+
+ /* the first TLV item in EAP Messages must be WSC_IE_VERSION */
+ NdisMoveMemory(&WscType, pData, 2);
+ if (ntohs(WscType) != WSC_ID_VERSION)
+ goto out;
+
+ /* Not Wsc Start, We have to look for WSC_IE_MSG_TYPE to classify M2 ~ M8, the remain size must large than 4 */
+ while (Length > 4)
+ {
+ /* arm-cpu has packet alignment issue, it's better to use memcpy to retrieve data */
+ NdisMoveMemory(&WscType, pData, 2);
+ NdisMoveMemory(&WscLen, pData + 2, 2);
+ WscLen = ntohs(WscLen);
+ if (ntohs(WscType) == WSC_ID_MSG_TYPE)
+ {
+ return(*(pData + 4)); /* Found the message type */
+ }
+ else
+ {
+ pData += (WscLen + 4);
+ Length -= (WscLen + 4);
+ }
+ }
+ }
+
+out:
+ return WSC_MSG_UNKNOWN;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Classify WSC message type
+
+ Arguments:
+ EAPType Value of EAP message type
+ MsgType Internal Message definition for MLME state machine
+
+ Return Value:
+ TRUE Found appropriate message type
+ FALSE No appropriate message type
+
+ Note:
+ All these constants are defined in wsc.h
+ For supplicant, there is only EAPOL Key message avaliable
+
+ ========================================================================
+*/
+BOOLEAN WscMsgTypeSubst(
+ IN UCHAR EAPType,
+ IN UCHAR EAPCode,
+ OUT INT *MsgType)
+{
+ switch (EAPType)
+ {
+ case EAPPacket:
+ *MsgType = WSC_EAPOL_PACKET_MSG;
+ break;
+ case EAPOLStart:
+ *MsgType = WSC_EAPOL_START_MSG;
+ break;
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscMsgTypeSubst : unsupported EAP Type(%d); \n", EAPType));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+VOID WscInitRegistrarPair(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ IN UCHAR apidx)
+{
+ UCHAR CurOpMode = 0xff;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscInitRegistrarPair\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ CurOpMode = AP_MODE;
+#endif // CONFIG_AP_SUPPORT //
+
+
+ pWscControl->WscActionMode = 0;
+
+ /* 1. Version */
+ /*pWscControl->RegData.SelfInfo.Version = WSC_VERSION; */
+
+ /* 2. UUID Enrollee, last 6 bytes use MAC */
+ NdisMoveMemory(&pWscControl->RegData.SelfInfo.Uuid[0], &pWscControl->Wsc_Uuid_E[0], UUID_LEN_HEX);
+
+ /* 3. MAC address */
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (apidx >= HW_BEACON_MAX_NUM)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("%s: apidx >= HW_BEACON_MAX_NUM!\n", __FUNCTION__));
+ apidx = 0;
+ }
+ NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr, pAdapter->ApCfg.MBSSID[apidx].Bssid, 6);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* 4. Device Name */
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (!RTMP_TEST_FLAG(pWscControl, 0x04))
+ NdisMoveMemory(&pWscControl->RegData.SelfInfo.DeviceName, AP_WSC_DEVICE_NAME, sizeof(AP_WSC_DEVICE_NAME));
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /* 5. Manufacture woody */
+ if (!RTMP_TEST_FLAG(pWscControl, 0x01))
+ NdisMoveMemory(&pWscControl->RegData.SelfInfo.Manufacturer, WSC_MANUFACTURE, sizeof(WSC_MANUFACTURE));
+
+ /* 6. Model Name */
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (!RTMP_TEST_FLAG(pWscControl, 0x02))
+ NdisMoveMemory(&pWscControl->RegData.SelfInfo.ModelName, AP_WSC_MODEL_NAME, sizeof(AP_WSC_MODEL_NAME));
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /* 7. Model Number */
+
+ if (!RTMP_TEST_FLAG(pWscControl, 0x08))
+ NdisMoveMemory(&pWscControl->RegData.SelfInfo.ModelNumber, WSC_MODEL_NUMBER, sizeof(WSC_MODEL_NUMBER));
+
+ /* 8. Serial Number */
+ if (!RTMP_TEST_FLAG(pWscControl, 0x10))
+ NdisMoveMemory(&pWscControl->RegData.SelfInfo.SerialNumber, WSC_MODEL_SERIAL, sizeof(WSC_MODEL_SERIAL));
+
+ /* 9. Authentication Type Flags */
+ /* Open(=1), WPAPSK(=2),Shared(=4), WPA2PSK(=20),WPA(=8),WPA2(=10) */
+ /* (0x01 | 0x02 | 0x04 | 0x20 | 0x08 | 0x10) = 0x3F */
+ /* WCN vista logo will check this flags. */
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ /*
+ AuthTypeFlags only needs to include Open and WPA2PSK in WSC 2.0.
+ */
+ pWscControl->RegData.SelfInfo.AuthTypeFlags = cpu2be16(0x0021);
+ else
+#endif /* WSC_V2_SUPPORT */
+ pWscControl->RegData.SelfInfo.AuthTypeFlags = cpu2be16(0x003F);
+
+ /* 10. Encryption Type Flags */
+ /* None(=1), WEP(=2), TKIP(=4), AES(=8) */
+ /* (0x01 | 0x02 | 0x04 | 0x08) = 0x0F */
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ /*
+ EncrTypeFlags only needs to include None and AES in WSC 2.0.
+ */
+ pWscControl->RegData.SelfInfo.EncrTypeFlags = cpu2be16(0x0009);
+ else
+#endif /* WSC_V2_SUPPORT */
+ pWscControl->RegData.SelfInfo.EncrTypeFlags = cpu2be16(0x000F);
+
+ /* 11. Connection Type Flag */
+ pWscControl->RegData.SelfInfo.ConnTypeFlags = 0x01; /* ESS */
+
+ /* 12. Associate state */
+ pWscControl->RegData.SelfInfo.AssocState = cpu2be16(0x0000); /* Not associated */
+
+ /* 13. Configure Error */
+ pWscControl->RegData.SelfInfo.ConfigError = cpu2be16(0x0000); /* No error */
+
+ /* 14. OS Version */
+ pWscControl->RegData.SelfInfo.OsVersion = cpu2be32(0x80000000); /* first bit must be 1 */
+
+ /* 15. RF Band */
+ /* Some WPS AP would check RfBand value in M1, ex. D-Link DIR-628 */
+ pWscControl->RegData.SelfInfo.RfBand = 0x00;
+ if (WMODE_CAP_5G(pAdapter->CommonCfg.PhyMode))
+ pWscControl->RegData.SelfInfo.RfBand |= WSC_RFBAND_50GHZ; /* 5.0G */
+
+ if (WMODE_CAP_2G(pAdapter->CommonCfg.PhyMode))
+ pWscControl->RegData.SelfInfo.RfBand |= WSC_RFBAND_24GHZ; /* 2.4G */
+
+ /* 16. Config Method */
+ pWscControl->RegData.SelfInfo.ConfigMethods = cpu2be16(pWscControl->WscConfigMethods);
+ /*pWscControl->RegData.EnrolleeInfo.ConfigMethods = cpu2be16(WSC_CONFIG_METHODS); // Label, Display, PBC */
+ /*pWscControl->RegData.EnrolleeInfo.ConfigMethods = cpu2be16(0x0084); // Label, Display, PBC */
+
+ /* 17. Simple Config State */
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ pWscControl->RegData.SelfInfo.ScState = pWscControl->WscConfStatus;
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* 18. Device Password ID */
+ if (pWscControl->WscMode == WSC_PIN_MODE)
+ {
+ pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PIN); /* PIN mode */
+ }
+ else
+ {
+ pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PBC); /* PBC */
+ }
+
+ /* 19. SSID */
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ NdisMoveMemory(pWscControl->RegData.SelfInfo.Ssid, pAdapter->ApCfg.MBSSID[apidx].Ssid, pAdapter->ApCfg.MBSSID[apidx].SsidLen);
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* 20. Primary Device Type */
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (pWscControl->EntryIfIdx & MIN_NET_DEVICE_FOR_APCLI)
+ NdisMoveMemory(&pWscControl->RegData.SelfInfo.PriDeviceType, &STA_Wsc_Pri_Dev_Type[0], 8);
+ else
+ NdisMoveMemory(&pWscControl->RegData.SelfInfo.PriDeviceType, &AP_Wsc_Pri_Dev_Type[0], 8);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscInitRegistrarPair\n"));
+}
+
+VOID WscSendEapReqId(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN UCHAR CurOpMode)
+{
+ UCHAR Header802_3[14];
+ USHORT Length;
+ IEEE8021X_FRAME Ieee_8021x;
+ EAP_FRAME EapFrame;
+ UCHAR *pOutBuffer = NULL;
+ ULONG FrameLen = 0;
+ UCHAR Data[] = "hello";
+ UCHAR Id;
+ PWSC_CTRL pWpsCtrl = NULL;
+
+ NdisZeroMemory(Header802_3,sizeof(UCHAR)*14);
+
+ /* 1. Send EAP-Rsp Id */
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendEapReqId\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ pWpsCtrl = &pAd->ApCfg.MBSSID[pEntry->apidx].WscControl;
+ MAKE_802_3_HEADER(Header802_3,
+ &pEntry->Addr[0],
+ &pAd->ApCfg.MBSSID[pEntry->apidx].Bssid[0],
+ EAPOL);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ if (pWpsCtrl == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("pWpsCtrl == NULL!\n"));
+ return;
+ }
+
+ /* Length, -1 NULL pointer of string */
+ Length = sizeof(EAP_FRAME) + sizeof(Data) - 1;
+
+ /* Zero 802.1x body */
+ NdisZeroMemory(&Ieee_8021x, sizeof(Ieee_8021x));
+ Ieee_8021x.Version = EAPOL_VER;
+ Ieee_8021x.Type = EAPPacket;
+ Ieee_8021x.Length = cpu2be16(Length);
+
+ /* Zero EAP frame */
+ NdisZeroMemory(&EapFrame, sizeof(EapFrame));
+ /* RFC 3748 Ch 4.1: recommended to initalize Identifier with a
+ * random number */
+ Id = RandomByte(pAd);
+ if (Id == pWpsCtrl->lastId)
+ Id += 1;
+ EapFrame.Code = EAP_CODE_REQ;
+ EapFrame.Id = Id;
+ EapFrame.Length = cpu2be16(Length);
+ EapFrame.Type = EAP_TYPE_ID;
+ pWpsCtrl->lastId = Id;
+
+ /* Out buffer for transmitting EAP-Req(Identity) */
+/* pOutBuffer = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER);
+ if(pOutBuffer == NULL)
+ return;
+
+ FrameLen = 0;
+
+ /* Make Transmitting frame */
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(IEEE8021X_FRAME), &Ieee_8021x,
+ sizeof(EapFrame), &EapFrame,
+ (sizeof(Data) - 1), Data,
+ END_OF_ARGS);
+
+ /* Copy frame to Tx ring */
+ RTMPToWirelessSta(pAd, pEntry, Header802_3, sizeof(Header802_3), (PUCHAR)pOutBuffer, FrameLen, TRUE);
+
+ pWpsCtrl->WscRetryCount = 0;
+ if (pOutBuffer)
+/* kfree(pOutBuffer); */
+ os_free_mem(NULL, pOutBuffer);
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendEapReqId\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Send EAPoL-Start packet to AP.
+
+ Arguments:
+ pAd - NIC Adapter pointer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after link up
+ 1. Change the correct parameters
+ 2. Send EAPOL - START
+
+ ========================================================================
+*/
+VOID WscSendEapolStart(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PUCHAR pBssid,
+ IN UCHAR CurOpMode)
+{
+ IEEE8021X_FRAME Packet;
+ UCHAR Header802_3[14];
+ MAC_TABLE_ENTRY *pEntry;
+
+ pEntry = MacTableLookup(pAdapter, pBssid);
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendEapolStart\n"));
+
+ NdisZeroMemory(Header802_3,sizeof(UCHAR)*14);
+
+ /* 1. Change the authentication to open and encryption to none if necessary. */
+
+ /* init 802.3 header and Fill Packet */
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ MAKE_802_3_HEADER(Header802_3,
+ pBssid,
+ &pAdapter->ApCfg.ApCliTab[0].CurrentAddress[0],
+ EAPOL);
+ }
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Zero message 2 body */
+ NdisZeroMemory(&Packet, sizeof(Packet));
+ Packet.Version = EAPOL_VER;
+ Packet.Type = EAPOLStart;
+ Packet.Length = cpu2be16(0);
+
+ if (pEntry)
+ RTMPToWirelessSta(pAdapter, pEntry, Header802_3, sizeof(Header802_3), (PUCHAR)&Packet, 4, TRUE);
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ /* Update WSC status */
+ pAdapter->ApCfg.ApCliTab[0].WscControl.WscStatus = STATUS_WSC_EAPOL_START_SENT;
+ pAdapter->ApCfg.ApCliTab[0].WscControl.WscState = WSC_STATE_WAIT_REQ_ID;
+ if (!pAdapter->ApCfg.ApCliTab[0].WscControl.EapolTimerRunning)
+ {
+ pAdapter->ApCfg.ApCliTab[0].WscControl.EapolTimerRunning = TRUE;
+ RTMPSetTimer(&pAdapter->ApCfg.ApCliTab[0].WscControl.EapolTimer, WSC_EAPOL_START_TIME_OUT);
+ }
+ }
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendEapolStart\n"));
+}
+
+VOID WscSendEapRspId(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PWSC_CTRL pWscControl)
+{
+ UCHAR Header802_3[14];
+ USHORT Length = 0;
+ IEEE8021X_FRAME Ieee_8021x;
+ EAP_FRAME EapFrame;
+ UCHAR *pOutBuffer = NULL;
+ ULONG FrameLen = 0;
+ UCHAR regIdentity[] = "WFA-SimpleConfig-Registrar-1-0";
+ UCHAR enrIdentity[] = "WFA-SimpleConfig-Enrollee-1-0";
+ UCHAR CurOpMode = 0xff;
+
+ NdisZeroMemory(Header802_3,sizeof(UCHAR)*14);
+
+ /* 1. Send EAP-Rsp Id */
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendEapRspId\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ MAKE_802_3_HEADER(Header802_3,
+ &pEntry->Addr[0],
+ &pAdapter->ApCfg.ApCliTab[0].CurrentAddress[0],
+ EAPOL);
+ Length = sizeof(EAP_FRAME) + sizeof(enrIdentity) - 1;
+ pWscControl->WscConfMode = WSC_ENROLLEE; /* Ap Client only support Enrollee now. 20070518 */
+ }
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /* Zero 802.1x body */
+ NdisZeroMemory(&Ieee_8021x, sizeof(Ieee_8021x));
+ Ieee_8021x.Version = EAPOL_VER;
+ Ieee_8021x.Type = EAPPacket;
+ Ieee_8021x.Length = cpu2be16(Length);
+
+ /* Zero EAP frame */
+ NdisZeroMemory(&EapFrame, sizeof(EapFrame));
+ EapFrame.Code = EAP_CODE_RSP;
+ EapFrame.Id = pWscControl->lastId;
+ EapFrame.Length = cpu2be16(Length);
+ EapFrame.Type = EAP_TYPE_ID;
+
+ /* Out buffer for transmitting EAP-Req(Identity) */
+/* pOutBuffer = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER);
+ if(pOutBuffer == NULL)
+ return;
+
+ FrameLen = 0;
+
+ if (pWscControl->WscConfMode == WSC_REGISTRAR)
+ {
+ /* Make Transmitting frame */
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(IEEE8021X_FRAME), &Ieee_8021x,
+ sizeof(EapFrame), &EapFrame,
+ (sizeof(regIdentity) - 1), regIdentity,
+ END_OF_ARGS);
+ }
+ else if (pWscControl->WscConfMode == WSC_ENROLLEE)
+ {
+ /* Make Transmitting frame */
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(IEEE8021X_FRAME), &Ieee_8021x,
+ sizeof(EapFrame), &EapFrame,
+ (sizeof(enrIdentity) - 1), enrIdentity,
+ END_OF_ARGS);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscConfMode(%d) is not WSC_REGISTRAR nor WSC_ENROLLEE.\n", pWscControl->WscConfMode));
+ goto out;
+ }
+
+ /* Copy frame to Tx ring */
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ RTMPToWirelessSta(pAdapter, pEntry, Header802_3, sizeof(Header802_3), (PUCHAR)pOutBuffer, FrameLen, TRUE);
+ }
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ pWscControl->WscRetryCount = 0;
+ if (!pWscControl->EapolTimerRunning)
+ {
+ pWscControl->EapolTimerRunning = TRUE;
+ RTMPSetTimer(&pWscControl->EapolTimer, WSC_EAP_ID_TIME_OUT);
+ }
+out:
+ if (pOutBuffer)
+/* kfree(pOutBuffer); */
+ os_free_mem(NULL, pOutBuffer);
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendEapRspId\n"));
+}
+
+VOID WscUPnPErrHandle(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWscControl,
+ IN UINT eventID)
+{
+ int dataLen;
+ UCHAR *pWscData;
+ UCHAR CurOpMode;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Into WscUPnPErrHandle, send WSC_OPCODE_UPNP_CTRL with eventID=0x%x!\n", eventID));
+
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ CurOpMode = AP_MODE;
+#endif // CONFIG_AP_SUPPORT //
+
+
+ os_alloc_mem(NULL, (UCHAR **)&pWscData, WSC_MAX_DATA_LEN);
+ if (pWscData != NULL)
+ {
+ NdisZeroMemory(pWscData, WSC_MAX_DATA_LEN);
+
+ dataLen = BuildMessageNACK(pAd, pWscControl, pWscData);
+ WscSendUPnPMessage(pAd, (pWscControl->EntryIfIdx & 0x0F),
+ WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_NORMAL,
+ pWscData, dataLen, eventID, 0, NULL, CurOpMode);
+
+ os_free_mem(NULL, pWscData);
+ }
+ else
+ {
+ WscSendUPnPMessage(pAd, (pWscControl->EntryIfIdx & 0x0F),
+ WSC_OPCODE_UPNP_CTRL, 0, NULL, 0, eventID, 0, NULL, CurOpMode);
+ }
+}
+
+/*
+ Format of iwcustom msg WSC clientJoin message:
+ 1. SSID which station want to probe(32 bytes):
+ <SSID string>
+ *If the length if SSID string is small than 32 bytes, fill 0x0 for remaining bytes.
+ 2. sender MAC address(6 bytes):
+ 3. Status:
+ Set as 1 means change APStatus as 1.
+ Set as 2 means change STAStatus as 1.
+ Set as 3 means trigger msg.
+
+ 32 6 1
+ +----------+--------+------+
+ |SSIDString| SrcMAC |Status|
+*/
+int WscSendUPnPConfReqMsg(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR apIdx,
+ IN PUCHAR ssidStr,
+ IN PUCHAR macAddr,
+ IN INT Status,
+ IN UINT eventID,
+ IN UCHAR CurOpMode)
+{
+ UCHAR pData[39] = {0};
+
+
+ strncpy((PSTRING) pData, (PSTRING)ssidStr, strlen((PSTRING) ssidStr));
+ NdisMoveMemory(&pData[32], macAddr, MAC_ADDR_LEN);
+ pData[38] = Status;
+ WscSendUPnPMessage(pAd, apIdx, WSC_OPCODE_UPNP_MGMT, WSC_UPNP_MGMT_SUB_CONFIG_REQ,
+ &pData[0], 39, eventID, 0, NULL, CurOpMode);
+
+ return 0;
+}
+
+
+/*
+ NETLINK tunnel msg format send to WSCUPnP handler in user space:
+ 1. Signature of following string(Not include the quote, 8 bytes)
+ "RAWSCMSG"
+ 2. eID: eventID (4 bytes)
+ the ID of this message(4 bytes)
+ 3. aID: ackID (4 bytes)
+ means that which event ID this mesage was response to.
+ 4. TL: Message Total Length (4 bytes)
+ Total length of this message.
+ 5. F: Flag (2 bytes)
+ used to notify some specific character of this msg segment.
+ Bit 1: fragment
+ set as 1 if netlink layer have more segment of this Msg need to send.
+ Bit 2~15: reserve, should set as 0 now.
+ 5. SL: Segment Length(2 bytes)
+ msg actual length in this segment, The SL may not equal the "TL" field if "F" ==1
+ 6. devMac: device mac address(6 bytes)
+ Indicate the netdevice which this msg belong. For the wscd in user space will
+ depends this address dispatch the msg to correct UPnP Device instance to handle it.
+ 7. "WSC_MSG" info:
+
+ 8 4 4 4 2 2 6 variable length(MAXIMUM=232)
+ +------------+----+----+----+--+--+------+------------------------+
+ | Signature |eID |aID | TL | F | SL|devMac| WSC_MSG |
+
+*/
+int WscSendUPnPMessage(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR devIfIdx,
+ IN USHORT msgType,
+ IN USHORT msgSubType,
+ IN PUCHAR pData,
+ IN INT dataLen,
+ IN UINT eventID,
+ IN UINT toIPAddr,
+ IN PUCHAR pMACAddr,
+ IN UCHAR CurOpMode)
+{
+/* union iwreq_data wrqu; */
+ RTMP_WSC_NLMSG_HDR *pNLMsgHdr;
+ RTMP_WSC_MSG_HDR *pWscMsgHdr;
+
+ UCHAR hdrBuf[42]; /*RTMP_WSC_NLMSG_HDR_LEN + RTMP_WSC_MSG_HDR_LEN */
+ int totalLen, leftLen, copyLen;
+ PUCHAR pBuf = NULL, pBufPtr = NULL, pPos = NULL;
+ PUCHAR pDevAddr = NULL;
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR bssIdx = devIfIdx;
+#endif /* CONFIG_AP_SUPPORT */
+ ULONG Now;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendUPnPMessage\n"));
+
+ if ((msgType & WSC_OPCODE_UPNP_MASK) != WSC_OPCODE_UPNP_MASK)
+ return FALSE;
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+#ifdef APCLI_SUPPORT
+ if (devIfIdx & MIN_NET_DEVICE_FOR_APCLI)
+ {
+ bssIdx &= (~MIN_NET_DEVICE_FOR_APCLI);
+ if (bssIdx >= MAX_APCLI_NUM)
+ return FALSE;
+ pDevAddr = &pAd->ApCfg.ApCliTab[bssIdx].CurrentAddress[0];
+ }
+ else
+#endif /* APCLI_SUPPORT */
+ pDevAddr = &pAd->ApCfg.MBSSID[bssIdx].Bssid[0];
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pDevAddr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("pDevAddr == NULL!\n"));
+ return FALSE;
+ }
+
+ /*Prepare the NLMsg header */
+ memset(hdrBuf, 0, sizeof(hdrBuf));
+ pNLMsgHdr = (RTMP_WSC_NLMSG_HDR *)hdrBuf;
+ memcpy(pNLMsgHdr, WSC_MSG_SIGNATURE, RTMP_WSC_NLMSG_SIGNATURE_LEN);
+
+ NdisGetSystemUpTime(&Now);
+ pNLMsgHdr->envID = Now;
+ pNLMsgHdr->ackID = eventID;
+ pNLMsgHdr->msgLen = dataLen + RTMP_WSC_MSG_HDR_LEN;
+
+ /*
+ In order to support multiple wscd, we need this new field to notify
+ the wscd which interface this msg send from.
+ */
+ NdisMoveMemory(&pNLMsgHdr->devAddr[0], pDevAddr, MAC_ADDR_LEN);
+
+ /*Prepare the WscMsg header */
+ pWscMsgHdr = (RTMP_WSC_MSG_HDR *)(hdrBuf + sizeof(RTMP_WSC_NLMSG_HDR));
+ switch(msgType)
+ {
+ case WSC_OPCODE_UPNP_DATA:
+ pWscMsgHdr->msgType = WSC_OPCODE_UPNP_DATA;
+ break;
+ case WSC_OPCODE_UPNP_MGMT:
+ pWscMsgHdr->msgType = WSC_OPCODE_UPNP_MGMT;
+ break;
+ case WSC_OPCODE_UPNP_CTRL:
+ pWscMsgHdr->msgType = WSC_OPCODE_UPNP_CTRL;
+ break;
+ default:
+ return FALSE;
+ }
+ pWscMsgHdr->msgSubType = msgSubType;
+ pWscMsgHdr->ipAddr = toIPAddr;
+ pWscMsgHdr->msgLen = dataLen;
+
+ if ((pWscMsgHdr->msgType == WSC_OPCODE_UPNP_DATA) &&
+ (eventID == 0) &&
+ (pMACAddr != NULL) &&
+ (NdisEqualMemory(pMACAddr, ZERO_MAC_ADDR, MAC_ADDR_LEN) == FALSE))
+ {
+ pWscMsgHdr->msgSubType |= WSC_UPNP_DATA_SUB_INCLUDE_MAC;
+ pNLMsgHdr->msgLen += MAC_ADDR_LEN;
+ pWscMsgHdr->msgLen += MAC_ADDR_LEN;
+ }
+
+ /*Allocate memory and copy the msg. */
+ totalLen = leftLen = pNLMsgHdr->msgLen;
+ pPos = pData;
+ os_alloc_mem(NULL, (UCHAR **)&pBuf, IWEVCUSTOM_MSG_MAX_LEN);
+/* if((pBuf = kmalloc(IWEVCUSTOM_MSG_MAX_LEN, GFP_ATOMIC)) != NULL) */
+ if (pBuf != NULL)
+ {
+ int firstSeg = 1;
+
+ while(leftLen)
+ {
+ /*Prepare the payload */
+ memset(pBuf, 0, IWEVCUSTOM_MSG_MAX_LEN);
+
+ pNLMsgHdr->segLen = (leftLen > IWEVCUSTOM_PAYLOD_MAX_LEN ? IWEVCUSTOM_PAYLOD_MAX_LEN : leftLen);
+ leftLen -= pNLMsgHdr->segLen;
+ pNLMsgHdr->flags = (leftLen > 0 ? 1 : 0);
+
+ memcpy(pBuf, pNLMsgHdr, RTMP_WSC_NLMSG_HDR_LEN);
+ pBufPtr = &pBuf[RTMP_WSC_NLMSG_HDR_LEN];
+
+ if(firstSeg){
+ memcpy(pBufPtr, pWscMsgHdr, RTMP_WSC_MSG_HDR_LEN);
+ pBufPtr += RTMP_WSC_MSG_HDR_LEN;
+ copyLen = (pNLMsgHdr->segLen - RTMP_WSC_MSG_HDR_LEN);
+ if ((pWscMsgHdr->msgSubType & WSC_UPNP_DATA_SUB_INCLUDE_MAC) == WSC_UPNP_DATA_SUB_INCLUDE_MAC)
+ {
+ NdisMoveMemory(pBufPtr, pMACAddr, MAC_ADDR_LEN);
+ pBufPtr += MAC_ADDR_LEN;
+ copyLen -= MAC_ADDR_LEN;
+ }
+ NdisMoveMemory(pBufPtr, pPos, copyLen);
+ pPos += copyLen;
+ firstSeg = 0;
+ } else {
+ NdisMoveMemory(pBufPtr, pPos, pNLMsgHdr->segLen);
+ pPos += pNLMsgHdr->segLen;
+ }
+
+ /*Send WSC Msg to wscd, msg length = pNLMsgHdr->segLen + sizeof(RTMP_WSC_NLMSG_HDR) */
+ RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_WSC_UPNP_EVENT_FLAG, NULL, pBuf, pNLMsgHdr->segLen + sizeof(RTMP_WSC_NLMSG_HDR));
+ }
+
+/* kfree(pBuf); */
+ os_free_mem(NULL, pBuf);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendUPnPMessage\n"));
+ return TRUE;
+}
+
+
+VOID WscSendMessage(
+ IN PRTMP_ADAPTER pAdapter,
+ IN UCHAR OpCode,
+ IN PUCHAR pData,
+ IN INT Len,
+ IN PWSC_CTRL pWscControl,
+ IN UCHAR OpMode,
+ IN UCHAR EapType)
+{
+ /* Inb-EAP Message */
+ UCHAR Header802_3[14];
+ USHORT Length, MsgLen;
+ IEEE8021X_FRAME Ieee_8021x;
+ EAP_FRAME EapFrame;
+ WSC_FRAME WscFrame;
+ UCHAR *pOutBuffer = NULL;
+ ULONG FrameLen = 0;
+ MAC_TABLE_ENTRY *pEntry;
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR bssIdx = (pWscControl->EntryIfIdx & 0x0F);
+#endif /* CONFIG_AP_SUPPORT */
+ UCHAR CurOpMode = 0xFF;
+
+ if ((Len <= 0) && (OpCode != WSC_OPCODE_START) && (OpCode != WSC_OPCODE_FRAG_ACK))
+ return;
+
+ /* Send message */
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendMessage\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+ NdisZeroMemory(Header802_3,sizeof(UCHAR)*14);
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (OpMode == AP_MODE)
+ {
+ MAKE_802_3_HEADER(Header802_3, &pWscControl->EntryAddr[0], &pAdapter->ApCfg.MBSSID[bssIdx].Bssid[0], EAPOL);
+ }
+#ifdef APCLI_SUPPORT
+ else if (OpMode == AP_CLIENT_MODE)
+ {
+ MAKE_802_3_HEADER(Header802_3, &pWscControl->EntryAddr[0], &pAdapter->ApCfg.ApCliTab[0].CurrentAddress[0], EAPOL);
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* Length = EAP + WSC_Frame + Payload */
+ Length = sizeof(EAP_FRAME) + sizeof(WSC_FRAME) + Len;
+
+ if (pWscControl->bWscFragment && (pWscControl->bWscFirstOne))
+ {
+ Length += 2;
+ MsgLen = pWscControl->WscTxBufLen + Len;
+ MsgLen = htons(MsgLen);
+ }
+
+ /* Zero 802.1x body */
+ NdisZeroMemory(&Ieee_8021x, sizeof(Ieee_8021x));
+ Ieee_8021x.Version = EAPOL_VER;
+ Ieee_8021x.Type = EAPPacket;
+ Ieee_8021x.Length = cpu2be16(Length);
+
+ /* Zero EAP frame */
+ NdisZeroMemory(&EapFrame, sizeof(EapFrame));
+
+ if (EapType == EAP_CODE_REQ)
+ {
+ EapFrame.Code = EAP_CODE_REQ;
+ EapFrame.Id = ++(pWscControl->lastId);
+ }
+ else
+ {
+ EapFrame.Code = EAP_CODE_RSP;
+ EapFrame.Id = pWscControl->lastId; /* same as eap_req id */
+ }
+
+ EapFrame.Length = cpu2be16(Length);
+ EapFrame.Type = EAP_TYPE_WSC;
+
+ /* Zero WSC Frame */
+ NdisZeroMemory(&WscFrame, sizeof(WscFrame));
+ WscFrame.SMI[0] = 0x00;
+ WscFrame.SMI[1] = 0x37;
+ WscFrame.SMI[2] = 0x2A;
+ WscFrame.VendorType = cpu2be32(WSC_VENDOR_TYPE);
+ WscFrame.OpCode = OpCode;
+ WscFrame.Flags = 0x00;
+ if (pWscControl->bWscFragment && (pWscControl->bWscLastOne == FALSE))
+ WscFrame.Flags |= WSC_MSG_FLAG_MF;
+
+ if (pWscControl->bWscFragment && (pWscControl->bWscFirstOne))
+ {
+ WscFrame.Flags |= WSC_MSG_FLAG_LF;
+ }
+
+ /* Out buffer for transmitting message */
+ os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER);
+ if(pOutBuffer == NULL)
+ return;
+
+ FrameLen = 0;
+
+ /* Make Transmitting frame */
+ if (pData && (Len > 0))
+ {
+ if (pWscControl->bWscFragment && (pWscControl->bWscFirstOne))
+ {
+ UCHAR LF_Len = 2;
+ ULONG TmpLen = 0;
+
+ pWscControl->bWscFirstOne = FALSE;
+ MakeOutgoingFrame(pOutBuffer, &TmpLen,
+ sizeof(IEEE8021X_FRAME), &Ieee_8021x,
+ sizeof(EapFrame), &EapFrame,
+ sizeof(WscFrame), &WscFrame,
+ LF_Len, &MsgLen,
+ END_OF_ARGS);
+
+ FrameLen += TmpLen;
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
+ Len, pData,
+ END_OF_ARGS);
+
+ FrameLen += TmpLen;
+ }
+ else
+ {
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(IEEE8021X_FRAME), &Ieee_8021x,
+ sizeof(EapFrame), &EapFrame,
+ sizeof(WscFrame), &WscFrame,
+ Len, pData,
+ END_OF_ARGS);
+ }
+ }
+ else
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(IEEE8021X_FRAME), &Ieee_8021x,
+ sizeof(EapFrame), &EapFrame,
+ sizeof(WscFrame), &WscFrame,
+ END_OF_ARGS);
+
+ /* Copy frame to Tx ring */
+ pEntry = MacTableLookup(pAdapter, &pWscControl->EntryAddr[0]);
+
+ if (pEntry)
+ RTMPToWirelessSta(pAdapter, pEntry, Header802_3, sizeof(Header802_3), (PUCHAR)pOutBuffer, FrameLen, TRUE);
+ else
+ DBGPRINT(RT_DEBUG_WARN, ("pEntry is NULL\n"));
+
+ if (pOutBuffer)
+ os_free_mem(NULL, pOutBuffer);
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendMessage\n"));
+}
+
+VOID WscBuildBeaconIE(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR b_configured,
+ IN BOOLEAN b_selRegistrar,
+ IN USHORT devPwdId,
+ IN USHORT selRegCfgMethods,
+ IN UCHAR apidx,
+ IN UCHAR *pAuthorizedMACs,
+ IN UCHAR AuthorizedMACsLen,
+ IN UCHAR CurOpMode)
+{
+ WSC_IE_HEADER ieHdr;
+/* UCHAR Data[256]; */
+ UCHAR *Data = NULL;
+ PUCHAR pData;
+ INT Len = 0, templen = 0;
+ USHORT tempVal = 0;
+ PWSC_CTRL pWpsCtrl = NULL;
+ PWSC_REG_DATA pReg = NULL;
+
+
+ /* allocate memory */
+ os_alloc_mem(NULL, (UCHAR **)&Data, 256);
+ if (Data == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ return;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ pWpsCtrl = &pAd->ApCfg.MBSSID[apidx & 0x0F].WscControl;
+#endif /* CONFIG_AP_SUPPORT */
+
+ pReg = &pWpsCtrl->RegData;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscBuildBeaconIE\n"));
+ /* WSC IE HEader */
+ ieHdr.elemId = 221;
+ ieHdr.length = 4;
+ ieHdr.oui[0] = 0x00; ieHdr.oui[1] = 0x50; ieHdr.oui[2] = 0xF2;
+ ieHdr.oui[3] = 0x04;
+
+ pData = (PUCHAR) &Data[0];
+ Len = 0;
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Simple Config State */
+ templen = AppendWSCTLV(WSC_ID_SC_STATE, pData, (UINT8 *)&b_configured, 0);
+ pData += templen;
+ Len += templen;
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef WSC_V2_SUPPORT
+ if ((CurOpMode == AP_MODE) && pWpsCtrl->bSetupLock)
+ {
+ // AP Setup Lock
+ templen = AppendWSCTLV(WSC_ID_AP_SETUP_LOCKED, pData, (UINT8 *)&pWpsCtrl->bSetupLock, 0);
+ pData += templen;
+ Len += templen;
+ }
+#endif /* WSC_V2_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ if ( b_selRegistrar )
+ {
+ /* 3.Selected Registrar */
+ templen = AppendWSCTLV(WSC_ID_SEL_REGISTRAR, pData, (UINT8 *)&b_selRegistrar, 0);
+ pData += templen;
+ Len += templen;
+
+ /*4. Device Password ID */
+ tempVal = htons(devPwdId);
+ templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&tempVal, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 5. Selected Registrar Config Methods */
+ tempVal = selRegCfgMethods;
+ tempVal = htons(tempVal);
+ templen = AppendWSCTLV(WSC_ID_SEL_REG_CFG_METHODS, pData, (UINT8 *)&tempVal, 0);
+ pData += templen;
+ Len += templen;
+ }
+
+ /* 6. UUID last 6 bytes use MAC */
+ templen = AppendWSCTLV(WSC_ID_UUID_E, pData, &pWpsCtrl->Wsc_Uuid_E[0], 0);
+ pData += templen;
+ Len += templen;
+
+ /* 7. RF Bands */
+ if (CurOpMode == AP_MODE)
+ {
+ if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode))
+ tempVal = 2;
+ else
+ tempVal = 1;
+ }
+ else
+ {
+ if (pAd->CommonCfg.Channel > 14)
+ tempVal = 2;
+ else
+ tempVal = 1;
+ }
+
+#ifdef RT_BIG_ENDIAN
+ tempVal =SWAP16(tempVal);
+#endif /* RT_BIG_ENDIAN */
+ templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&tempVal, 0);
+ pData += templen;
+ Len += templen;
+
+
+#ifdef WSC_V2_SUPPORT
+ if (pWpsCtrl->WscV2Info.bEnableWpsV2)
+ {
+ PWSC_TLV pWscTLV = &pWpsCtrl->WscV2Info.ExtraTlv;
+ WscGenV2Msg(pWpsCtrl,
+ b_selRegistrar,
+ pAuthorizedMACs,
+ AuthorizedMACsLen,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+
+
+ ieHdr.length = ieHdr.length + Len;
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ memcpy(pAd->ApCfg.MBSSID[apidx].WscIEBeacon.Value, &ieHdr, sizeof(WSC_IE_HEADER));
+ memcpy(pAd->ApCfg.MBSSID[apidx].WscIEBeacon.Value + sizeof(WSC_IE_HEADER), Data, Len);
+ pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen = sizeof(WSC_IE_HEADER) + Len;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ if (Data != NULL)
+ os_free_mem(NULL, Data);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscBuildBeaconIE\n"));
+}
+
+VOID WscBuildProbeRespIE(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR respType,
+ IN UCHAR scState,
+ IN BOOLEAN b_selRegistrar,
+ IN USHORT devPwdId,
+ IN USHORT selRegCfgMethods,
+ IN UCHAR apidx,
+ IN UCHAR *pAuthorizedMACs,
+ IN INT AuthorizedMACsLen,
+ IN UCHAR CurOpMode)
+{
+ WSC_IE_HEADER ieHdr;
+/* UCHAR Data[512]; */
+ UCHAR *Data = NULL;
+ PUCHAR pData;
+ INT Len = 0, templen = 0;
+ USHORT tempVal = 0;
+ PWSC_CTRL pWpsCtrl = NULL;
+ PWSC_REG_DATA pReg = NULL;
+
+
+ /* allocate memory */
+ os_alloc_mem(NULL, (UCHAR **)&Data, 512);
+ if (Data == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ return;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ pWpsCtrl = &pAd->ApCfg.MBSSID[apidx & 0x0F].WscControl;
+#endif /* CONFIG_AP_SUPPORT */
+
+ pReg = &pWpsCtrl->RegData;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscBuildProbeRespIE, apidx = %x\n", apidx));
+
+ /* WSC IE Header */
+ ieHdr.elemId = 221;
+ ieHdr.length = 4;
+ ieHdr.oui[0] = 0x00; ieHdr.oui[1] = 0x50; ieHdr.oui[2] = 0xF2;
+ ieHdr.oui[3] = 0x04;
+
+ pData = (PUCHAR) &Data[0];
+ Len = 0;
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Simple Config State */
+ templen = AppendWSCTLV(WSC_ID_SC_STATE, pData, (UINT8 *)&scState, 0);
+ pData += templen;
+ Len += templen;
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef WSC_V2_SUPPORT
+ if ((CurOpMode == AP_MODE) && pWpsCtrl->bSetupLock)
+ {
+ // AP Setup Lock
+ templen = AppendWSCTLV(WSC_ID_AP_SETUP_LOCKED, pData, (UINT8 *)&pWpsCtrl->bSetupLock, 0);
+ pData += templen;
+ Len += templen;
+ }
+#endif /* WSC_V2_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ if ( b_selRegistrar )
+ {
+ /* 3. Selected Registrar */
+ templen = AppendWSCTLV(WSC_ID_SEL_REGISTRAR, pData, (UINT8 *)&b_selRegistrar, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 4. Device Password ID */
+ tempVal = htons(devPwdId);
+ templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&tempVal, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 5. Selected Registrar Config Methods */
+ tempVal = htons(selRegCfgMethods);
+ templen = AppendWSCTLV(WSC_ID_SEL_REG_CFG_METHODS, pData, (UINT8 *)&tempVal, 0);
+ pData += templen;
+ Len += templen;
+
+ }
+
+ /* 6. Response Type WSC_ID_RESP_TYPE */
+ templen = AppendWSCTLV(WSC_ID_RESP_TYPE, pData, (UINT8 *)&respType, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 7. UUID last 6 bytes use MAC */
+ templen = AppendWSCTLV(WSC_ID_UUID_E, pData, &pWpsCtrl->Wsc_Uuid_E[0], 0);
+ pData += templen;
+ Len += templen;
+
+ /* 8. Manufacturer */
+ NdisZeroMemory(pData, 64 + 4);
+ templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((PSTRING) pReg->SelfInfo.Manufacturer));
+ pData += templen;
+ Len += templen;
+
+ /* 9. Model Name */
+ NdisZeroMemory(pData, 32 + 4);
+ templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((PSTRING) pReg->SelfInfo.ModelName));
+ pData += templen;
+ Len += templen;
+
+ /* 10. Model Number */
+ NdisZeroMemory(pData, 32 + 4);
+ templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((PSTRING) pReg->SelfInfo.ModelNumber));
+ pData += templen;
+ Len += templen;
+
+ /* 11. Serial Number */
+ NdisZeroMemory(pData, 32 + 4);
+ templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((PSTRING) pReg->SelfInfo.SerialNumber));
+ pData += templen;
+ Len += templen;
+
+ /* 12. Primary Device Type */
+ templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 13. Device Name */
+ NdisZeroMemory(pData, 32 + 4);
+ templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((PSTRING) pReg->SelfInfo.DeviceName));
+ pData += templen;
+ Len += templen;
+
+ /* 14. Config Methods */
+ /*tempVal = htons(0x008a); */
+ /*tempVal = htons(0x0084); */
+ {
+ /*
+ WSC 1.0 WCN logo testing will check the value of config method in probe response and M1.
+ Config method shall be identical in probe response and M1.
+ */
+#ifdef WSC_V2_SUPPORT
+ if (pWpsCtrl->WscV2Info.bEnableWpsV2)
+ tempVal = pWpsCtrl->WscConfigMethods & 0xF97F;
+ else
+#endif /* WSC_V2_SUPPORT */
+ tempVal = pWpsCtrl->WscConfigMethods & 0x00FF;
+ }
+
+ tempVal = htons(tempVal);
+ templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&tempVal, 0);
+ pData += templen;
+ Len += templen;
+
+
+ /* 15. RF Bands */
+ if (CurOpMode == AP_MODE)
+ {
+ if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode))
+ tempVal = 2;
+ else
+ tempVal = 1;
+ }
+ else
+ {
+ if (pAd->CommonCfg.Channel > 14)
+ tempVal = 2;
+ else
+ tempVal = 1;
+ }
+#ifdef RT_BIG_ENDIAN
+ tempVal =SWAP16(tempVal);
+#endif /* RT_BIG_ENDIAN */
+ templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&tempVal, 0);
+ pData += templen;
+ Len += templen;
+
+
+#ifdef WSC_V2_SUPPORT
+ if (pWpsCtrl->WscV2Info.bEnableWpsV2)
+ {
+ PWSC_TLV pWscTLV = &pWpsCtrl->WscV2Info.ExtraTlv;
+ WscGenV2Msg(pWpsCtrl,
+ b_selRegistrar,
+ pAuthorizedMACs,
+ AuthorizedMACsLen,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+
+ if (Len > 251)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Len is overflow!\n"));
+ }
+
+ ieHdr.length = ieHdr.length + Len;
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ memcpy(pAd->ApCfg.MBSSID[apidx & 0xF].WscIEProbeResp.Value, &ieHdr, sizeof(WSC_IE_HEADER));
+ memcpy(pAd->ApCfg.MBSSID[apidx & 0xF].WscIEProbeResp.Value + sizeof(WSC_IE_HEADER), Data, Len);
+ pAd->ApCfg.MBSSID[apidx & 0xF].WscIEProbeResp.ValueLen = sizeof(WSC_IE_HEADER) + Len;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ if (Data != NULL)
+ os_free_mem(NULL, Data);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscBuildProbeRespIE\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Ap send EAP-Fail to station
+
+ Arguments:
+ pAd - NIC Adapter pointer
+ Id - ID between EAP-Req and EAP-Rsp pair
+ pEntry - The Station Entry information
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID WscSendEapFail(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWscControl,
+ IN BOOLEAN bSendDeAuth)
+{
+ UCHAR Header802_3[14];
+ USHORT Length;
+ IEEE8021X_FRAME Ieee_8021x;
+ EAP_FRAME EapFrame;
+ UCHAR *pOutBuffer = NULL;
+ ULONG FrameLen = 0;
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR apidx = (pWscControl->EntryIfIdx & 0x0F);
+#endif /* CONFIG_AP_SUPPORT */
+ MAC_TABLE_ENTRY *pEntry;
+ UCHAR CurOpMode = 0xFF;
+
+ NdisZeroMemory(Header802_3,sizeof(UCHAR)*14);
+
+ /* 1. Send EAP-Rsp Id */
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendEapFail\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ MAKE_802_3_HEADER(Header802_3,
+ &pWscControl->EntryAddr[0],
+ &pAd->ApCfg.MBSSID[apidx].Bssid[0],
+ EAPOL);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /* Length, -1 type size, Eap-Fail doesn't need Type item */
+ Length = sizeof(EAP_FRAME) - sizeof(UCHAR);
+
+ /* Zero 802.1x body */
+ NdisZeroMemory(&Ieee_8021x, sizeof(Ieee_8021x));
+ Ieee_8021x.Version = EAPOL_VER;
+ Ieee_8021x.Type = EAPPacket;
+ Ieee_8021x.Length = cpu2be16(Length);
+
+ /* Zero EAP frame */
+ NdisZeroMemory(&EapFrame, sizeof(EapFrame));
+ EapFrame.Code = EAP_CODE_FAIL;
+ EapFrame.Id = pWscControl->lastId;
+ EapFrame.Length = cpu2be16(Length);
+
+ /* Out buffer for transmitting EAP-Req(Identity) */
+/* pOutBuffer = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER);
+ if(pOutBuffer == NULL)
+ return;
+
+ FrameLen = 0;
+
+ /* Make Transmitting frame */
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(IEEE8021X_FRAME), &Ieee_8021x,
+ sizeof(EapFrame)-1, &EapFrame, END_OF_ARGS);
+
+ pEntry = MacTableLookup(pAd, &pWscControl->EntryAddr[0]);
+ /* Copy frame to Tx ring */
+ RTMPToWirelessSta(pAd, pEntry, Header802_3, sizeof(Header802_3), (PUCHAR)pOutBuffer, FrameLen, TRUE);
+
+
+ if (pOutBuffer)
+/* kfree(pOutBuffer); */
+ os_free_mem(NULL, pOutBuffer);
+
+#ifdef CONFIG_AP_SUPPORT
+ if (pEntry && bSendDeAuth && (CurOpMode == AP_MODE))
+ {
+ MlmeDeAuthAction(pAd, pEntry, REASON_DEAUTH_STA_LEAVING, TRUE);
+ }
+ if (pEntry == NULL)
+ {
+ /*
+ If STA dis-connect un-normally, reset EntryAddr here.
+ */
+ NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendEapFail\n"));
+}
+
+#ifdef CONFIG_AP_SUPPORT
+VOID WscBuildAssocRespIE(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR ApIdx,
+ IN UCHAR Reason,
+ OUT PUCHAR pOutBuf,
+ OUT PUCHAR pIeLen)
+{
+ WSC_IE_HEADER ieHdr;
+/* UCHAR Data[512] = {0}; */
+ UCHAR *Data = NULL;
+ PUCHAR pData;
+ INT Len = 0, templen = 0;
+ UINT8 tempVal = 0;
+ PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pAd->ApCfg.MBSSID[ApIdx].WscControl.RegData;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscBuildAssocRespIE\n"));
+
+ /* allocate memory */
+ os_alloc_mem(NULL, (UCHAR **)&Data, 512);
+ if (Data == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ return;
+ }
+ Data[0] = 0;
+
+ /* WSC IE Header */
+ ieHdr.elemId = 221;
+ ieHdr.length = 4;
+ ieHdr.oui[0] = 0x00; ieHdr.oui[1] = 0x50;
+ ieHdr.oui[2] = 0xF2; ieHdr.oui[3] = 0x04;
+
+ pData = (PUCHAR) &Data[0];
+ Len = 0;
+
+ /* Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Request Type */
+ tempVal = WSC_MSGTYPE_AP_WLAN_MGR;
+ templen = AppendWSCTLV(WSC_ID_RESP_TYPE, pData, (UINT8 *)&tempVal, 0);
+ pData += templen;
+ Len += templen;
+
+#ifdef WSC_V2_SUPPORT
+ if (pAd->ApCfg.MBSSID[ApIdx].WscControl.WscV2Info.bEnableWpsV2)
+ {
+ WscGenV2Msg(&pAd->ApCfg.MBSSID[ApIdx].WscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+ }
+#endif /* WSC_V2_SUPPORT */
+
+
+ ieHdr.length = ieHdr.length + Len;
+ NdisMoveMemory(pOutBuf, &ieHdr, sizeof(WSC_IE_HEADER));
+ NdisMoveMemory(pOutBuf + sizeof(WSC_IE_HEADER), Data, Len);
+ *pIeLen = sizeof(WSC_IE_HEADER) + Len;
+
+ if (Data != NULL)
+ os_free_mem(NULL, Data);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscBuildAssocRespIE\n"));
+}
+
+
+VOID WscSelectedRegistrar(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pReginfo,
+ IN UINT Length,
+ IN UCHAR apidx)
+{
+ PUCHAR pData;
+ INT IsAPConfigured;
+ UCHAR wsc_version, wsc_sel_reg = 0;
+ USHORT wsc_dev_pass_id = 0, wsc_sel_reg_conf_mthd = 0;
+ USHORT WscType, WscLen;
+ PUCHAR pAuthorizedMACs = NULL;
+ UCHAR AuthorizedMACsLen = 0;
+ PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl;
+
+ pData = (PUCHAR)pReginfo;
+
+ if (Length < 4)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscSelectedRegistrar --> Unknown IE \n"));
+ return;
+ }
+
+ hex_dump("WscSelectedRegistrar - Reginfo", pReginfo, Length);
+ while (Length > 4)
+ {
+ /* arm-cpu has packet alignment issue, it's better to use memcpy to retrieve data */
+ NdisMoveMemory(&WscType, pData, 2);
+ NdisMoveMemory(&WscLen, pData + 2, 2);
+ WscLen = ntohs(WscLen);
+ pData += 4;
+ Length -= 4;
+ switch (ntohs(WscType))
+ {
+ case WSC_ID_VERSION:
+ wsc_version = *pData;
+ break;
+
+ case WSC_ID_SEL_REGISTRAR:
+ wsc_sel_reg = *pData;
+ break;
+
+ case WSC_ID_DEVICE_PWD_ID:
+ NdisMoveMemory(&wsc_dev_pass_id, pData, sizeof(USHORT));
+ wsc_dev_pass_id = be2cpu16(wsc_dev_pass_id);
+ break;
+
+ case WSC_ID_SEL_REG_CFG_METHODS:
+ NdisMoveMemory(&wsc_sel_reg_conf_mthd, pData, sizeof(USHORT));
+ wsc_sel_reg_conf_mthd = be2cpu16(wsc_sel_reg_conf_mthd);
+ break;
+
+ case WSC_ID_VENDOR_EXT:
+#ifdef WSC_V2_SUPPORT
+ if (pWscCtrl->WscV2Info.bEnableWpsV2 && (WscLen > 0))
+ {
+ /*
+ Find WFA_EXT_ID_AUTHORIZEDMACS
+ */
+ os_alloc_mem(NULL, &pAuthorizedMACs, WscLen);
+ if (pAuthorizedMACs)
+ {
+ NdisZeroMemory(pAuthorizedMACs, WscLen);
+ WscParseV2SubItem(WFA_EXT_ID_AUTHORIZEDMACS, pData, WscLen, pAuthorizedMACs, &AuthorizedMACsLen);
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscSelectedRegistrar --> Unknown IE 0x%04x\n", WscType));
+ break;
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ Length -= WscLen;
+ }
+
+ IsAPConfigured = pWscCtrl->WscConfStatus;
+
+ if (wsc_sel_reg == 0x01)
+ {
+ pWscCtrl->WscSelReg = 1;
+ WscBuildBeaconIE(pAd, WSC_SCSTATE_CONFIGURED, TRUE, wsc_dev_pass_id, wsc_sel_reg_conf_mthd, apidx, pAuthorizedMACs, AuthorizedMACsLen, AP_MODE);
+ WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, TRUE, wsc_dev_pass_id, wsc_sel_reg_conf_mthd, pWscCtrl->EntryIfIdx, pAuthorizedMACs, AuthorizedMACsLen, AP_MODE);
+#ifdef WSC_V2_SUPPORT
+ hex_dump("WscSelectedRegistrar - AuthorizedMACs::", pAuthorizedMACs, AuthorizedMACsLen);
+ if ((AuthorizedMACsLen == 6) &&
+ (NdisEqualMemory(pAuthorizedMACs, BROADCAST_ADDR, MAC_ADDR_LEN) == FALSE) &&
+ (NdisEqualMemory(pAuthorizedMACs, ZERO_MAC_ADDR, MAC_ADDR_LEN) == FALSE) &&
+ (pWscCtrl->WscState <= WSC_STATE_WAIT_M3))
+ {
+ PWSC_PEER_ENTRY pWscPeer = NULL;
+ NdisMoveMemory(pWscCtrl->EntryAddr, pAuthorizedMACs, MAC_ADDR_LEN);
+ RTMP_SEM_LOCK(&pWscCtrl->WscPeerListSemLock);
+ WscClearPeerList(&pWscCtrl->WscPeerList);
+ os_alloc_mem(pAd, (UCHAR **)&pWscPeer, sizeof(WSC_PEER_ENTRY));
+ if (pWscPeer)
+ {
+ NdisZeroMemory(pWscPeer, sizeof(WSC_PEER_ENTRY));
+ NdisMoveMemory(pWscPeer->mac_addr, pAuthorizedMACs, MAC_ADDR_LEN);
+ NdisGetSystemUpTime(&pWscPeer->receive_time);
+ insertTailList(&pWscCtrl->WscPeerList,
+ (PLIST_ENTRY)pWscPeer);
+ DBGPRINT(RT_DEBUG_TRACE, ("WscSelectedRegistrar --> Add this MAC to WscPeerList\n"));
+ }
+ ASSERT(pWscPeer != NULL);
+ RTMP_SEM_UNLOCK(&pWscCtrl->WscPeerListSemLock);
+ }
+#endif /* WSC_V2_SUPPORT */
+ }
+ else
+ {
+ pWscCtrl->WscSelReg = 0;
+ WscBuildBeaconIE(pAd, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, apidx, NULL, 0, AP_MODE);
+ WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, pWscCtrl->EntryIfIdx, NULL, 0, AP_MODE);
+ }
+ APUpdateBeaconFrame(pAd, apidx);
+
+#ifdef WSC_V2_SUPPORT
+ if (pAuthorizedMACs)
+ os_free_mem(NULL, pAuthorizedMACs);
+#endif /* WSC_V2_SUPPORT */
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+
+VOID WscProfileRetryTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAdapter = NULL;
+ PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext;
+ BOOLEAN bReConnect = TRUE;
+ UCHAR CurOpMode = 0xFF;
+
+ if (pWscControl == NULL)
+ return;
+
+ pAdapter = pWscControl->pAd;
+
+ if (pAdapter != NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscProfileRetryTimeout:: WSC profile retry timeout index: %d\n", pWscControl->WscProfile.ApplyProfileIdx));
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ CurOpMode = AP_MODE;
+
+#ifdef APCLI_SUPPORT
+ if( (CurOpMode == AP_MODE)
+ && (pAdapter->ApCfg.ApCliTab[BSS0].CtrlCurrState == APCLI_CTRL_CONNECTED)
+ && (pAdapter->ApCfg.ApCliTab[BSS0].SsidLen != 0))
+ {
+ INT i;
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ PMAC_TABLE_ENTRY pEntry = &pAdapter->MacTab.Content[i];
+
+ if ( IS_ENTRY_APCLI(pEntry) &&
+ (pEntry->Sst == SST_ASSOC) &&
+ (pEntry->PortSecured == WPA_802_1X_PORT_SECURED))
+ {
+ bReConnect = FALSE;
+ }
+ }
+ }
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+ if ((CurOpMode == STA_MODE) && INFRA_ON(pAdapter) && (pAdapter->IndicateMediaState == NdisMediaStateConnected))
+ {
+ pWscControl->WscProfileRetryTimerRunning = FALSE;
+ bReConnect = FALSE;
+ }
+
+ if (bReConnect)
+ {
+ if (pWscControl->WscProfile.ApplyProfileIdx < pWscControl->WscProfile.ProfileCnt-1)
+ pWscControl->WscProfile.ApplyProfileIdx++;
+ else
+ pWscControl->WscProfile.ApplyProfileIdx = 0;
+
+#ifdef APCLI_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ BOOLEAN apcliEn;
+ WscWriteConfToApCliCfg(pAdapter,
+ pWscControl,
+ &pWscControl->WscProfile.Profile[pWscControl->WscProfile.ApplyProfileIdx],
+ TRUE);
+
+ apcliEn = pAdapter->ApCfg.ApCliTab[BSS0].Enable;
+
+ /* bring apcli interface down first */
+ if(apcliEn == TRUE )
+ {
+ pAdapter->ApCfg.ApCliTab[BSS0].Enable = FALSE;
+ ApCliIfDown(pAdapter);
+ pAdapter->ApCfg.ApCliTab[BSS0].Enable = TRUE;
+ }
+ }
+#endif /* APCLI_SUPPORT */
+
+
+ pAdapter->WriteWscCfgToDatFile = (pWscControl->EntryIfIdx & 0x0F);
+/*#ifdef KTHREAD_SUPPORT */
+/* WAKE_UP(&(pAdapter->wscTask)); */
+/*#else */
+/* RTMP_SEM_EVENT_UP(&(pAdapter->wscTask.taskSema)); */
+/*#endif */
+ RtmpOsTaskWakeUp(&(pAdapter->wscTask));
+ DBGPRINT(RT_DEBUG_TRACE, ("WscProfileRetryTimeout:: WSC profile retry index: %d\n", pWscControl->WscProfile.ApplyProfileIdx));
+ }
+ }
+}
+
+VOID WscPBCTimeOutAction(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext;
+ RTMP_ADAPTER *pAd = NULL;
+ BOOLEAN Cancelled;
+
+ DBGPRINT(RT_DEBUG_OFF, ("-----> WscPBCTimeOutAction\n"));
+
+ if (pWscControl != NULL)
+ pAd = pWscControl->pAd;
+
+ if (pAd != NULL)
+ {
+
+ if (pWscControl->WscPBCTimerRunning)
+ {
+ pWscControl->WscPBCTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->WscPBCTimer, &Cancelled);
+ }
+
+ WscPBCExec(pAd, FALSE, pWscControl);
+
+ /* call Mlme handler to execute it */
+ RTMP_MLME_HANDLER(pAd);
+ }
+ DBGPRINT(RT_DEBUG_OFF, ("<----- WscPBCTimeOutAction\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Exec scan after scan timer expiration
+
+ Arguments:
+ FunctionContext NIC Adapter pointer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID WscScanTimeOutAction(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = NULL;
+ PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext;
+
+ if (pWscControl == NULL)
+ return;
+
+ pAd = pWscControl->pAd;
+
+ if (pAd != NULL)
+ {
+ /* call to execute the scan actions */
+ WscScanExec(pAd, pWscControl);
+
+ /* register 10 second timer for PBC or PIN connection execution */
+ if (pWscControl->WscMode == WSC_PBC_MODE)
+ {
+ /* Prevent infinite loop if conncet time out didn't stop the repeat scan */
+ if (pWscControl->WscState != WSC_STATE_OFF)
+ {
+ RTMPSetTimer(&pWscControl->WscPBCTimer, 10000);
+ pWscControl->WscPBCTimerRunning = TRUE;
+ }
+ }
+ else if (pWscControl->WscMode == WSC_PIN_MODE)
+ {
+ /* Prevent infinite loop if conncet time out didn't stop the repeat scan */
+ }
+
+ DBGPRINT(RT_DEBUG_OFF, ("!!! WscScanTimeOutAction !!!\n"));
+
+ /* call Mlme handler to execute it */
+ RTMP_MLME_HANDLER(pAd);
+ }
+}
+
+BOOLEAN ValidateChecksum(
+ IN UINT PIN)
+{
+ UINT accum = 0;
+
+ accum += 3 * ((PIN / 10000000) % 10);
+ accum += 1 * ((PIN / 1000000) % 10);
+ accum += 3 * ((PIN / 100000) % 10);
+ accum += 1 * ((PIN / 10000) % 10);
+ accum += 3 * ((PIN / 1000) % 10);
+ accum += 1 * ((PIN / 100) % 10);
+ accum += 3 * ((PIN / 10) % 10);
+ accum += 1 * ((PIN / 1) % 10);
+
+ return (0 == (accum % 10));
+} /* ValidateChecksum */
+
+/*
+ Generate 4-digit random number, ex:1234
+*/
+UINT WscRandomGen4digitPinCode(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT iPin;
+
+ iPin = RandomByte2(pAd) * 256 * 256 + RandomByte2(pAd) * 256 + RandomByte2(pAd);
+ iPin = iPin % 10000;
+
+ return iPin;
+}
+
+UINT WscRandomGeneratePinCode(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR apidx)
+{
+ UINT iPin;
+ UINT checksum;
+
+ iPin = RandomByte(pAd) * 256 * 256 + RandomByte(pAd) * 256 + RandomByte(pAd);
+
+ iPin = iPin % 10000000;
+
+
+ checksum = ComputeChecksum( iPin );
+ iPin = iPin*10 + checksum;
+
+ return iPin;
+}
+
+
+#ifdef CONFIG_AP_SUPPORT
+VOID WscInformFromWPA(
+ IN PMAC_TABLE_ENTRY pEntry)
+{
+ /* WPA_STATE_MACHINE informs this Entry is already WPA_802_1X_PORT_SECURED. */
+ RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)pEntry->pAd;
+ BOOLEAN Cancelled;
+
+ if (pEntry->apidx >= pAd->ApCfg.BssidNum)
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscInformFromWPA\n"));
+
+ if (MAC_ADDR_EQUAL(pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr))
+ {
+ NdisZeroMemory(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EntryAddr, MAC_ADDR_LEN);
+ RTMPCancelTimer(&pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EapolTimer, &Cancelled);
+ pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.EapolTimerRunning = FALSE;
+ pEntry->bWscCapable = FALSE;
+ pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscState = WSC_STATE_CONFIGURED;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Reset EntryIfIdx to %d\n", WSC_INIT_ENTRY_APIDX));
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscInformFromWPA\n"));
+}
+
+VOID WscDelWPARetryTimer(
+ IN PRTMP_ADAPTER pAd)
+{
+ PMAC_TABLE_ENTRY pEntry;
+ UCHAR apidx = MAIN_MBSSID;
+ BOOLEAN Cancelled;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscDelWPARetryTimer\n"));
+
+ pEntry = MacTableLookup(pAd, pAd->ApCfg.MBSSID[apidx].WscControl.EntryAddr);
+
+ if (pEntry)
+ {
+ RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
+ pEntry->WpaState = AS_NOTUSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscDelWPARetryTimer\n"));
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+VOID WscStop(
+ IN PRTMP_ADAPTER pAd,
+#ifdef CONFIG_AP_SUPPORT
+ IN BOOLEAN bFromApCli,
+#endif /* CONFIG_AP_SUPPORT */
+ IN PWSC_CTRL pWscControl)
+{
+ PWSC_UPNP_NODE_INFO pWscUPnPInfo;
+ BOOLEAN Cancelled;
+#ifdef WSC_LED_SUPPORT
+ UCHAR WPSLEDStatus;
+#endif /* WSC_LED_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+ MAC_TABLE_ENTRY *pEntry;
+#endif /* CONFIG_AP_SUPPORT */
+ UCHAR CurOpMode = 0xff;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+
+ pWscUPnPInfo = &pWscControl->WscUPnPNodeInfo;
+
+ if(pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE)
+ {
+ pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled);
+ pWscUPnPInfo->bUPnPMsgTimerPending = FALSE;
+ }
+ if(pWscControl->bM2DTimerRunning)
+ {
+ pWscControl->bM2DTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->M2DTimer, &Cancelled);
+ }
+
+ pWscUPnPInfo->bUPnPInProgress = FALSE;
+ pWscControl->M2DACKBalance = 0;
+ pWscUPnPInfo->registrarID = 0;
+
+ if (pWscControl->Wsc2MinsTimerRunning)
+ {
+ pWscControl->Wsc2MinsTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled);
+ }
+
+ if (pWscControl->WscUpdatePortCfgTimerRunning)
+ {
+ pWscControl->WscUpdatePortCfgTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->WscUpdatePortCfgTimer, &Cancelled);
+ }
+
+ RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled);
+ pWscControl->EapolTimerRunning = FALSE;
+#ifdef CONFIG_AP_SUPPORT
+//sync by 7610
+ if ((pWscControl->EntryIfIdx & 0x0F)< pAd->ApCfg.BssidNum)
+ {
+ pEntry = MacTableLookup(pAd, pWscControl->EntryAddr);
+
+ if (CurOpMode == AP_MODE)
+ {
+ if (pEntry && !bFromApCli)
+ {
+ pEntry->bWscCapable = FALSE;
+ }
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN);
+
+ pWscControl->WscSelReg = 0;
+ if ( (pWscControl->WscStatus == STATUS_WSC_CONFIGURED) ||
+ (pWscControl->WscStatus == STATUS_WSC_FAIL) ||
+ (pWscControl->WscStatus == STATUS_WSC_PBC_TOO_MANY_AP))
+ ;
+ else
+ pWscControl->WscStatus = STATUS_WSC_NOTUSED;
+ pWscControl->WscState = WSC_STATE_OFF;
+ pWscControl->lastId = 1;
+ pWscControl->EapMsgRunning = FALSE;
+ pWscControl->EapolTimerPending = FALSE;
+ pWscControl->bWscTrigger = FALSE;
+
+ if (pWscControl->WscScanTimerRunning)
+ {
+ pWscControl->WscScanTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->WscScanTimer, &Cancelled);
+ }
+
+ if (pWscControl->WscPBCTimerRunning)
+ {
+ pWscControl->WscPBCTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->WscPBCTimer, &Cancelled);
+ }
+
+
+#ifdef WSC_LED_SUPPORT
+ if (pWscControl->WscLEDTimerRunning)
+ {
+ pWscControl->WscLEDTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->WscLEDTimer, &Cancelled);
+ }
+ if (pWscControl->WscSkipTurnOffLEDTimerRunning)
+ {
+ pWscControl->WscSkipTurnOffLEDTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->WscSkipTurnOffLEDTimer, &Cancelled);
+ }
+ /* Reset the WPS walk time. */
+ pWscControl->bWPSWalkTimeExpiration = FALSE;
+ WPSLEDStatus = LED_WPS_TURN_LED_OFF;
+ RTMPSetLED(pAd, WPSLEDStatus);
+#endif /* WSC_LED_SUPPORT */
+//sync by 7610
+}
+
+VOID WscInit(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bFromApCli,
+ IN UCHAR BssIndex)
+{
+ IN PWSC_CTRL pWscControl = NULL;
+ UCHAR CurOpMode = AP_MODE;
+
+#ifdef CONFIG_AP_SUPPORT
+ INT IsAPConfigured;
+
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+#ifdef APCLI_SUPPORT
+ if (bFromApCli)
+ pWscControl = &pAd->ApCfg.ApCliTab[BssIndex & 0x0F].WscControl;
+ else
+#endif /* APCLI_SUPPORT */
+ pWscControl = &pAd->ApCfg.MBSSID[BssIndex & 0x0F].WscControl;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ if (pWscControl == NULL)
+ return;
+
+ if (pWscControl->WscEnrolleePinCode == 0)
+ {
+ if (pWscControl->WscEnrollee4digitPinCode)
+ {
+ pWscControl->WscEnrolleePinCodeLen = 4;
+ pWscControl->WscEnrolleePinCode = WscRandomGen4digitPinCode(pAd);
+ }
+ else
+ {
+ pWscControl->WscEnrolleePinCode = GenerateWpsPinCode(pAd, bFromApCli, BssIndex);
+ pWscControl->WscEnrolleePinCodeLen = 8;
+ }
+ }
+ pWscControl->RegData.SelfInfo.Version = WSC_VERSION;
+#ifdef WSC_V2_SUPPORT
+ pWscControl->RegData.SelfInfo.Version2 = WSC_V2_VERSION;
+#endif /* WSC_V2_SUPPORT */
+
+ pWscControl->bWscLastOne = FALSE;
+ pWscControl->bWscFirstOne = FALSE;
+
+
+ pWscControl->WscStatus = STATUS_WSC_IDLE;
+#ifdef CONFIG_AP_SUPPORT
+ if (((CurOpMode == AP_MODE) &&
+ (pWscControl->WscConfMode == WSC_DISABLE))
+#ifdef WSC_V2_SUPPORT
+ || ((pWscControl->WscV2Info.bWpsEnable == FALSE) && pWscControl->WscV2Info.bEnableWpsV2)
+#endif /* WSC_V2_SUPPORT */
+ )
+ {
+ if (CurOpMode == AP_MODE)
+ {
+#ifdef APCLI_SUPPORT
+ if (!bFromApCli)
+#endif /* APCLI_SUPPORT */
+ {
+ pAd->ApCfg.MBSSID[BssIndex & 0x0F].WscIEBeacon.ValueLen = 0;
+ pAd->ApCfg.MBSSID[BssIndex & 0x0F].WscIEProbeResp.ValueLen = 0;
+ }
+ }
+ }
+ else
+#endif /* CONFIG_AP_SUPPORT */
+ {
+
+ WscInitRegistrarPair(pAd, pWscControl, BssIndex);
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+#ifdef APCLI_SUPPORT
+ if (!bFromApCli)
+#endif /* APCLI_SUPPORT */
+ {
+ IsAPConfigured = pWscControl->WscConfStatus;
+ WscBuildBeaconIE(pAd, IsAPConfigured, FALSE, 0, 0, (BssIndex & 0x0F), NULL, 0, AP_MODE);
+ WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, BssIndex, NULL, 0, AP_MODE);
+ APUpdateBeaconFrame(pAd, pWscControl->EntryIfIdx & 0x0F);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+}
+
+USHORT WscGetAuthType(
+ IN NDIS_802_11_AUTHENTICATION_MODE authType)
+{
+ switch(authType)
+ {
+ case Ndis802_11AuthModeOpen:
+ return WSC_AUTHTYPE_OPEN;
+ case Ndis802_11AuthModeWPAPSK:
+ return WSC_AUTHTYPE_WPAPSK;
+ case Ndis802_11AuthModeShared:
+ return WSC_AUTHTYPE_SHARED;
+ case Ndis802_11AuthModeWPANone:
+ return WSC_AUTHTYPE_WPANONE;
+ case Ndis802_11AuthModeWPA:
+ return WSC_AUTHTYPE_WPA;
+ case Ndis802_11AuthModeWPA1WPA2:
+ return (WSC_AUTHTYPE_WPA | WSC_AUTHTYPE_WPA2);
+ case Ndis802_11AuthModeWPA2:
+ return WSC_AUTHTYPE_WPA2;
+ case Ndis802_11AuthModeWPA1PSKWPA2PSK:
+ return (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK);
+ case Ndis802_11AuthModeWPA2PSK:
+ return WSC_AUTHTYPE_WPA2PSK;
+ default:
+ return WSC_AUTHTYPE_OPEN;
+ }
+}
+
+USHORT WscGetEncryType(
+ IN NDIS_802_11_WEP_STATUS encryType)
+{
+ switch(encryType)
+ {
+ case Ndis802_11WEPDisabled:
+ return WSC_ENCRTYPE_NONE;
+ case Ndis802_11WEPEnabled:
+ return WSC_ENCRTYPE_WEP;
+ case Ndis802_11Encryption2Enabled:
+ return WSC_ENCRTYPE_TKIP;
+ case Ndis802_11Encryption4Enabled:
+ return (WSC_ENCRTYPE_AES | WSC_ENCRTYPE_TKIP);
+ default:
+ case Ndis802_11Encryption3Enabled:
+ return WSC_ENCRTYPE_AES;
+ }
+}
+
+PSTRING WscGetAuthTypeStr(
+ IN USHORT authFlag)
+{
+ switch(authFlag)
+ {
+ case WSC_AUTHTYPE_OPEN:
+ return "OPEN";
+ case WSC_AUTHTYPE_WPAPSK:
+ return "WPAPSK";
+ case WSC_AUTHTYPE_SHARED:
+ return "SHARED";
+ case WSC_AUTHTYPE_WPANONE:
+ return "WPANONE";
+ case WSC_AUTHTYPE_WPA:
+ return "WPA";
+ case WSC_AUTHTYPE_WPA2:
+ return "WPA2";
+ default:
+ case (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK):
+ return "WPAPSKWPA2PSK";
+ case WSC_AUTHTYPE_WPA2PSK:
+ return "WPA2PSK";
+ case (WSC_AUTHTYPE_OPEN | WSC_AUTHTYPE_SHARED):
+ return "WEPAUTO";
+ }
+}
+
+PSTRING WscGetEncryTypeStr(
+ IN USHORT encryFlag)
+{
+ switch(encryFlag)
+ {
+ case WSC_ENCRTYPE_NONE:
+ return "NONE";
+ case WSC_ENCRTYPE_WEP:
+ return "WEP";
+ case WSC_ENCRTYPE_TKIP:
+ return "TKIP";
+ default:
+ case (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES):
+ return "TKIPAES";
+ case WSC_ENCRTYPE_AES:
+ return "AES";
+ }
+}
+
+NDIS_802_11_AUTHENTICATION_MODE WscGetAuthMode(
+ IN USHORT authFlag)
+{
+ switch(authFlag)
+ {
+ case WSC_AUTHTYPE_OPEN:
+ return Ndis802_11AuthModeOpen;
+ case WSC_AUTHTYPE_WPAPSK:
+ return Ndis802_11AuthModeWPAPSK;
+ case WSC_AUTHTYPE_SHARED:
+ return Ndis802_11AuthModeShared;
+ case WSC_AUTHTYPE_WPANONE:
+ return Ndis802_11AuthModeWPANone;
+ case WSC_AUTHTYPE_WPA:
+ return Ndis802_11AuthModeWPA;
+ case WSC_AUTHTYPE_WPA2:
+ return Ndis802_11AuthModeWPA2;
+ default:
+ case (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK):
+ return Ndis802_11AuthModeWPA1PSKWPA2PSK;
+ case WSC_AUTHTYPE_WPA2PSK:
+ return Ndis802_11AuthModeWPA2PSK;
+ }
+}
+
+NDIS_802_11_WEP_STATUS WscGetWepStatus(
+ IN USHORT encryFlag)
+{
+ switch(encryFlag)
+ {
+ case WSC_ENCRTYPE_NONE:
+ return Ndis802_11WEPDisabled;
+ case WSC_ENCRTYPE_WEP:
+ return Ndis802_11WEPEnabled;
+ case WSC_ENCRTYPE_TKIP:
+ return Ndis802_11Encryption2Enabled;
+ default:
+ case (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES):
+ return Ndis802_11Encryption4Enabled;
+ case WSC_ENCRTYPE_AES:
+ return Ndis802_11Encryption3Enabled;
+ }
+}
+
+void WscWriteConfToPortCfg(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWscControl,
+ IN PWSC_CREDENTIAL pCredential,
+ IN BOOLEAN bEnrollee)
+{
+ UCHAR CurApIdx = MAIN_MBSSID;
+ UCHAR CurOpMode = AP_MODE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscWriteConfToPortCfg\n"));
+
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ CurApIdx = (pWscControl->EntryIfIdx & 0x0F);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+ if (bEnrollee || (CurOpMode == AP_MODE))
+ {
+ if (CurOpMode == AP_MODE)
+ {
+ NdisZeroMemory(pAd->ApCfg.MBSSID[CurApIdx].Ssid, MAX_LEN_OF_SSID);
+ NdisMoveMemory(pAd->ApCfg.MBSSID[CurApIdx].Ssid, pCredential->SSID.Ssid, pCredential->SSID.SsidLength);
+ pAd->ApCfg.MBSSID[CurApIdx].SsidLen = pCredential->SSID.SsidLength;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ra%d - AuthType: %u, EncrType: %u\n", CurApIdx, pCredential->AuthType, pCredential->EncrType));
+ if (pCredential->AuthType & (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK | WSC_AUTHTYPE_WPANONE))
+ {
+ if (!(pCredential->EncrType & (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES)))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AuthType is WPAPSK or WPA2PAK.\n"
+ "Get illegal EncrType(%d) from External Registrar, set EncrType to TKIP\n",
+ pCredential->EncrType));
+ pCredential->EncrType = WSC_ENCRTYPE_TKIP;
+ }
+#ifdef CONFIG_AP_SUPPORT
+#ifdef WSC_V2_SUPPORT
+ if ((CurOpMode == AP_MODE) && (pWscControl->WscV2Info.bEnableWpsV2))
+ {
+ if (pCredential->AuthType == WSC_AUTHTYPE_WPAPSK)
+ pCredential->AuthType = (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK);
+ if (pCredential->EncrType == WSC_ENCRTYPE_TKIP)
+ pCredential->EncrType = (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES);
+ }
+#endif /* WSC_V2_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ WscSetAuthMode(pAd, CurOpMode, CurApIdx, WscGetAuthTypeStr(pCredential->AuthType));
+ WscSetEncrypType(pAd, CurOpMode, CurApIdx, WscGetEncryTypeStr(pCredential->EncrType));
+ if (pCredential->EncrType != WSC_ENCRTYPE_NONE)
+ {
+ if (pCredential->EncrType & (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES))
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ pAd->ApCfg.MBSSID[CurApIdx].DefaultKeyId = 1;
+#endif /* CONFIG_AP_SUPPORT */
+
+ if (pCredential->KeyLength >= 8 && pCredential->KeyLength <= 64)
+ {
+ UCHAR *pPMKBuf = NULL, *pSSIDStr = NULL;
+ INT ssidLen = 0;
+ STRING PassphraseStr[65] = {0};
+
+ pWscControl->WpaPskLen = pCredential->KeyLength;
+ RTMPZeroMemory(pWscControl->WpaPsk, 64);
+ RTMPMoveMemory(pWscControl->WpaPsk, pCredential->Key, pWscControl->WpaPskLen);
+ //sync by 7610
+ RTMPMoveMemory(PassphraseStr, pCredential->Key, pWscControl->WpaPskLen);
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ pPMKBuf = pAd->ApCfg.MBSSID[CurApIdx].PMK;
+ pSSIDStr = (PUCHAR)pAd->ApCfg.MBSSID[CurApIdx].Ssid;
+ ssidLen = pAd->ApCfg.MBSSID[CurApIdx].SsidLen;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ RT_CfgSetWPAPSKKey(pAd, pCredential->Key, pWscControl->WpaPskLen, pSSIDStr, ssidLen, pPMKBuf);
+ DBGPRINT(RT_DEBUG_TRACE, ("WpaPskLen = %d\n", pWscControl->WpaPskLen));
+ }
+ else
+ {
+ pWscControl->WpaPskLen = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("WPAPSK: Invalid Key Length (%d)\n", pCredential->KeyLength));
+ }
+ }
+ else if (pCredential->EncrType == WSC_ENCRTYPE_WEP)
+ {
+ UCHAR WepKeyId = 0;
+ USHORT WepKeyLen = pCredential->KeyLength;
+
+ if ((pCredential->KeyIndex >= 1) && (pCredential->KeyIndex <= 4))
+ {
+ WepKeyId = (pCredential->KeyIndex - 1); /* KeyIndex = 1 ~ 4 */
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ pAd->ApCfg.MBSSID[CurApIdx].DefaultKeyId = WepKeyId;
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* 5 or 13 ASCII characters */
+ /* 10 or 26 Hex characters */
+ if (WepKeyLen == 5 || WepKeyLen == 13 || WepKeyLen == 10 || WepKeyLen == 26)
+ {
+ if (WepKeyLen == 5 || WepKeyLen == 13)
+ {
+ pAd->SharedKey[CurApIdx][WepKeyId].KeyLen = (UCHAR)WepKeyLen;
+ memcpy(pAd->SharedKey[CurApIdx][WepKeyId].Key,
+ pCredential->Key,
+ WepKeyLen);
+ if (WepKeyLen == 5)
+ pAd->SharedKey[CurApIdx][WepKeyId].CipherAlg = CIPHER_WEP64;
+ else
+ pAd->SharedKey[CurApIdx][WepKeyId].CipherAlg = CIPHER_WEP128;
+ }
+ else
+ {
+ pAd->SharedKey[CurApIdx][WepKeyId].KeyLen = (UCHAR)(WepKeyLen/2);
+ AtoH((PSTRING) pCredential->Key, pAd->SharedKey[CurApIdx][WepKeyId].Key, WepKeyLen/2);
+ if (WepKeyLen == 10)
+ pAd->SharedKey[CurApIdx][WepKeyId].CipherAlg = CIPHER_WEP64;
+ else
+ pAd->SharedKey[CurApIdx][WepKeyId].CipherAlg = CIPHER_WEP128;
+ }
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("WEP: Invalid Key Length (%d)\n", pCredential->KeyLength));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Unsupport default key index (%d)\n", WepKeyId));
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ pAd->ApCfg.MBSSID[CurApIdx].DefaultKeyId = 0;
+#endif /* CONFIG_AP_SUPPORT */
+
+ }
+ }
+ }
+#ifdef CONFIG_AP_SUPPORT
+ }
+ else
+ {
+ if (CurOpMode == AP_MODE)
+ {
+ pAd->ApCfg.MBSSID[CurApIdx].DefaultKeyId = 1;
+ WscSetAuthMode(pAd, CurOpMode, CurApIdx, "WPAPSKWPA2PSK");
+ WscSetEncrypType(pAd, CurOpMode, CurApIdx, "TKIPAES");
+ pWscControl->WpaPskLen = (INT)pCredential->KeyLength;
+ NdisZeroMemory(pWscControl->WpaPsk, 64);
+ NdisMoveMemory(pWscControl->WpaPsk, pCredential->Key, pWscControl->WpaPskLen);
+ /* Copy SSID */
+ NdisZeroMemory(pAd->ApCfg.MBSSID[CurApIdx].Ssid, MAX_LEN_OF_SSID);
+ NdisMoveMemory(pAd->ApCfg.MBSSID[CurApIdx].Ssid, pCredential->SSID.Ssid, pCredential->SSID.SsidLength);
+ pAd->ApCfg.MBSSID[CurApIdx].SsidLen = pCredential->SSID.SsidLength;
+ /*
+ Hex Key
+ */
+ if(pWscControl->WscKeyASCII == 0)
+ {
+ AtoH((PSTRING) pWscControl->WpaPsk, pAd->ApCfg.MBSSID[CurApIdx].PMK, 32);
+ }
+ else
+ {
+ UCHAR keyMaterial[40] = {0};
+
+ RtmpPasswordHash((PSTRING)pWscControl->WpaPsk,
+ (PUCHAR) pAd->ApCfg.MBSSID[CurApIdx].Ssid,
+ pAd->ApCfg.MBSSID[CurApIdx].SsidLen,
+ keyMaterial);
+ NdisMoveMemory(pAd->ApCfg.MBSSID[CurApIdx].PMK, keyMaterial, 32);
+ }
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- ra%d - WscWriteConfToPortCfg\n", CurApIdx));
+}
+
+
+VOID WscWriteSsidToDatFile(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING pTempStr,
+ IN BOOLEAN bNewFormat,
+ IN UCHAR CurOpMode)
+{
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR apidx;
+#endif /* CONFIG_AP_SUPPORT */
+ INT offset = 0;
+
+ if (bNewFormat == FALSE)
+ {
+ NdisZeroMemory(pTempStr, 512);
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ if (apidx == 0)
+ {
+ NdisMoveMemory(pTempStr, "SSID=", strlen("SSID="));
+ offset = strlen(pTempStr);
+ }
+ else
+ {
+ offset = strlen(pTempStr);
+ NdisMoveMemory(pTempStr + offset, ";", 1);
+ offset += 1;
+ }
+ NdisMoveMemory(pTempStr + offset, pAd->ApCfg.MBSSID[apidx].Ssid, pAd->ApCfg.MBSSID[apidx].SsidLen);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+#ifdef CONFIG_AP_SUPPORT
+ else
+ {
+ STRING item_str[10] = {0};
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ snprintf(item_str, sizeof(item_str), "SSID%d", (apidx + 1));
+ if (rtstrstr(pTempStr, item_str))
+ {
+ NdisZeroMemory(pTempStr, 512);
+ NdisMoveMemory(pTempStr, item_str, strlen(item_str));
+ offset = strlen(pTempStr);
+ NdisMoveMemory(pTempStr + offset, "=", 1);
+ offset += 1;
+ NdisMoveMemory(pTempStr + offset, pAd->ApCfg.MBSSID[apidx].Ssid, pAd->ApCfg.MBSSID[apidx].SsidLen);
+ }
+ NdisZeroMemory(item_str, 10);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+}
+
+
+VOID WscWriteWpaPskToDatFile(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING pTempStr,
+ IN BOOLEAN bNewFormat)
+{
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR apidx;
+#endif /* CONFIG_AP_SUPPORT */
+ PWSC_CTRL pWscControl;
+ INT offset = 0;
+
+ if (bNewFormat == FALSE)
+ {
+ NdisZeroMemory(pTempStr, 512);
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl;
+ if (apidx == 0)
+ {
+ NdisMoveMemory(pTempStr, "WPAPSK=", strlen("WPAPSK="));
+ offset = strlen(pTempStr);
+ }
+ else
+ {
+ offset = strlen(pTempStr);
+ NdisMoveMemory(pTempStr + offset, ";", 1);
+ offset += 1;
+ }
+ NdisMoveMemory(pTempStr + offset, pWscControl->WpaPsk, pWscControl->WpaPskLen);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+#ifdef CONFIG_AP_SUPPORT
+ else
+ {
+ STRING item_str[10] = {0};
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ snprintf(item_str, sizeof(item_str), "WPAPSK%d", (apidx + 1));
+ if (rtstrstr(pTempStr, item_str))
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl;
+ NdisZeroMemory(pTempStr, 512);
+ NdisMoveMemory(pTempStr, item_str, strlen(item_str));
+ offset = strlen(pTempStr);
+ NdisMoveMemory(pTempStr + offset, "=", 1);
+ offset += 1;
+ NdisMoveMemory(pTempStr + offset, pWscControl->WpaPsk, pWscControl->WpaPskLen);
+ }
+ NdisZeroMemory(item_str, 10);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+}
+
+BOOLEAN WscCheckNonce(
+ IN PRTMP_ADAPTER pAdapter,
+ IN MLME_QUEUE_ELEM *pElem,
+ IN BOOLEAN bFlag,
+ IN PWSC_CTRL pWscControl)
+{
+ USHORT Length;
+ PUCHAR pData;
+ USHORT WscType, WscLen, WscId;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscCheckNonce\n"));
+
+ if (bFlag)
+ {
+ /* check Registrar Nonce */
+ WscId = WSC_ID_REGISTRAR_NONCE;
+ DBGPRINT(RT_DEBUG_TRACE, ("check Registrar Nonce\n"));
+ }
+ else
+ {
+ /* check Enrollee Nonce */
+ WscId = WSC_ID_ENROLLEE_NONCE;
+ DBGPRINT(RT_DEBUG_TRACE, ("check Enrollee Nonce\n"));
+ }
+
+ pData = pElem->Msg;
+ Length = pElem->MsgLen;
+
+ /* We have to look for WSC_IE_MSG_TYPE to classify M2 ~ M8, the remain size must large than 4 */
+ while (Length > 4)
+ {
+ WSC_IE TLV_Recv;
+ char ZeroNonce[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+ memcpy((UINT8 *)&TLV_Recv, pData, 4);
+ WscType = be2cpu16(TLV_Recv.Type);
+ WscLen = be2cpu16(TLV_Recv.Length);
+ pData += 4;
+ Length -= 4;
+
+ if (WscType == WscId)
+ {
+ if (RTMPCompareMemory(pWscControl->RegData.SelfNonce, pData, 16) == 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Nonce match!!\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscCheckNonce\n"));
+ return TRUE;
+ }
+ else if (NdisEqualMemory(pData, ZeroNonce, 16))
+ {
+ /* Intel external registrar will send WSC_NACK with enrollee nonce */
+ /* "10 1A 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" */
+ /* when AP is configured and user selects not to configure AP. */
+ DBGPRINT(RT_DEBUG_TRACE, ("Zero Enrollee Nonce!!\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscCheckNonce\n"));
+ return TRUE;
+ }
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ Length -= WscLen;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Nonce mismatch!!\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscCheckNonce\n"));
+ return FALSE;
+}
+
+VOID WscGetRegDataPIN(
+ IN PRTMP_ADAPTER pAdapter,
+ IN UINT PinCode,
+ IN PWSC_CTRL pWscControl)
+{
+ UCHAR tempPIN[9] = {0};
+
+ if ((pWscControl->WscMode == WSC_PBC_MODE) ||
+ (pWscControl->WscMode == WSC_SMPBC_MODE))
+ pWscControl->WscPinCode = 0;
+ else
+ pWscControl->WscPinCode = PinCode;
+
+ memset(pWscControl->RegData.PIN, 0, 8);
+
+ if (pWscControl->WscPinCode == 0)
+ {
+ snprintf((PSTRING) tempPIN, sizeof(tempPIN), "00000000");
+ memcpy(pWscControl->RegData.PIN, tempPIN, 8);
+ pWscControl->RegData.PinCodeLen = 8;
+ }
+ else
+ {
+ if ( pWscControl->WscPinCodeLen == 4)
+ {
+ UCHAR temp4PIN[5] = {0};
+ snprintf((PSTRING) temp4PIN, sizeof(temp4PIN), "%04u", pWscControl->WscPinCode);
+ memcpy(pWscControl->RegData.PIN, temp4PIN, 4);
+ pWscControl->RegData.PinCodeLen = 4;
+ }
+ else
+ {
+ snprintf((PSTRING) tempPIN, sizeof(tempPIN), "%08u", pWscControl->WscPinCode);
+ memcpy(pWscControl->RegData.PIN, tempPIN, 8);
+ pWscControl->RegData.PinCodeLen = 8;
+ }
+ }
+ hex_dump("WscGetRegDataPIN - PIN", pWscControl->RegData.PIN, 8);
+}
+
+VOID WscEapActionDisabled(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl)
+{
+ INT DataLen = 0;
+ UCHAR *WscData = NULL;
+ /*BOOLEAN Cancelled;*/
+
+ os_alloc_mem(NULL, &WscData, 256);
+
+ if (WscData == NULL)
+ return;
+
+ DataLen = BuildMessageNACK(pAdapter, pWscControl, WscData);
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ {
+ if (pWscControl->EntryIfIdx & MIN_NET_DEVICE_FOR_APCLI)
+ WscSendMessage(pAdapter, WSC_OPCODE_NACK, WscData, DataLen, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP);
+ else
+ WscSendMessage(pAdapter, WSC_OPCODE_NACK, WscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ if (WscData)
+ os_free_mem(NULL, WscData);
+
+ /* RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); */
+ /* pWscControl->EapolTimerRunning = FALSE; */
+}
+
+VOID WscGetConfigErrFromNack(
+ IN PRTMP_ADAPTER pAdapter,
+ IN MLME_QUEUE_ELEM *pElem,
+ OUT USHORT *pConfigError)
+{
+ USHORT Length = 0;
+ PUCHAR pData;
+ USHORT WscType, WscLen, ConfigError = 0;
+
+ pData = pElem->Msg;
+ Length = pElem->MsgLen;
+
+ while (Length > 4)
+ {
+ WSC_IE TLV_Recv;
+ memcpy((UINT8 *)&TLV_Recv, pData, 4);
+ WscType = be2cpu16(TLV_Recv.Type);
+ WscLen = be2cpu16(TLV_Recv.Length);
+ pData += 4;
+ Length -= 4;
+
+ if (WscType == WSC_ID_CONFIG_ERROR)
+ {
+ NdisMoveMemory(&ConfigError, pData, sizeof(USHORT));
+ DBGPRINT(RT_DEBUG_TRACE, ("WSC_ID_CONFIG_ERROR: %d\n", ntohs(ConfigError)));
+ *pConfigError = ntohs(ConfigError);
+ return;
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ Length -= WscLen;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("WSC_ID_CONFIG_ERROR is missing\n"));
+}
+
+INT WscSetAuthMode(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR CurOpMode,
+ IN UCHAR apidx,
+ IN PSTRING arg)
+{
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ UINT32 i;
+
+ if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0))
+ pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeAutoSwitch;
+ else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0))
+ pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeOpen;
+ else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0))
+ pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeShared;
+ else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0))
+ pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPAPSK;
+ else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0))
+ pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA;
+ else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0))
+ pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA2PSK;
+ else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0))
+ pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA2;
+ else if ((strcmp(arg, "WPA1WPA2") == 0) || (strcmp(arg, "wpa1wpa2") == 0))
+ pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA1WPA2;
+ else if ((strcmp(arg, "WPAPSKWPA2PSK") == 0) || (strcmp(arg, "wpapskwpa2psk") == 0))
+ pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeWPA1PSKWPA2PSK;
+ else
+ {
+ pAd->ApCfg.MBSSID[apidx].AuthMode = Ndis802_11AuthModeOpen;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Unknow AuthMode (%s), set AuthMode to OPEN\n", __FUNCTION__, arg));
+ }
+
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i]))
+ {
+ pAd->MacTab.Content[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+ }
+ }
+ pAd->ApCfg.MBSSID[apidx].PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+ /*RTMPMakeRSNIE(pAd, pAd->ApCfg.MBSSID[apidx].AuthMode, pAd->ApCfg.MBSSID[apidx].WepStatus, apidx); */
+
+ pAd->ApCfg.MBSSID[apidx].DefaultKeyId = 0;
+
+ if(pAd->ApCfg.MBSSID[apidx].AuthMode >= Ndis802_11AuthModeWPA)
+ pAd->ApCfg.MBSSID[apidx].DefaultKeyId = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) %s::(AuthMode=%d)\n", apidx, __FUNCTION__, pAd->ApCfg.MBSSID[apidx].AuthMode));
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ return TRUE;
+}
+
+INT WscSetEncrypType(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR CurOpMode,
+ IN UCHAR apidx,
+ IN PSTRING arg)
+{
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+
+ if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0))
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPDisabled;
+ else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0))
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPEnabled;
+ else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0))
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption2Enabled;
+ else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0))
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption3Enabled;
+ else if ((strcmp(arg, "TKIPAES") == 0) || (strcmp(arg, "tkipaes") == 0))
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11Encryption4Enabled;
+ else
+ {
+ pAd->ApCfg.MBSSID[apidx].WepStatus = Ndis802_11WEPDisabled;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Unknow EncrypType (%s), set EncrypType to NONE\n", __FUNCTION__, arg));
+ }
+
+ if (pAd->ApCfg.MBSSID[apidx].WepStatus >= Ndis802_11Encryption2Enabled)
+ pAd->ApCfg.MBSSID[apidx].DefaultKeyId = 0;
+
+ /*RTMPMakeRSNIE(pAd, pAd->ApCfg.MBSSID[apidx].AuthMode, pAd->ApCfg.MBSSID[apidx].WepStatus, apidx); */
+ DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) %s::(EncrypType=%d)\n", apidx, __FUNCTION__, pAd->ApCfg.MBSSID[apidx].WepStatus));
+
+ return TRUE;
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ return TRUE;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Push PBC from HW/SW Buttton
+
+ Arguments:
+ pAd - NIC Adapter pointer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+
+VOID WscPushPBCAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWscControl)
+{
+ BOOLEAN Cancelled;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscPushPBCAction\n"));
+
+ /* 0. PBC mode, disregard the SSID information, we have to get the current AP list */
+ /* and check the beacon for Push buttoned AP. */
+
+ /* 1. Cancel old timer to prevent use push continuously */
+ if (pWscControl->Wsc2MinsTimerRunning)
+ {
+ pWscControl->Wsc2MinsTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled);
+ }
+ if (pWscControl->WscScanTimerRunning)
+ {
+ pWscControl->WscScanTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->WscScanTimer, &Cancelled);
+ }
+ if (pWscControl->WscPBCTimerRunning)
+ {
+ pWscControl->WscPBCTimerRunning = FALSE;
+ RTMPCancelTimer(&pWscControl->WscPBCTimer, &Cancelled);
+ }
+
+ /* Set WSC state to WSC_STATE_INIT */
+ pWscControl->WscState = WSC_STATE_START;
+ pWscControl->WscStatus = STATUS_WSC_SCAN_AP;
+
+ /* Init Registrar pair structures */
+ WscInitRegistrarPair(pAd, pWscControl, BSS0);
+
+ /* For PBC, the PIN is all '0' */
+ WscGetRegDataPIN(pAd, pWscControl->WscPinCode, pWscControl);
+
+ /* 2. Set 2 min timout routine */
+ RTMPSetTimer(&pWscControl->Wsc2MinsTimer, WSC_TWO_MINS_TIME_OUT);
+ pWscControl->Wsc2MinsTimerRunning = TRUE;
+ pWscControl->bWscTrigger = TRUE; /* start work */
+
+
+ /* 3. Call WscScan subroutine */
+ WscScanExec(pAd, pWscControl);
+
+ /* 4. Set 10 second timer to invoke PBC connection actions. */
+ RTMPSetTimer(&pWscControl->WscPBCTimer, 10000);
+ pWscControl->WscPBCTimerRunning = TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscPushPBCAction\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Doing an active scan with empty SSID, the scanened list will
+ be processed in PBCexec or PINexec routines
+
+ Arguments:
+ pAd - NIC Adapter pointer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID WscScanExec(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWscControl)
+{
+#ifdef WSC_LED_SUPPORT
+ UCHAR WPSLEDStatus;
+#endif /* WSC_LED_SUPPORT */
+
+ /* Prevent infinite loop if conncet time out didn't stop the repeat scan */
+ if ((pWscControl->WscStatus == STATUS_WSC_FAIL) ||
+ (pWscControl->WscState == WSC_STATE_OFF))
+ return;
+
+ DBGPRINT(RT_DEBUG_OFF, ("!!! WscScanExec !!!\n"));
+
+ pWscControl->WscStatus = STATUS_WSC_SCAN_AP;
+
+#ifdef WSC_LED_SUPPORT
+ /* The protocol is connecting to a partner. */
+ WPSLEDStatus = LED_WPS_IN_PROCESS;
+ RTMPSetLED(pAd, WPSLEDStatus);
+#endif /* WSC_LED_SUPPORT */
+
+#ifdef APCLI_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ ApSiteSurvey(pAd, NULL, SCAN_WSC_ACTIVE, FALSE);
+ }
+#endif /* APCLI_SUPPORT */
+
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Doing PBC conenction verification, it will check current BSS list
+ and find the correct number of PBC AP. If only 1 exists, it will
+ start to make connection. Otherwise, it will set a scan timer
+ to perform another scan for next PBC connection execution.
+
+ Arguments:
+ pAd - NIC Adapter pointer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+BOOLEAN WscPBCExec(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bFromM2,
+ IN PWSC_CTRL pWscControl)
+{
+#ifdef WSC_LED_SUPPORT
+ UCHAR WPSLEDStatus;
+#endif /* WSC_LED_SUPPORT */
+ UCHAR CurOpMode = AP_MODE;
+
+ if (pWscControl == NULL)
+ return FALSE;
+
+
+ DBGPRINT(RT_DEBUG_OFF, ("-----> WscPBCExec !!!\n"));
+
+ /* 1. Search the qualified SSID from current SSID list */
+ WscPBCBssTableSort(pAd, pWscControl);
+
+ /* 2. Check the qualified AP for connection, if more than 1 AP avaliable, report error. */
+ if (pWscControl->WscPBCBssCount != 1)
+ {
+ /* Set WSC state to WSC_FAIL */
+ pWscControl->WscState = WSC_STATE_FAIL;
+ if (pWscControl->WscPBCBssCount== 0)
+ {
+ pWscControl->WscStatus = STATUS_WSC_PBC_NO_AP;
+#ifdef WSC_LED_SUPPORT
+ /* Failed to find any partner. */
+ WPSLEDStatus = LED_WPS_ERROR;
+ RTMPSetLED(pAd, WPSLEDStatus);
+#ifdef CONFIG_WIFI_LED_SUPPORT
+ if (LED_MODE(pAd) == WPS_LED_MODE_SHARE)
+ RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_FAIL_WIFI_LED_TIMEOUT);
+#endif /* CONFIG_WIFI_LED_SUPPORT */
+
+#endif /* WSC_LED_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_OFF, ("WscPBCExec --> AP list is %d, wait for next time\n",
+ pWscControl->WscPBCBssCount));
+
+ {
+ /* 2.1. Set 1 second timer to invoke another scan */
+ RTMPSetTimer(&pWscControl->WscScanTimer, 1000);
+ pWscControl->WscScanTimerRunning = TRUE;
+ }
+ }
+ else
+ {
+ pWscControl->WscStatus = STATUS_WSC_PBC_TOO_MANY_AP;
+ RTMPSendWirelessEvent(pAd, IW_WSC_PBC_SESSION_OVERLAP, NULL, BSS0, 0);
+
+#ifdef WSC_LED_SUPPORT
+ if (LED_MODE(pAd) == WPS_LED_MODE_9) /* WPS LED mode 9. */
+ {
+ /* In case of the WPS LED mode 9, the UI would abort the connection attempt by making the RT_OID_802_11_WSC_SET_WPS_STATE_MACHINE_TERMINATION request. */
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Skip the WPS session overlap detected LED indication.\n", __FUNCTION__));
+ }
+ else /* Other LED mode. */
+ {
+ /* Session overlap detected. */
+ WPSLEDStatus = LED_WPS_SESSION_OVERLAP_DETECTED;
+ RTMPSetLED(pAd, WPSLEDStatus);
+
+
+ }
+#endif /* WSC_LED_SUPPORT */
+
+ /*
+ 20101210 - According to the response from WFA:
+ The station shall not continue scanning waiting for only one registrar to appear
+ */
+ DBGPRINT(RT_DEBUG_TRACE, ("WscPBCExec --> AP list is %d, stop WPS process!\n",
+ pWscControl->WscPBCBssCount));
+
+ WscStop(pAd,
+#ifdef CONFIG_AP_SUPPORT
+ FALSE,
+#endif /* CONFIG_AP_SUPPORT */
+ pWscControl);
+ pWscControl->WscConfMode = WSC_DISABLE;
+ RTMPZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID);
+ pAd->MlmeAux.AutoReconnectSsidLen = pAd->CommonCfg.SsidLen;
+ RTMPMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen);
+ }
+
+ /* 2.2 We have to quit for now */
+ return FALSE;
+ }
+
+ if (bFromM2)
+ return TRUE;
+
+
+ /* 3. Now we got the intend AP, Set the WSC state and enqueue the SSID connection command */
+ pAd->MlmeAux.CurrReqIsFromNdis = FALSE;
+
+
+#ifdef WSC_LED_SUPPORT
+ /* The protocol is connecting to a partner. */
+ WPSLEDStatus = LED_WPS_IN_PROCESS;
+ RTMPSetLED(pAd, WPSLEDStatus);
+#endif /* WSC_LED_SUPPORT */
+
+#ifdef APCLI_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ STRING ChStr[5] = {0};
+
+ NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr,
+ pAd->ApCfg.ApCliTab[BSS0].CurrentAddress,
+ MAC_ADDR_LEN);
+
+ snprintf(ChStr, sizeof(ChStr), "%d", pAd->MlmeAux.Channel);
+ Set_Channel_Proc(pAd, ChStr);
+
+ /* bring apcli interface down first */
+ if(pAd->ApCfg.ApCliTab[BSS0].Enable == TRUE)
+ {
+ pAd->ApCfg.ApCliTab[BSS0].Enable = FALSE;
+ ApCliIfDown(pAd);
+ }
+ pAd->ApCfg.ApCliTab[BSS0].Enable = TRUE;
+ }
+#endif /* APCLI_SUPPORT */
+
+
+ DBGPRINT(RT_DEBUG_OFF, ("<----- WscPBCExec !!!\n"));
+ return TRUE;
+}
+
+BOOLEAN WscBssWpsIESearchForPBC(
+ PRTMP_ADAPTER pAd,
+ PWSC_CTRL pWscControl,
+ PBSS_ENTRY pInBss,
+ UUID_BSSID_CH_INFO ApUuidBssid[],
+ INT VarIeLen,
+ PUCHAR pVar)
+{
+ INT j = 0, Len = 0, idx = 0;
+ BOOLEAN bFound, bSameAP, bSelReg;
+ PUCHAR pData = NULL;
+ PBEACON_EID_STRUCT pEid;
+ USHORT DevicePasswordID;
+ PWSC_IE pWscIE;
+ UUID_BSSID_CH_INFO TmpInfo;
+ UCHAR zeros16[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+ pData = pVar;
+ bFound = FALSE;
+ bSameAP = FALSE;
+ bSelReg = FALSE;
+ Len = VarIeLen;
+ NdisZeroMemory(&TmpInfo, sizeof(UUID_BSSID_CH_INFO));
+ while ((Len > 0) && (bFound == FALSE))
+ {
+ pEid = (PBEACON_EID_STRUCT) pData;
+
+ /* No match, skip the Eid and move forward, IE_WFA_WSC = 0xdd */
+ if (pEid->Eid != IE_WFA_WSC)
+ {
+ /* Set the offset and look for next IE */
+ pData += (pEid->Len + 2);
+ Len -= (pEid->Len + 2);
+ continue;
+ }
+ else
+ {
+ /* Found IE with 0xdd */
+ /* check for WSC OUI -- 00 50 f2 04 */
+ if ((NdisEqualMemory(pEid->Octet, WPS_OUI, 4) == FALSE)
+ )
+ {
+ /* Set the offset and look for next IE */
+ pData += (pEid->Len + 2);
+ Len -= (pEid->Len + 2);
+ continue;
+ }
+ }
+
+ /* 3. Found AP with WSC IE in beacons, skip 6 bytes = 1 + 1 + 4 */
+ pData += 6;
+ Len -= 6;
+
+ /* 4. Start to look the PBC type within WSC VarIE */
+ while (Len > 0)
+ {
+ /* Check for WSC IEs */
+ pWscIE = (PWSC_IE) pData;
+
+ if (be2cpu16(pWscIE->Type) == WSC_ID_SEL_REGISTRAR)
+ {
+ hex_dump("SelReg:", pData, 5);
+ bSelReg = pWscIE->Data[0];
+ DBGPRINT(RT_DEBUG_TRACE, ("bSelReg = %d\n", bSelReg));
+ }
+
+
+ /* Check for device password ID, PBC = 0x0004, SMPBC = 0x0006 */
+ if (be2cpu16(pWscIE->Type) == WSC_ID_DEVICE_PWD_ID)
+ {
+ /* Found device password ID */
+#ifdef WINBOND
+ /*The Winbond's platform will fail to retrive 2-bytes data, if use the original */
+ /*be2cpu16<-- */
+ DevicePasswordID = WINBON_GET16((PUCHAR)&pWscIE->Data[0]);
+#else
+ DevicePasswordID = be2cpu16(get_unaligned((USHORT *)&pWscIE->Data[0]));
+ /*DevicePasswordID = be2cpu16(*((USHORT *) &pWscIE->Data[0])); */
+#endif /* WINBOND */
+ DBGPRINT(RT_DEBUG_TRACE, ("WscPBCBssTableSort : DevicePasswordID = 0x%04x\n", DevicePasswordID));
+ if (((pWscControl->WscMode == WSC_PBC_MODE) && (DevicePasswordID == DEV_PASS_ID_PBC)) ||
+ ((pWscControl->WscMode == WSC_SMPBC_MODE) && (DevicePasswordID == DEV_PASS_ID_SMPBC)))
+ {
+ /* Found matching PBC AP in current list, add it into table and add the count */
+ bFound = TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("DPID=PBC Found --> \n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("# Bssid %02x:%02x:%02x:%02x:%02x:%02x\n",
+ pInBss->Bssid[0], pInBss->Bssid[1], pInBss->Bssid[2], pInBss->Bssid[3], pInBss->Bssid[4], pInBss->Bssid[5]));
+
+ if (pInBss->Channel > 14)
+ TmpInfo.Band = WSC_RFBAND_50GHZ;
+ else
+ TmpInfo.Band = WSC_RFBAND_24GHZ;
+
+ RTMPMoveMemory(&TmpInfo.Bssid[0], &pInBss->Bssid[0], MAC_ADDR_LEN);
+ TmpInfo.Channel = pInBss->Channel;
+ RTMPZeroMemory(&TmpInfo.Ssid[0], MAX_LEN_OF_SSID);
+ RTMPMoveMemory(&TmpInfo.Ssid[0], &pInBss->Ssid[0], pInBss->SsidLen);
+ TmpInfo.SsidLen = pInBss->SsidLen;
+ }
+ }
+
+ /* UUID_E is optional for beacons, but mandatory for probe-request */
+ if (be2cpu16(pWscIE->Type) == WSC_ID_UUID_E)
+ {
+ /* Avoid error UUID-E storage from PIN mode */
+ RTMPMoveMemory(&TmpInfo.Uuid[0], (UCHAR *)(pData+4), 16);
+ }
+
+ /* Set the offset and look for PBC information */
+ /* Since Type and Length are both short type, we need to offset 4, not 2 */
+ pData += (be2cpu16(pWscIE->Length) + 4);
+ Len -= (be2cpu16(pWscIE->Length) + 4);
+ }
+
+
+ if ((bFound == TRUE) && (bSelReg == TRUE))
+ {
+ if (pWscControl->WscPBCBssCount == 8)
+ {
+ break;
+ }
+
+ if (pWscControl->WscPBCBssCount > 0)
+ {
+ for (j = 0; j < pWscControl->WscPBCBssCount; j++)
+ {
+ if (RTMPCompareMemory(&ApUuidBssid[j].Uuid[0], &TmpInfo.Uuid[0], 16) == 0)
+ {
+ if (RTMPCompareMemory(&TmpInfo.Uuid[0], zeros16, 16) != 0)
+ {
+ /*
+ Same UUID, indicate concurrent AP
+ We can indicate 1 AP only.
+ */
+ bSameAP = TRUE;
+ break;
+ }
+ else if (RTMPCompareMemory(&TmpInfo.Uuid[0], zeros16, 16) == 0)
+ {
+ if (ApUuidBssid[j].Band != TmpInfo.Band)
+ {
+ if (RTMPCompareMemory(&ApUuidBssid[j].Bssid[0], &TmpInfo.Bssid[0], 5) == 0)
+ {
+ /*
+ Zero UUID at different band, and first 5bytes of two BSSIDs are the same.
+ Indicate concurrent AP, we can indicate 1 AP only.
+ */
+ bSameAP = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ else if ((RTMPCompareMemory(&TmpInfo.Uuid[0], zeros16, 16) == 0) ||
+ (RTMPCompareMemory(&ApUuidBssid[j].Uuid[0], zeros16, 16) == 0))
+ {
+ if ((RTMPCompareMemory(&ApUuidBssid[j].Bssid[0], &TmpInfo.Bssid[0], 5) == 0) &&
+ (ApUuidBssid[j].Band != TmpInfo.Band))
+ {
+ INT tmpDiff = (INT)(ApUuidBssid[j].Bssid[5] - TmpInfo.Bssid[5]);
+ /*
+ Zero UUID and Non-zero UUID at different band, and two BSSIDs are very close.
+ Indicate concurrent AP, we can indicate 1 AP only.
+ */
+ if ((tmpDiff <= 4) ||
+ (tmpDiff >= -4))
+ {
+ bSameAP = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (bSameAP)
+ {
+ if ((pWscControl->WpsApBand == PREFERRED_WPS_AP_PHY_TYPE_2DOT4_G_FIRST) &&
+ (TmpInfo.Band == WSC_RFBAND_24GHZ) &&
+ (ApUuidBssid[j].Band != TmpInfo.Band))
+ {
+ RTMPMoveMemory(&(ApUuidBssid[j].Bssid[0]), &TmpInfo.Bssid[0], MAC_ADDR_LEN);
+ RTMPZeroMemory(&(ApUuidBssid[j].Ssid[0]), MAX_LEN_OF_SSID);
+ RTMPMoveMemory(&(ApUuidBssid[j].Ssid[0]), &TmpInfo.Ssid[0], TmpInfo.SsidLen);
+ ApUuidBssid[j].SsidLen = TmpInfo.SsidLen;
+ ApUuidBssid[j].Channel = TmpInfo.Channel;
+ }
+ else if ((pWscControl->WpsApBand == PREFERRED_WPS_AP_PHY_TYPE_5_G_FIRST) &&
+ (TmpInfo.Band == WSC_RFBAND_50GHZ) &&
+ (ApUuidBssid[j].Band != TmpInfo.Band))
+ {
+ RTMPMoveMemory(&(ApUuidBssid[j].Bssid[0]), &TmpInfo.Bssid[0], MAC_ADDR_LEN);
+ RTMPZeroMemory(&(ApUuidBssid[j].Ssid[0]), MAX_LEN_OF_SSID);
+ RTMPMoveMemory(&(ApUuidBssid[j].Ssid[0]), &TmpInfo.Ssid[0], TmpInfo.SsidLen);
+ ApUuidBssid[j].SsidLen = TmpInfo.SsidLen;
+ ApUuidBssid[j].Channel = TmpInfo.Channel;
+ }
+ }
+
+ if (bSameAP == FALSE)
+ {
+ UCHAR index = pWscControl->WscPBCBssCount;
+
+ /* Store UUID */
+ RTMPMoveMemory(&(ApUuidBssid[index].Uuid[0]), &TmpInfo.Uuid[0], 16);
+ RTMPMoveMemory(&(ApUuidBssid[index].Bssid[0]), &pInBss->Bssid[0], MAC_ADDR_LEN);
+ RTMPZeroMemory(&(ApUuidBssid[index].Ssid[0]), MAX_LEN_OF_SSID);
+ RTMPMoveMemory(&(ApUuidBssid[index].Ssid[0]), &pInBss->Ssid[0], pInBss->SsidLen);
+ ApUuidBssid[index].SsidLen = pInBss->SsidLen;
+ ApUuidBssid[index].Channel = pInBss->Channel;
+ if (ApUuidBssid[index].Channel > 14)
+ ApUuidBssid[index].Band = WSC_RFBAND_50GHZ;
+ else
+ ApUuidBssid[index].Band = WSC_RFBAND_24GHZ;
+ DBGPRINT(RT_DEBUG_ERROR, ("UUID-E= "));
+ for(idx=0; idx<16; idx++)
+ DBGPRINT_RAW(RT_DEBUG_ERROR, ("%02x ", ApUuidBssid[index].Uuid[idx]));
+ DBGPRINT(RT_DEBUG_ERROR, ("\n"));
+
+ pWscControl->WscPBCBssCount++;
+ }
+ }
+ }
+
+ return (bFound && bSelReg);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Find WSC PBC activated AP list
+
+ Arguments:
+ pAd - NIC Adapter pointer
+ OutTab - Qualified AP BSS table
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ All these constants are defined in wsc.h
+
+ ========================================================================
+*/
+VOID WscPBCBssTableSort(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWscControl)
+{
+ INT i;
+ PBSS_ENTRY pInBss;
+/* UUID_BSSID_CH_INFO ApUuidBssid[8]; */
+ UUID_BSSID_CH_INFO *ApUuidBssid = NULL;
+ BOOLEAN rv = FALSE;
+ UCHAR CurOpMode = AP_MODE;
+
+
+#ifdef APCLI_SUPPORT
+if (CurOpMode == AP_MODE)
+ pWscControl = &pAd->ApCfg.ApCliTab[BSS0].WscControl;
+#endif /* APCLI_SUPPORT */
+
+
+ if (pWscControl == NULL)
+ return;
+
+ /* allocate memory */
+ os_alloc_mem(NULL, (UCHAR **)&ApUuidBssid, sizeof(UUID_BSSID_CH_INFO)*8);
+ if (ApUuidBssid == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ return;
+ }
+
+ NdisZeroMemory(&ApUuidBssid[0], sizeof(UUID_BSSID_CH_INFO));
+ pWscControl->WscPBCBssCount = 0;
+ for (i = 0; i < pAd->ScanTab.BssNr; i++)
+ {
+ /* BSS entry for VarIE processing */
+ pInBss = (PBSS_ENTRY) &pAd->ScanTab.BssEntry[i];
+
+ /* 1. Check VarIE length */
+ if (pInBss->VarIELen == 0)
+ continue;
+
+
+ /* 2. Search for WSC IE - 0xdd xx 00 50 f2 04 */
+ rv = WscBssWpsIESearchForPBC(pAd,
+ pWscControl,
+ pInBss,
+ ApUuidBssid,
+ pInBss->VarIELen,
+ pInBss->VarIEs);
+ if (rv == FALSE)
+ {
+ WscBssWpsIESearchForPBC(pAd,
+ pWscControl,
+ pInBss,
+ ApUuidBssid,
+ pInBss->VarIeFromProbeRspLen,
+ pInBss->pVarIeFromProbRsp);
+ }
+ }
+
+ if (pWscControl->WscPBCBssCount == 1)
+ {
+ RTMPZeroMemory(&pWscControl->WscSsid, sizeof(NDIS_802_11_SSID));
+ RTMPMoveMemory(pWscControl->WscSsid.Ssid, ApUuidBssid[0].Ssid, ApUuidBssid[0].SsidLen);
+ pWscControl->WscSsid.SsidLength = ApUuidBssid[0].SsidLen;
+ RTMPZeroMemory(pWscControl->WscBssid, MAC_ADDR_LEN);
+ RTMPMoveMemory(pWscControl->WscBssid, ApUuidBssid[0].Bssid, MAC_ADDR_LEN);
+ pAd->MlmeAux.Channel = ApUuidBssid[0].Channel;
+
+#ifdef APCLI_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ NdisZeroMemory(pAd->ApCfg.ApCliTab[BSS0].CfgSsid, MAX_LEN_OF_SSID);
+ NdisMoveMemory(pAd->ApCfg.ApCliTab[BSS0].CfgSsid, ApUuidBssid[0].Ssid, ApUuidBssid[0].SsidLen);
+ pAd->ApCfg.ApCliTab[BSS0].CfgSsidLen = (UCHAR)ApUuidBssid[0].SsidLen;
+ }
+#endif /* APCLI_SUPPORT */
+
+ }
+
+ if (ApUuidBssid != NULL)
+ os_free_mem(NULL, ApUuidBssid);
+
+ DBGPRINT(RT_DEBUG_OFF, ("WscPBCBssTableSort : Total %d PBC Registrar Found\n", pWscControl->WscPBCBssCount));
+}
+
+VOID WscGenRandomKey(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWscControl,
+ INOUT PUCHAR pKey,
+ INOUT PUSHORT pKeyLen)
+{
+ UCHAR tempRandomByte = 0;
+ UCHAR idx = 0;
+ UCHAR keylen = 0;
+ UCHAR retry = 0;
+
+ NdisZeroMemory(pKey, 64);
+
+ /*
+ Hex Key 64 digital
+ */
+ if(pWscControl->WscKeyASCII == 0)
+ {
+ UCHAR tmpStrB[3];
+ for (idx = 0; idx < 32; idx++)
+ {
+ NdisZeroMemory(&tmpStrB[0], sizeof(tmpStrB));
+ tempRandomByte = RandomByte(pAd);
+ snprintf((PSTRING) &tmpStrB[0], 3, "%02x", tempRandomByte);
+ NdisMoveMemory(pKey+(idx*2), &tmpStrB[0], 2);
+ }
+ *pKeyLen = 64;
+ }
+ else
+ {
+ /*
+ ASCII Key, random length
+ */
+ if(pWscControl->WscKeyASCII == 1)
+ {
+ do{
+ keylen = RandomByte(pAd);
+ keylen = keylen % 64;
+ if(retry++ > 20)
+ keylen = 8;
+ }while(keylen < 8);
+ }
+ else
+ keylen = pWscControl->WscKeyASCII;
+
+ /*
+ Generate printable ASCII (decimal 33 to 126)
+ */
+ for(idx = 0; idx < keylen; idx++)
+ {
+ tempRandomByte = RandomByte(pAd)%94+33;
+ *(pKey+idx) = tempRandomByte;
+ }
+ *pKeyLen = keylen;
+ }
+}
+
+VOID WscCreateProfileFromCfg(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR OpMode,
+ IN PWSC_CTRL pWscControl,
+ OUT PWSC_PROFILE pWscProfile)
+{
+ UCHAR apidx = (pWscControl->EntryIfIdx & 0x0F);
+ USHORT authType = 0, encyType = 0;
+ UCHAR WepKeyId = 0;
+ PWSC_CREDENTIAL pCredential = NULL;
+ UCHAR CurOpMode = AP_MODE;
+
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if ((OpMode & 0x0F) == AP_MODE)
+ {
+ /*
+ AP needs to choose the STA's authType and encyType in two cases.
+ 1. AP is unconfigurated (authType and encyType will be updated to mixed mode by WscWriteConfToPortCfg() )
+ 2. AP's authType is mixed mode, we should choose the suitable authType and encyType to STA
+ STA's authType and encyType depend on WscSecurityMode flag
+ */
+
+ if (((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED ) ||
+ (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) &&
+ (OpMode & REGISTRAR_ACTION))
+ {
+ switch (pAd->ApCfg.MBSSID[apidx].WscSecurityMode)
+ {
+ case WPAPSKTKIP:
+ authType = WSC_AUTHTYPE_WPAPSK;
+ encyType = WSC_ENCRTYPE_TKIP;
+ break;
+ case WPAPSKAES:
+ authType = WSC_AUTHTYPE_WPAPSK;
+ encyType = WSC_ENCRTYPE_AES;
+ break;
+ case WPA2PSKTKIP:
+ authType = WSC_AUTHTYPE_WPA2PSK;
+ encyType = WSC_ENCRTYPE_TKIP;
+ break;
+ case WPA2PSKAES:
+ authType = WSC_AUTHTYPE_WPA2PSK;
+ encyType = WSC_ENCRTYPE_AES;
+ break;
+ default:
+ authType = (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK);
+ encyType = (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES);
+ break;
+ }
+
+ if (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED)
+ {
+ /*
+ Although AuthMode is mixed mode, cipher maybe not mixed mode.
+ We need to correct cipher here.
+ */
+ if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption2Enabled)
+ encyType = WSC_ENCRTYPE_TKIP;
+ if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption3Enabled)
+ encyType = WSC_ENCRTYPE_AES;
+ }
+ }
+ else
+ {
+ authType = WscGetAuthType(pAd->ApCfg.MBSSID[apidx].AuthMode);
+ encyType = WscGetEncryType(pAd->ApCfg.MBSSID[apidx].WepStatus);
+ }
+ WepKeyId = pAd->ApCfg.MBSSID[apidx].DefaultKeyId;
+ }
+#ifdef APCLI_SUPPORT
+ else if (OpMode == AP_CLIENT_MODE)
+ {
+ apidx = apidx & 0x0F;
+ authType = WscGetAuthType(pAd->ApCfg.ApCliTab[apidx].AuthMode);
+ encyType = WscGetEncryType(pAd->ApCfg.ApCliTab[apidx].WepStatus);
+ WepKeyId = pAd->ApCfg.ApCliTab[apidx].DefaultKeyId;
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscGetDefaultProfileForM8\n"));
+
+ pCredential = &pWscProfile->Profile[0]; /*Only support one credential now. 20070515 */
+ NdisZeroMemory(pCredential, sizeof(WSC_CREDENTIAL));
+ pWscProfile->ProfileCnt = 1;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: pWscControl->WscConfStatus = %d, OpMode = %d\n",
+ __FUNCTION__, pWscControl->WscConfStatus, OpMode));
+
+ /* NewKey, NewKeyIndex for M8 */
+ if ((WSC_SCSTATE_UNCONFIGURED == pWscControl->WscConfStatus) &&
+ ((((OpMode & 0x0F) == AP_MODE)
+ ) && (OpMode & REGISTRAR_ACTION)))
+ {
+ pCredential->KeyIndex = 1;
+ if ((OpMode & 0x0F) == STA_MODE)
+ {
+ {
+ WscGenRandomKey(pAd, pWscControl, pCredential->Key, &pCredential->KeyLength);
+ authType = WSC_AUTHTYPE_WPA2PSK;
+ encyType = WSC_ENCRTYPE_AES;
+ }
+ }
+ else
+ WscGenRandomKey(pAd, pWscControl, pCredential->Key, &pCredential->KeyLength);
+ }
+ else
+ {
+ pCredential->KeyIndex = 1;
+ pCredential->KeyLength = 0;
+ NdisZeroMemory(pCredential->Key, 64);
+ switch (encyType)
+ {
+ case WSC_ENCRTYPE_NONE:
+ break;
+ case WSC_ENCRTYPE_WEP:
+ pCredential->KeyIndex = (WepKeyId + 1);
+ if (((OpMode & 0x0F) == AP_MODE || (OpMode & 0x0F) == STA_MODE) && pAd->SharedKey[apidx][WepKeyId].KeyLen)
+ {
+ INT i;
+ for (i=0; i<pAd->SharedKey[apidx][WepKeyId].KeyLen; i++)
+ {
+ snprintf((PSTRING) pCredential->Key, 64, "%s%02x", pCredential->Key, pAd->SharedKey[apidx][WepKeyId].Key[i]);
+ }
+ pCredential->KeyLength = pAd->SharedKey[apidx][WepKeyId].KeyLen*2;
+ }
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+ else if ((OpMode == AP_CLIENT_MODE) && (pAd->ApCfg.ApCliTab[apidx].SharedKey[WepKeyId].KeyLen) &&
+ (CurOpMode == AP_MODE))
+ {
+ INT i;
+ for (i=0; i<pAd->ApCfg.ApCliTab[apidx].SharedKey[WepKeyId].KeyLen; i++)
+ {
+ snprintf((PSTRING) pCredential->Key, 64, "%s%02x", pCredential->Key, pAd->ApCfg.ApCliTab[apidx].SharedKey[WepKeyId].Key[i]);
+ }
+ pCredential->KeyLength = pAd->SharedKey[apidx][WepKeyId].KeyLen*2;
+ }
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+ break;
+ case WSC_ENCRTYPE_TKIP:
+ case WSC_ENCRTYPE_AES:
+ case (WSC_ENCRTYPE_AES | WSC_ENCRTYPE_TKIP):
+ pCredential->KeyLength = pWscControl->WpaPskLen;
+ memcpy(pCredential->Key,
+ pWscControl->WpaPsk,
+ pWscControl->WpaPskLen);
+ break;
+ }
+ }
+
+ pCredential->AuthType = authType;
+ pCredential->EncrType = encyType;
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if ((OpMode & 0x0F) == AP_MODE)
+ {
+ NdisMoveMemory(pCredential->MacAddr, pAd->ApCfg.MBSSID[apidx].Bssid, 6);
+ if ((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) &&
+ (pWscControl->WscDefaultSsid.SsidLength > 0) &&
+ (pWscControl->WscDefaultSsid.SsidLength < 33))
+ {
+ NdisMoveMemory(pCredential->SSID.Ssid, pWscControl->WscDefaultSsid.Ssid, pWscControl->WscDefaultSsid.SsidLength);
+ pCredential->SSID.SsidLength = pWscControl->WscDefaultSsid.SsidLength;
+ }
+ else
+ {
+ NdisMoveMemory(pCredential->SSID.Ssid, pAd->ApCfg.MBSSID[apidx].Ssid, pAd->ApCfg.MBSSID[apidx].SsidLen);
+ pCredential->SSID.SsidLength = pAd->ApCfg.MBSSID[apidx].SsidLen;
+ }
+ }
+#ifdef APCLI_SUPPORT
+ else if (OpMode == AP_CLIENT_MODE)
+ {
+ NdisMoveMemory(pCredential->MacAddr, APCLI_ROOT_BSSID_GET(pAd, pAd->ApCfg.ApCliTab[apidx].MacTabWCID), 6);
+ NdisMoveMemory(pCredential->SSID.Ssid, pAd->ApCfg.ApCliTab[apidx].Ssid, pAd->ApCfg.ApCliTab[apidx].SsidLen);
+ pCredential->SSID.SsidLength = pAd->ApCfg.ApCliTab[apidx].SsidLen;
+ }
+#endif /* APCLI_SUPPORT */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2 && (OpMode & REGISTRAR_ACTION))
+ NdisMoveMemory(pCredential->MacAddr, pWscControl->EntryAddr, 6);
+#endif /* WSC_V2_SUPPORT */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscCreateProfileFromCfg\n"));
+
+}
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef APCLI_SUPPORT
+void WscWriteConfToApCliCfg(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWscControl,
+ IN PWSC_CREDENTIAL pCredential,
+ IN BOOLEAN bEnrollee)
+{
+ UCHAR CurApIdx = BSS0;
+ APCLI_STRUCT *pApCliTab;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscWriteConfToApCliCfg\n"));
+
+ CurApIdx = (pWscControl->EntryIfIdx & 0x0F);
+ {
+ pApCliTab = &pAd->ApCfg.ApCliTab[CurApIdx];
+
+ NdisZeroMemory(pApCliTab->Ssid, MAX_LEN_OF_SSID);
+ NdisMoveMemory(pApCliTab->Ssid, pCredential->SSID.Ssid, pCredential->SSID.SsidLength);
+ pApCliTab->SsidLen = pCredential->SSID.SsidLength;
+
+ NdisZeroMemory(pApCliTab->CfgSsid, MAX_LEN_OF_SSID);
+ NdisMoveMemory(pApCliTab->CfgSsid, pCredential->SSID.Ssid, pCredential->SSID.SsidLength);
+ pApCliTab->CfgSsidLen = pCredential->SSID.SsidLength;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AuthType: %d, EncrType: %d\n", pCredential->AuthType, pCredential->EncrType));
+ if ((pCredential->AuthType == WSC_AUTHTYPE_WPAPSK) ||
+ (pCredential->AuthType == WSC_AUTHTYPE_WPA2PSK))
+ {
+ if ((pCredential->EncrType != WSC_ENCRTYPE_TKIP) && (pCredential->EncrType != WSC_ENCRTYPE_AES))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AuthType is WPAPSK or WPA2PAK.\n"
+ "Get illegal EncrType(%d) from External Registrar, set EncrType to TKIP\n",
+ pCredential->EncrType));
+ pCredential->EncrType = WSC_ENCRTYPE_TKIP;
+ }
+ }
+ Set_ApCli_AuthMode_Proc(pAd, WscGetAuthTypeStr(pCredential->AuthType));
+ Set_ApCli_EncrypType_Proc(pAd, WscGetEncryTypeStr(pCredential->EncrType));
+
+ if (pCredential->EncrType != WSC_ENCRTYPE_NONE)
+ {
+ if (pCredential->EncrType & (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES))
+ {
+ pApCliTab->DefaultKeyId = 0;
+
+ if (pCredential->KeyLength >= 8 && pCredential->KeyLength <= 64)
+ {
+ pWscControl->WpaPskLen = (INT) pCredential->KeyLength;
+ NdisZeroMemory(pWscControl->WpaPsk, 64);
+ NdisMoveMemory(pWscControl->WpaPsk, pCredential->Key, pWscControl->WpaPskLen);
+ RT_CfgSetWPAPSKKey(pAd, (PSTRING) pCredential->Key, pWscControl->WpaPskLen,
+ (PUCHAR)pApCliTab->Ssid, pApCliTab->SsidLen,
+ pApCliTab->PMK);
+ DBGPRINT(RT_DEBUG_TRACE, ("WpaPskLen = %d\n", pWscControl->WpaPskLen));
+ }
+ else
+ {
+ pWscControl->WpaPskLen = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("WPAPSK: Invalid Key Length (%d)\n", pCredential->KeyLength));
+ }
+ }
+ else if (pCredential->EncrType == WSC_ENCRTYPE_WEP)
+ {
+ CHAR WepKeyId = 0;
+ USHORT WepKeyLen = pCredential->KeyLength;
+
+ WepKeyId = (pCredential->KeyIndex - 1); /* KeyIndex = 1 ~ 4 */
+ if ((WepKeyId >= 0) && (WepKeyId <=3))
+ {
+ pApCliTab->DefaultKeyId = WepKeyId;
+
+ /* 5 or 13 ASCII characters */
+ /* 10 or 26 Hex characters */
+ if (WepKeyLen == 5 || WepKeyLen == 13 || WepKeyLen == 10 || WepKeyLen == 26)
+ {
+ if (WepKeyLen == 5 || WepKeyLen == 13)
+ {
+ pApCliTab->SharedKey[WepKeyId].KeyLen = WepKeyLen;
+ memcpy(pApCliTab->SharedKey[WepKeyId].Key,
+ pCredential->Key,WepKeyLen);
+ if (WepKeyLen == 5)
+ pApCliTab->SharedKey[WepKeyId].CipherAlg = CIPHER_WEP64;
+ else
+ pApCliTab->SharedKey[WepKeyId].CipherAlg = CIPHER_WEP128;
+ }
+ else
+ {
+ pApCliTab->SharedKey[WepKeyId].KeyLen = (UCHAR) WepKeyLen/2;
+ AtoH((PSTRING) pCredential->Key, pApCliTab->SharedKey[WepKeyId].Key, WepKeyLen/2);
+ if (WepKeyLen == 10)
+ pApCliTab->SharedKey[WepKeyId].CipherAlg = CIPHER_WEP64;
+ else
+ pApCliTab->SharedKey[WepKeyId].CipherAlg = CIPHER_WEP128;
+ }
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("WEP: Invalid Key Length (%d)\n", pCredential->KeyLength));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Unsupport default key index (%d), use key Index 1.\n", WepKeyId));
+ pApCliTab->DefaultKeyId = WepKeyId = 0;
+ }
+ }
+ }
+ }
+
+ if (pWscControl->WscProfile.ProfileCnt > 1)
+ {
+ pWscControl->WscProfileRetryTimerRunning = TRUE;
+ RTMPSetTimer(&pWscControl->WscProfileRetryTimer, WSC_PROFILE_RETRY_TIME_OUT);
+ }
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscWriteConfToApCliCfg\n"));
+}
+
+VOID WscApCliLinkDown(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWscControl)
+{
+ UCHAR apidx = (pWscControl->EntryIfIdx & 0x0F);
+ UCHAR mac_addr[MAC_ADDR_LEN];
+ BOOLEAN apcliEn = pAd->ApCfg.ApCliTab[apidx].Enable;
+
+ NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr,
+ pAd->ApCfg.ApCliTab[apidx].CurrentAddress,
+ 6);
+
+ /* bring apcli interface down first */
+ if(apcliEn == TRUE )
+ {
+ pAd->ApCfg.ApCliTab[apidx].Enable = FALSE;
+ ApCliIfDown(pAd);
+ }
+ pAd->ApCfg.ApCliTab[apidx].Enable = apcliEn;
+ memcpy(mac_addr, pAd->ApCfg.ApCliTab[apidx].CurrentAddress, MAC_ADDR_LEN);
+ pWscControl->WscStatus = STATUS_WSC_LINK_UP;
+ pWscControl->bWscTrigger = TRUE;
+}
+#endif /* APCLI_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+VOID WpsSmProcess(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ int HeaderLen = LENGTH_802_11 + LENGTH_802_1_H + sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME);
+ PHEADER_802_11 pHeader;
+ PMAC_TABLE_ENTRY pEntry = NULL;
+ int apidx = MAIN_MBSSID;
+ PWSC_CTRL pWpsCtrl = NULL;
+ UCHAR CurOpMode = 0xFF;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ CurOpMode = AP_MODE;
+ }
+#endif // CONFIG_AP_SUPPORT //
+
+
+ if (CurOpMode == 0xFF)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("Unkown OpMode (CurOpMode=0x%02x)\n", CurOpMode));
+ return;
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("CurOpMode=0x%02x\n", CurOpMode));
+
+ pHeader = (PHEADER_802_11)Elem->Msg;
+
+ if (Elem->MsgType == WSC_EAPOL_PACKET_MSG)
+ {
+ if ((pEntry = MacTableLookup(pAd, pHeader->Addr2)))
+ apidx = pEntry->apidx;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+#ifdef APCLI_SUPPORT
+ if (pEntry && IS_ENTRY_APCLI(pEntry))
+ pWpsCtrl = &pAd->ApCfg.ApCliTab[apidx].WscControl;
+ else
+#endif /* APCLI_SUPPORT */
+ pWpsCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ if((Elem->MsgType == WSC_EAPOL_UPNP_MSG) && (Elem->MsgLen > HeaderLen))
+ { /*The WSC msg from UPnP daemon */
+ PUCHAR pData;
+ UCHAR MacAddr[MAC_ADDR_LEN]= {0};
+
+ /* Skip the (802.11 + 802.1h + 802.1x + EAP) header */
+ pData = (PUCHAR) &Elem->Msg[HeaderLen];
+ Elem->MsgLen -= HeaderLen;
+ /* The Addr1 of UPnP-Msg used to indicate the MAC address of the AP interface. Now always be ra0. */
+ NdisMoveMemory(MacAddr, pHeader->Addr1, MAC_ADDR_LEN);
+ NdisMoveMemory(Elem->Msg, MacAddr, MAC_ADDR_LEN);
+ NdisMoveMemory(Elem->Msg+6, pData, Elem->MsgLen);
+
+ StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState);
+ }
+ else if (Elem->MsgType == WSC_EAPOL_START_MSG)
+ StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState);
+ else if (pEntry && (Elem->MsgType == WSC_EAPOL_PACKET_MSG))
+ { /* WSC_STATE_MACHINE can service only one station at one time */
+ PSTRING pData;
+ PEAP_FRAME pEapFrame;
+ /* Skip the EAP LLC header */
+ pData = (PSTRING) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
+ pEapFrame = (PEAP_FRAME)(pData + sizeof(IEEE8021X_FRAME));
+ pData += sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME);
+
+ DBGPRINT(RT_DEBUG_ERROR, ("%s:: EAPOL Packet. Code = %d. Type = %d\n",
+ __FUNCTION__, pEapFrame->Code, pEapFrame->Type));
+ if (pEapFrame->Code == EAP_CODE_FAIL)
+ { /* EAP-Fail */
+ STRING fail_data[] = "EAP_FAIL";
+ NdisMoveMemory(Elem->Msg, pHeader->Addr2, MAC_ADDR_LEN);
+ NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, fail_data, strlen(fail_data));
+ Elem->MsgLen = strlen(fail_data);
+ StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState);
+ return;
+ }
+ else if ((pEapFrame->Code == EAP_CODE_REQ) && (pEapFrame->Type == EAP_TYPE_ID))
+ { /* EAP-Req (Identity) */
+ STRING id_data[] = "hello";
+
+ pWpsCtrl->lastId = pEapFrame->Id;
+ NdisMoveMemory(Elem->Msg, pHeader->Addr2, MAC_ADDR_LEN);
+ NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, id_data, strlen(id_data));
+ Elem->MsgLen = strlen(id_data);
+ StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState);
+ return;
+ }
+ else if ((pEapFrame->Code == EAP_CODE_REQ) && (pEapFrame->Type == EAP_TYPE_WSC))
+ { /* EAP-Req (Messages) */
+ if (Elem->MsgLen <= HeaderLen)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Elem->MsgLen(%ld) <= HeaderLen(%d) !!\n", Elem->MsgLen, HeaderLen));
+ return;
+ }
+
+ pWpsCtrl->lastId = pEapFrame->Id;
+ Elem->MsgLen -= (LENGTH_802_11 + LENGTH_802_1_H + sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME));
+ if (WscCheckWSCHeader((PUCHAR)pData))
+ {
+ PWSC_FRAME pWsc = (PWSC_FRAME) pData;
+
+ NdisMoveMemory(Elem->Msg, pHeader->Addr2, MAC_ADDR_LEN);
+ if (pWsc->OpCode == WSC_OPCODE_FRAG_ACK)
+ {
+ /*
+ Send rest WSC frag data
+ */
+ STRING wsc_frag_ack[] = "WSC_FRAG_ACK";
+
+ NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, wsc_frag_ack, strlen(wsc_frag_ack));
+ Elem->MsgLen = strlen(wsc_frag_ack);
+ StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState);
+ }
+ else if (pWsc->OpCode == WSC_OPCODE_START)
+ {
+ STRING wsc_start[] = "WSC_START";
+
+ NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, wsc_start, strlen(wsc_start));
+ Elem->MsgLen = strlen(wsc_start);
+ StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState);
+ }
+ else
+ {
+ if (pWsc->Flags & WSC_MSG_FLAG_LF)
+ {
+ pData += (sizeof(WSC_FRAME) + 2);
+ Elem->MsgLen -= (sizeof(WSC_FRAME) + 2);
+ }
+ else
+ {
+ pData += sizeof(WSC_FRAME);
+ Elem->MsgLen -= sizeof(WSC_FRAME);
+ }
+
+ if ((pWpsCtrl->WscRxBufLen + Elem->MsgLen) < (MGMT_DMA_BUFFER_SIZE-6))
+ {
+ NdisMoveMemory((pWpsCtrl->pWscRxBuf + pWpsCtrl->WscRxBufLen), pData, Elem->MsgLen);
+ pWpsCtrl->WscRxBufLen += Elem->MsgLen;
+ }
+#ifdef WSC_V2_SUPPORT
+ if (pWsc->Flags & WSC_MSG_FLAG_MF)
+ WscSendEapFragAck(pAd, pWpsCtrl, pEntry);
+ else
+#endif /* WSC_V2_SUPPORT */
+ {
+ NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, pWpsCtrl->pWscRxBuf, pWpsCtrl->WscRxBufLen);
+ Elem->MsgLen = pWpsCtrl->WscRxBufLen;
+ StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState);
+ pWpsCtrl->WscRxBufLen = 0;
+ NdisZeroMemory(pWpsCtrl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE);
+ }
+ }
+ return;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ERROR: WscCheckWSCHeader() return FALSE!\n"));
+ return;
+ }
+ }
+
+ if (Elem->MsgLen <= HeaderLen)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Elem->MsgLen(%ld) <= HeaderLen(%d) !!\n", Elem->MsgLen, HeaderLen));
+ return;
+ }
+
+ Elem->MsgLen -= (LENGTH_802_11 + LENGTH_802_1_H + sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME));
+ NdisMoveMemory(Elem->Msg, pHeader->Addr2, MAC_ADDR_LEN);
+ if (IS_ENTRY_CLIENT(pEntry) &&
+ (pEapFrame->Code == EAP_CODE_RSP) &&
+ (pEapFrame->Type == EAP_TYPE_ID))
+ {
+ if (strstr(pData, "SimpleConfig"))
+ {
+ /* EAP-Rsp (Identity) */
+ NdisMoveMemory(Elem->Msg+6, pData, Elem->MsgLen);
+ StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState);
+ return;
+ }
+ else
+ {
+ BOOLEAN Cancelled;
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPCancelTimer EapolTimer!!\n"));
+ NdisZeroMemory(pWpsCtrl->EntryAddr, MAC_ADDR_LEN);
+ pWpsCtrl->EapolTimerRunning = FALSE;
+ RTMPCancelTimer(&pWpsCtrl->EapolTimer, &Cancelled);
+ return;
+ }
+ }
+ else
+ {
+ if (WscCheckWSCHeader((PUCHAR) pData))
+ {
+ /* EAP-Rsp (Messages) */
+ PWSC_FRAME pWsc = (PWSC_FRAME) pData;
+ if (pWsc->OpCode == WSC_OPCODE_FRAG_ACK)
+ {
+ /*
+ Send rest frag data
+ */
+ STRING wsc_frag_ack[] = "WSC_FRAG_ACK";
+ NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, wsc_frag_ack, strlen(wsc_frag_ack));
+ Elem->MsgLen = strlen(wsc_frag_ack);
+ StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState);
+ }
+ else
+ {
+ if (pWsc->Flags & WSC_MSG_FLAG_LF)
+ {
+ pData += (sizeof(WSC_FRAME) + 2);
+ Elem->MsgLen -= (sizeof(WSC_FRAME) + 2);
+ }
+ else
+ {
+ pData += sizeof(WSC_FRAME);
+ Elem->MsgLen -= sizeof(WSC_FRAME);
+ }
+
+ if ((pWpsCtrl->WscRxBufLen + Elem->MsgLen) < (MGMT_DMA_BUFFER_SIZE-6))
+ {
+ NdisMoveMemory((pWpsCtrl->pWscRxBuf + pWpsCtrl->WscRxBufLen), pData, Elem->MsgLen);
+ pWpsCtrl->WscRxBufLen += Elem->MsgLen;
+ }
+#ifdef WSC_V2_SUPPORT
+ if (pWsc->Flags & WSC_MSG_FLAG_MF)
+ WscSendEapFragAck(pAd, pWpsCtrl, pEntry);
+ else
+#endif /* WSC_V2_SUPPORT */
+ {
+ //NdisMoveMemory(Elem->Msg+6, pData, Elem->MsgLen);
+ NdisMoveMemory(Elem->Msg+6, pWpsCtrl->pWscRxBuf, pWpsCtrl->WscRxBufLen);
+ Elem->MsgLen = pWpsCtrl->WscRxBufLen;
+ StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState);
+ pWpsCtrl->WscRxBufLen = 0;
+ NdisZeroMemory(pWpsCtrl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE);
+ }
+ }
+ return;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ERROR: WscCheckWSCHeader() return FALSE!\n"));
+ return;
+ }
+ }
+ }
+ else
+ DBGPRINT(RT_DEBUG_WARN, ("Unknow Message Type (=%lu)\n", Elem->MsgType));
+}
+
+#ifdef CONFIG_AP_SUPPORT
+INT WscGetConfWithoutTrigger(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWscControl,
+ IN BOOLEAN bFromUPnP)
+{
+ INT WscMode;
+ INT IsAPConfigured;
+ PWSC_UPNP_NODE_INFO pWscUPnPNodeInfo;
+ UCHAR apIdx;
+
+#ifdef LINUX
+#endif /* LINUX */
+
+
+ /* TODO: Is it possible ApCli call this fucntion?? */
+ apIdx = (pWscControl->EntryIfIdx & 0x0F);
+
+ IsAPConfigured = pWscControl->WscConfStatus;
+ pWscUPnPNodeInfo = &pWscControl->WscUPnPNodeInfo;
+
+ if (pWscControl->WscConfMode == WSC_DISABLE)
+ {
+ pWscControl->bWscTrigger = FALSE;
+ DBGPRINT(RT_DEBUG_TRACE, ("WscGetConfForUpnp:: WPS is disabled.\n"));
+ return FALSE;
+ }
+
+ if (bFromUPnP)
+ WscStop(pAd, FALSE, pWscControl);
+
+ if (pWscControl->WscMode == 1)
+ WscMode = DEV_PASS_ID_PIN;
+ else
+ WscMode = DEV_PASS_ID_PBC;
+
+ WscBuildBeaconIE(pAd, IsAPConfigured, TRUE, WscMode, pWscControl->WscConfigMethods, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, AP_MODE);
+ WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, TRUE, WscMode, pWscControl->WscConfigMethods, pWscControl->EntryIfIdx, NULL, 0, AP_MODE);
+ APUpdateBeaconFrame(pAd, pWscControl->EntryIfIdx & 0x0F);
+
+ /* 2mins time-out timer */
+ RTMPSetTimer(&pWscControl->Wsc2MinsTimer, WSC_TWO_MINS_TIME_OUT);
+ pWscControl->Wsc2MinsTimerRunning = TRUE;
+ pWscControl->WscStatus = STATUS_WSC_LINK_UP;
+ if (bFromUPnP)
+ WscSendUPnPConfReqMsg(pAd, apIdx, (PUCHAR)pAd->ApCfg.MBSSID[apIdx].Ssid,
+ pAd->ApCfg.MBSSID[apIdx].Bssid, 3, 0, AP_MODE);
+
+ pWscControl->bWscTrigger = TRUE;
+ pWscControl->bWscAutoTigeer = TRUE;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: trigger WSC state machine\n", __FUNCTION__));
+
+ return TRUE;
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+VOID WscSendNACK(
+ IN PRTMP_ADAPTER pAdapter,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN PWSC_CTRL pWscControl)
+{
+ INT DataLen = 0;
+ PUCHAR pWscData = NULL;
+ BOOLEAN Cancelled;
+ UCHAR CurOpMode = AP_MODE;
+
+
+ os_alloc_mem(NULL, (UCHAR **)&pWscData, WSC_MAX_DATA_LEN);
+ if (pWscData == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscSendNACK:: WscData Allocate failed!\n"));
+ return;
+ }
+
+ NdisZeroMemory(pWscData, WSC_MAX_DATA_LEN);
+ DataLen = BuildMessageNACK(pAdapter, pWscControl, pWscData);
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (pEntry &&
+ (IS_ENTRY_APCLI(pEntry)
+ )
+ )
+ WscSendMessage(pAdapter, WSC_OPCODE_NACK, pWscData, DataLen, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP);
+ else
+ WscSendMessage(pAdapter, WSC_OPCODE_NACK, pWscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled);
+ pWscControl->EapolTimerRunning = FALSE;
+ pWscControl->RegData.ReComputePke = 1;
+
+ if (pWscData)
+ os_free_mem(NULL, pWscData);
+}
+
+#ifdef WSC_INCLUDED
+VOID WscCheckWpsIeFromWpsAP(
+ IN PRTMP_ADAPTER pAd,
+ IN PEID_STRUCT pEid,
+ OUT PUSHORT pDPIDFromAP)
+{
+ PUCHAR pData;
+ SHORT Len = 0;
+ PWSC_IE pWscIE;
+ USHORT DevicePasswordID;
+
+ if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4)
+ )
+ {
+ pData = (PUCHAR) pEid->Octet + 4;
+ Len = (SHORT)(pEid->Len - 4);
+
+ while (Len > 0)
+ {
+ WSC_IE WscIE;
+ NdisMoveMemory(&WscIE, pData, sizeof(WSC_IE));
+ /* Check for WSC IEs */
+ pWscIE = &WscIE;
+
+ /* Check for device password ID, PIN = 0x0000, PBC = 0x0004 */
+ if (pDPIDFromAP && be2cpu16(pWscIE->Type) == WSC_ID_DEVICE_PWD_ID)
+ {
+ /* Found device password ID */
+ NdisMoveMemory(&DevicePasswordID, pData + 4, sizeof(DevicePasswordID));
+ DevicePasswordID = be2cpu16(DevicePasswordID);
+ DBGPRINT(RT_DEBUG_INFO, ("WscCheckWpsIeFromWpsAP : DevicePasswordID = 0x%04x\n", DevicePasswordID));
+ if (DevicePasswordID == DEV_PASS_ID_PIN)
+ {
+ /* PIN */
+ *pDPIDFromAP = DEV_PASS_ID_PIN;
+ }
+ else if (DevicePasswordID == DEV_PASS_ID_PBC)
+ {
+ /* PBC */
+ *pDPIDFromAP = DEV_PASS_ID_PBC;
+ }
+ }
+
+
+ /* Set the offset and look for PBC information */
+ /* Since Type and Length are both short type, we need to offset 4, not 2 */
+ pData += (be2cpu16(pWscIE->Length) + 4);
+ Len -= (be2cpu16(pWscIE->Length) + 4);
+ }
+ }
+
+ return;
+}
+#endif /* WSC_INCLUDED */
+
+
+VOID WscPBCSessionOverlapCheck(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG now;
+ PWSC_STA_PBC_PROBE_INFO pWscStaPbcProbeInfo = &pAd->CommonCfg.WscStaPbcProbeInfo;
+
+ pAd->CommonCfg.WscPBCOverlap = FALSE;
+ if (pWscStaPbcProbeInfo->WscPBCStaProbeCount > 1)
+ {
+ UCHAR i;
+
+ for (i = 0; i < MAX_PBC_STA_TABLE_SIZE; i++)
+ {
+ NdisGetSystemUpTime(&now);
+ if (pWscStaPbcProbeInfo->Valid[i] &&
+ RTMP_TIME_AFTER(now, pWscStaPbcProbeInfo->ReciveTime[i] + 120*OS_HZ))
+ {
+ NdisZeroMemory(&(pWscStaPbcProbeInfo->StaMacAddr[i][0]), MAC_ADDR_LEN);
+ pWscStaPbcProbeInfo->ReciveTime[i] = 0;
+ pWscStaPbcProbeInfo->Valid[i] = FALSE;
+ pWscStaPbcProbeInfo->WscPBCStaProbeCount--;
+ }
+ }
+
+ if (pWscStaPbcProbeInfo->WscPBCStaProbeCount > 1)
+ pAd->CommonCfg.WscPBCOverlap = TRUE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscPBCSessionOverlapCheck : WscPBCStaProbeCount = %d\n",
+ pWscStaPbcProbeInfo->WscPBCStaProbeCount));
+ return;
+}
+
+VOID WscPBC_DPID_FromSTA(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pMacAddr)
+{
+ INT Index = 0;
+ UCHAR tab_idx;
+ BOOLEAN bAddEntry = FALSE;
+ ULONG now;
+ PWSC_STA_PBC_PROBE_INFO pWscStaPbcProbeInfo = &pAd->CommonCfg.WscStaPbcProbeInfo;
+
+ NdisGetSystemUpTime(&now);
+ if (pWscStaPbcProbeInfo->WscPBCStaProbeCount == 0)
+ bAddEntry = TRUE;
+ else
+ {
+ for (tab_idx = 0; tab_idx < MAX_PBC_STA_TABLE_SIZE; tab_idx++)
+ {
+ if (NdisEqualMemory(pMacAddr, pWscStaPbcProbeInfo->StaMacAddr[tab_idx], MAC_ADDR_LEN))
+ {
+ pWscStaPbcProbeInfo->ReciveTime[tab_idx] = now;
+ return;
+ }
+ }
+
+ for (tab_idx = 0; tab_idx < MAX_PBC_STA_TABLE_SIZE; tab_idx++)
+ {
+ if (RTMP_TIME_AFTER(now, pWscStaPbcProbeInfo->ReciveTime[tab_idx] + 120*OS_HZ) ||
+ NdisEqualMemory(pWscStaPbcProbeInfo->StaMacAddr[tab_idx], &ZERO_MAC_ADDR[0], MAC_ADDR_LEN))
+ {
+ if (pWscStaPbcProbeInfo->Valid[tab_idx] == FALSE)
+ {
+ Index = tab_idx;
+ bAddEntry = TRUE;
+ break;
+ }
+ else
+ {
+ pWscStaPbcProbeInfo->ReciveTime[tab_idx] = now;
+ NdisMoveMemory(pWscStaPbcProbeInfo->StaMacAddr[tab_idx], pMacAddr, MAC_ADDR_LEN);
+ return;
+ }
+ }
+ }
+ }
+
+ if (bAddEntry)
+ {
+ pWscStaPbcProbeInfo->WscPBCStaProbeCount++;
+ pWscStaPbcProbeInfo->ReciveTime[Index] = now;
+ pWscStaPbcProbeInfo->Valid[Index] = TRUE;
+ NdisMoveMemory(pWscStaPbcProbeInfo->StaMacAddr[Index], pMacAddr, MAC_ADDR_LEN);
+ }
+}
+
+void WscWriteConfToDatFile(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR CurOpMode)
+{
+ char *cfgData = 0;
+ PSTRING fileName = NULL;
+ RTMP_OS_FD file_r, file_w;
+ RTMP_OS_FS_INFO osFSInfo;
+ LONG rv, fileLen = 0;
+ char *offset = 0;
+ PSTRING pTempStr = 0;
+#ifdef CONFIG_AP_SUPPORT
+ INT index = 0;
+ UCHAR apidx = (pAd->WriteWscCfgToDatFile & 0x0F);
+#endif /* CONFIG_AP_SUPPORT */
+ PWSC_CTRL pWscControl = NULL;
+ PWSC_CREDENTIAL pCredentail = NULL;
+ STRING WepKeyName[MAX_WEPKEYNAME_LEN] = {0};
+ STRING WepKeyFormatName[MAX_WEPKEYNAME_LEN] = {0};
+ INT tempStrLen = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscWriteConfToDatFile(CurOpMode = %d)\n", CurOpMode));
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ if (apidx > pAd->ApCfg.BssidNum)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscWriteConfToDatFile (wrong apidx = %d)\n", apidx));
+ return;
+ }
+ pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl;
+ fileName = AP_PROFILE_PATH;
+
+ snprintf((PSTRING) WepKeyName, sizeof(WepKeyName), "Key%dStr%d=", pAd->ApCfg.MBSSID[apidx].DefaultKeyId+1, apidx+1);
+ snprintf((PSTRING) WepKeyFormatName, sizeof(WepKeyFormatName), "Key%dType=", pAd->ApCfg.MBSSID[apidx].DefaultKeyId+1);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ RtmpOSFSInfoChange(&osFSInfo, TRUE);
+
+ file_r = RtmpOSFileOpen(fileName, O_RDONLY, 0);
+ if (IS_FILE_OPEN_ERR(file_r))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("-->1) %s: Error opening file %s\n", __FUNCTION__, fileName));
+ return;
+ }
+ else
+ {
+ char tempStr[64] = {0};
+ while((rv = RtmpOSFileRead(file_r, tempStr, 64)) > 0)
+ {
+ fileLen += rv;
+ }
+ os_alloc_mem(NULL, (UCHAR **)&cfgData, fileLen);
+ if (cfgData == NULL)
+ {
+ RtmpOSFileClose(file_r);
+ DBGPRINT(RT_DEBUG_TRACE, ("CfgData kmalloc fail. (fileLen = %ld)\n", fileLen));
+ goto out;
+ }
+ NdisZeroMemory(cfgData, fileLen);
+ RtmpOSFileSeek(file_r, 0);
+ rv = RtmpOSFileRead(file_r, (PSTRING)cfgData, fileLen);
+ RtmpOSFileClose(file_r);
+ if (rv != fileLen)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CfgData kmalloc fail, fileLen = %ld\n", fileLen));
+ goto ReadErr;
+ }
+ }
+
+ file_w = RtmpOSFileOpen(fileName, O_WRONLY|O_TRUNC, 0);
+ if (IS_FILE_OPEN_ERR(file_w))
+ {
+ goto WriteFileOpenErr;
+ }
+ else
+ {
+ offset = (PCHAR) rtstrstr((PSTRING) cfgData, "Default\n");
+ offset += strlen("Default\n");
+ RtmpOSFileWrite(file_w, (PSTRING)cfgData, (int)(offset-cfgData));
+ os_alloc_mem(NULL, (UCHAR **)&pTempStr, 512);
+ if (!pTempStr)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("pTempStr kmalloc fail. (512)\n"));
+ RtmpOSFileClose(file_w);
+ goto WriteErr;
+ }
+
+ for (;;)
+ {
+ int i = 0;
+ PSTRING ptr;
+ BOOLEAN bNewFormat = TRUE;
+
+ NdisZeroMemory(pTempStr, 512);
+ ptr = (PSTRING) offset;
+ while(*ptr && *ptr != '\n')
+ {
+ pTempStr[i++] = *ptr++;
+ }
+ pTempStr[i] = 0x00;
+ if ((size_t)(offset - cfgData) < fileLen)
+ {
+ offset += strlen(pTempStr) + 1;
+ if ((strncmp(pTempStr, "SSID=", strlen("SSID=")) == 0) ||
+ strncmp(pTempStr, "SSID1=", strlen("SSID1=")) == 0 ||
+ strncmp(pTempStr, "SSID2=", strlen("SSID2=")) == 0 ||
+ strncmp(pTempStr, "SSID3=", strlen("SSID3=")) == 0 ||
+ strncmp(pTempStr, "SSID4=", strlen("SSID4=")) == 0
+ )
+ {
+ if (rtstrstr(pTempStr, "SSID="))
+ bNewFormat = FALSE;
+
+ WscWriteSsidToDatFile(pAd, pTempStr, bNewFormat, CurOpMode);
+ }
+ else if (strncmp(pTempStr, "AuthMode=", strlen("AuthMode=")) == 0)
+ {
+ NdisZeroMemory(pTempStr, 512);
+ snprintf(pTempStr, 512, "AuthMode=");
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ for (index = 0; index < pAd->ApCfg.BssidNum; index++)
+ {
+ if (pAd->ApCfg.MBSSID[index].SsidLen)
+ {
+ if (index == 0)
+ snprintf(pTempStr, 512, "%s%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].AuthMode));
+ else
+ snprintf(pTempStr, 512, "%s;%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].AuthMode));
+ }
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ else if (strncmp(pTempStr, "EncrypType=", strlen("EncrypType=")) == 0)
+ {
+ NdisZeroMemory(pTempStr, 512);
+ snprintf(pTempStr, 512, "EncrypType=");
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ for (index = 0; index < pAd->ApCfg.BssidNum; index++)
+ {
+ if (index == 0)
+ snprintf(pTempStr, 512, "%s%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].WepStatus));
+ else
+ snprintf(pTempStr, 512, "%s;%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].WepStatus));
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ else if ((strncmp(pTempStr, "WPAPSK=", strlen("WPAPSK=")) == 0) ||
+ (strncmp(pTempStr, "WPAPSK1=", strlen("WPAPSK1=")) == 0) ||
+ (strncmp(pTempStr, "WPAPSK2=", strlen("WPAPSK2=")) == 0) ||
+ (strncmp(pTempStr, "WPAPSK3=", strlen("WPAPSK3=")) == 0) ||
+ (strncmp(pTempStr, "WPAPSK4=", strlen("WPAPSK4=")) == 0))
+ {
+ bNewFormat = TRUE;
+ if (strstr(pTempStr, "WPAPSK="))
+ bNewFormat = FALSE;
+ WscWriteWpaPskToDatFile(pAd, pTempStr, bNewFormat);
+ }
+ else if (strncmp(pTempStr, "WscConfMode=", strlen("WscConfMode=")) == 0)
+ {
+ snprintf(pTempStr, 512, "WscConfMode=");
+#ifdef CONFIG_AP_SUPPORT
+ for (index = 0; index < pAd->ApCfg.BssidNum; index++)
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[index].WscControl;
+ if (index == 0)
+ snprintf(pTempStr, 512, "%s%d", pTempStr, pWscControl->WscConfMode);
+ else
+ snprintf(pTempStr, 512, "%s;%d", pTempStr, pWscControl->WscConfMode);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ else if (strncmp(pTempStr, "WscConfStatus=", strlen("WscConfStatus=")) == 0)
+ {
+ snprintf(pTempStr, 512, "WscConfStatus=");
+#ifdef CONFIG_AP_SUPPORT
+ for (index = 0; index < pAd->ApCfg.BssidNum; index++)
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[index].WscControl;
+ if (index == 0)
+ snprintf(pTempStr, 512, "%s%d", pTempStr, pWscControl->WscConfStatus);
+ else
+ snprintf(pTempStr, 512, "%s;%d", pTempStr, pWscControl->WscConfStatus);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+ else if (strncmp(pTempStr, "DefaultKeyID=", strlen("DefaultKeyID=")) == 0)
+ {
+ NdisZeroMemory(pTempStr, 512);
+ snprintf(pTempStr, 512, "DefaultKeyID=");
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ for (index = 0; index < pAd->ApCfg.BssidNum; index++)
+ {
+ if (index == 0)
+ snprintf(pTempStr, 512, "%s%d", pTempStr, pAd->ApCfg.MBSSID[index].DefaultKeyId+1);
+ else
+ snprintf(pTempStr, 512, "%s;%d", pTempStr, pAd->ApCfg.MBSSID[index].DefaultKeyId+1);
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+#ifdef CONFIG_AP_SUPPORT
+ else if ((strncmp(pTempStr, WepKeyFormatName, strlen(WepKeyFormatName)) == 0) &&
+ (CurOpMode == AP_MODE))
+ {
+ pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0];
+ if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11WEPEnabled)
+ {
+ UCHAR idx = 0, KeyType[4] = {0};
+ PSTRING ptr2, temp_ptr;
+
+ ptr2 = rtstrstr(pTempStr, "=");
+ temp_ptr = pTempStr;
+ pTempStr = ptr2+1;
+ KeyType[0] = (UCHAR)(*pTempStr - 0x30);
+ for (idx = 1; idx < 4; idx++)
+ {
+ ptr2 = rtstrstr(pTempStr, ";");
+ if (ptr2 == NULL)
+ break;
+ pTempStr = ptr2+1;
+ if ((pTempStr != NULL) ||
+ (*pTempStr == '0') ||
+ (*pTempStr == '1'))
+ KeyType[idx] = (UCHAR)(*pTempStr - 0x30);
+ }
+ pTempStr = temp_ptr;
+ NdisZeroMemory(pTempStr, 512);
+ NdisMoveMemory(pTempStr, WepKeyFormatName, strlen(WepKeyFormatName));
+ for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++)
+ {
+ if (idx == apidx)
+ snprintf(pTempStr, 512, "%s0", pTempStr);
+ else
+ snprintf(pTempStr, 512, "%s%d", pTempStr, KeyType[idx]);
+
+ if (apidx < (pAd->ApCfg.BssidNum - 1))
+ snprintf(pTempStr, 512, "%s;", pTempStr);
+ }
+ }
+ }
+ else if ((strncmp(pTempStr, WepKeyName, strlen(WepKeyName)) == 0) &&
+ (CurOpMode == AP_MODE))
+ {
+ pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0];
+ if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11WEPEnabled)
+ {
+ NdisZeroMemory(pTempStr, 512);
+ NdisMoveMemory(pTempStr, WepKeyName, strlen(WepKeyName));
+ tempStrLen = strlen(pTempStr);
+ if (pCredentail->KeyLength)
+ {
+ if ((pCredentail->KeyLength == 5) ||
+ (pCredentail->KeyLength == 13))
+ {
+ int jjj=0;
+ for (jjj=0; jjj<pCredentail->KeyLength; jjj++)
+ snprintf(pTempStr, 512, "%s%02x", pTempStr, pCredentail->Key[jjj]);
+ }
+ else if ((pCredentail->KeyLength == 10) ||
+ (pCredentail->KeyLength == 26))
+ {
+ NdisMoveMemory(pTempStr + tempStrLen, pCredentail->Key, pCredentail->KeyLength);
+ }
+ }
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ RtmpOSFileWrite(file_w, pTempStr, strlen(pTempStr));
+ RtmpOSFileWrite(file_w, "\n", 1);
+ }
+ else
+ {
+ break;
+ }
+ }
+ RtmpOSFileClose(file_w);
+ }
+
+WriteErr:
+ if (pTempStr)
+/* kfree(pTempStr); */
+ os_free_mem(NULL, pTempStr);
+ReadErr:
+WriteFileOpenErr:
+ if (cfgData)
+/* kfree(cfgData); */
+ os_free_mem(NULL, cfgData);
+out:
+ RtmpOSFSInfoChange(&osFSInfo, FALSE);
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscWriteConfToDatFile\n"));
+ return;
+}
+
+#ifdef CONFIG_AP_SUPPORT
+void WscWriteConfToAR9File(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR CurOpMode)
+{
+ PSTRING fileName = NULL;
+ RTMP_OS_FD file_w;
+ RTMP_OS_FS_INFO osFSInfo;
+ INT offset = 0;
+ INT datoffset = 0;
+ PSTRING pTempStr = 0;
+ PSTRING pDatStr = 0;
+#ifdef CONFIG_AP_SUPPORT
+ INT index = 0;
+ UCHAR apidx = MAIN_MBSSID;
+#endif /* CONFIG_AP_SUPPORT */
+ PWSC_CTRL pWscControl = NULL;
+ PWSC_CREDENTIAL pCredentail = NULL;
+ STRING WepKeyName[MAX_WEPKEYNAME_LEN] = {0};
+ STRING WepKeyFormatName[MAX_WEPKEYTYPE_LEN] = {0};
+ INT tempStrLen = 0;
+ STRING item_str[10] = {0};
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> WscWriteConfToAR9File\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl;
+ fileName = "/var/wps_profile.dat";
+
+ snprintf((PSTRING) WepKeyName, sizeof(WepKeyName), "Key%dStr1=", pAd->ApCfg.MBSSID[MAIN_MBSSID].DefaultKeyId+1);
+ snprintf((PSTRING) WepKeyFormatName, sizeof(WepKeyFormatName), "Key%dType=", pAd->ApCfg.MBSSID[MAIN_MBSSID].DefaultKeyId+1);
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ RtmpOSFSInfoChange(&osFSInfo, TRUE);
+ file_w = RtmpOSFileOpen(fileName, O_WRONLY|O_CREAT, 0);
+ if (IS_FILE_OPEN_ERR(file_w))
+ {
+ goto WriteFileOpenErr;
+ }
+ else
+ {
+ os_alloc_mem(NULL, (UCHAR **)&pTempStr, 512);
+ if (!pTempStr)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("pTempStr kmalloc fail. (512)\n"));
+ RtmpOSFileClose(file_w);
+ goto WriteErr;
+ }
+ os_alloc_mem(NULL, (UCHAR **)&pDatStr, 4096);
+ if (!pDatStr)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("pDatStr kmalloc fail. (4096)\n"));
+ RtmpOSFileClose(file_w);
+ goto WriteErr;
+ }
+
+ /*for (;;) */
+ {
+ NdisZeroMemory(pTempStr, 512);
+ NdisZeroMemory(pDatStr, 4096);
+ {
+ {
+ NdisZeroMemory(item_str, 10);
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ snprintf(item_str, sizeof(item_str), "SSID%d", (apidx + 1));
+ {
+ NdisMoveMemory(pTempStr, item_str, strlen(item_str));
+ offset = strlen(pTempStr);
+ NdisMoveMemory(pTempStr + offset, "=", 1);
+ offset += 1;
+ NdisMoveMemory(pTempStr + offset, pAd->ApCfg.MBSSID[apidx].Ssid, pAd->ApCfg.MBSSID[apidx].SsidLen);
+ offset += pAd->ApCfg.MBSSID[apidx].SsidLen;
+ NdisMoveMemory(pTempStr + offset, "\n", 1);
+ offset += 1;
+ }
+ NdisZeroMemory(item_str, 10);
+ }
+ }
+ NdisMoveMemory(pDatStr,pTempStr,offset);
+ datoffset += offset;
+
+ {
+ offset=0;
+ NdisZeroMemory(pTempStr, 512);
+ snprintf(pTempStr, 512, "AuthMode=");
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ for (index = 0; index < pAd->ApCfg.BssidNum; index++)
+ {
+ if (pAd->ApCfg.MBSSID[index].SsidLen)
+ {
+ if (index == 0)
+ snprintf(pTempStr, 512, "%s%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].AuthMode));
+ else
+ snprintf(pTempStr, 512, "%s;%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].AuthMode));
+ }
+ }
+ snprintf(pTempStr, 512, "%s\n", pTempStr);
+ offset=strlen(pTempStr);
+ NdisMoveMemory(pDatStr+datoffset,pTempStr,offset);
+ datoffset += offset;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+ {
+ offset=0;
+ NdisZeroMemory(pTempStr, 512);
+ snprintf(pTempStr, 512, "EncrypType=");
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ for (index = 0; index < pAd->ApCfg.BssidNum; index++)
+ {
+ if (index == 0)
+ snprintf(pTempStr, 512, "%s%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].WepStatus));
+ else
+ snprintf(pTempStr, 512, "%s;%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].WepStatus));
+ }
+ snprintf(pTempStr, 512, "%s\n", pTempStr);
+ offset=strlen(pTempStr);
+ NdisMoveMemory(pDatStr+datoffset,pTempStr,offset);
+ datoffset += offset;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+ {
+ offset=0;
+ NdisZeroMemory(pTempStr, 512);
+ NdisZeroMemory(item_str, 10);
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ snprintf(item_str, sizeof(item_str), "WPAPSK%d", (apidx + 1));
+ /*if (rtstrstr(pTempStr, item_str)) */
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl;
+ NdisMoveMemory(pTempStr, item_str, strlen(item_str));
+ offset = strlen(pTempStr);
+ NdisMoveMemory(pTempStr + offset, "=", 1);
+ offset += 1;
+ NdisMoveMemory(pTempStr + offset, pWscControl->WpaPsk, pWscControl->WpaPskLen);
+ offset += pWscControl->WpaPskLen;
+ NdisMoveMemory(pTempStr + offset, "\n", 1);
+ offset += 1;
+ }
+ NdisZeroMemory(item_str, 10);
+ }
+ NdisMoveMemory(pDatStr+datoffset,pTempStr,offset);
+ datoffset += offset;
+ }
+
+ {
+ offset=0;
+ NdisZeroMemory(pTempStr, 512);
+ snprintf(pTempStr, 512, "WscConfMode=");
+#ifdef CONFIG_AP_SUPPORT
+ for (index = 0; index < pAd->ApCfg.BssidNum; index++)
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[index].WscControl;
+ if (index == 0)
+ snprintf(pTempStr, 512, "%s%d", pTempStr, pWscControl->WscConfMode);
+ else
+ snprintf(pTempStr, 512, "%s;%d", pTempStr, pWscControl->WscConfMode);
+ }
+ snprintf(pTempStr, 512, "%s\n", pTempStr);
+ offset=strlen(pTempStr);
+ NdisMoveMemory(pDatStr+datoffset,pTempStr,offset);
+ datoffset += offset;
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+ {
+ offset=0;
+ NdisZeroMemory(pTempStr, 512);
+ snprintf(pTempStr, 512, "WscConfStatus=");
+#ifdef CONFIG_AP_SUPPORT
+ for (index = 0; index < pAd->ApCfg.BssidNum; index++)
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[index].WscControl;
+ if (index == 0)
+ snprintf(pTempStr, 512, "%s%d", pTempStr, pWscControl->WscConfStatus);
+ else
+ snprintf(pTempStr, 512, "%s;%d", pTempStr, pWscControl->WscConfStatus);
+ }
+ snprintf(pTempStr, 512, "%s\n", pTempStr);
+ offset=strlen(pTempStr);
+ NdisMoveMemory(pDatStr+datoffset,pTempStr,offset);
+ datoffset += offset;
+#endif /* CONFIG_AP_SUPPORT */
+ }
+
+ {
+ offset=0;
+ NdisZeroMemory(pTempStr, 512);
+ snprintf(pTempStr, 512, "DefaultKeyID=");
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ for (index = 0; index < pAd->ApCfg.BssidNum; index++)
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[index].WscControl;
+ if (index == 0)
+ snprintf(pTempStr, 512, "%s%d", pTempStr, pAd->ApCfg.MBSSID[apidx].DefaultKeyId+1);
+ else
+ snprintf(pTempStr, 512, "%s;%d", pTempStr, pAd->ApCfg.MBSSID[apidx].DefaultKeyId+1);
+ }
+ snprintf(pTempStr, 512, "%s\n", pTempStr);
+ offset=strlen(pTempStr);
+ NdisMoveMemory(pDatStr+datoffset,pTempStr,offset);
+ datoffset += offset;
+ }
+
+#endif /* CONFIG_AP_SUPPORT */
+ }
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ for (index = 1; index <= 4; index++)
+ {
+ snprintf(WepKeyFormatName, sizeof(WepKeyFormatName), "Key%dType=", index);
+ /*if (rtstrstr(pTempStr, WepKeyFormatName)) */
+ {
+ NdisZeroMemory(pTempStr, 512);
+ offset=0;
+ NdisMoveMemory(pTempStr, WepKeyFormatName, strlen(WepKeyFormatName));
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ if (pAd->ApCfg.MBSSID[MAIN_MBSSID].WepStatus == Ndis802_11WEPEnabled)
+ {
+ pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0];
+ if ((pCredentail->KeyLength == 5) ||
+ (pCredentail->KeyLength == 13))
+ snprintf(pTempStr, 512, "%s1", pTempStr); /* ASCII */
+ else
+ snprintf(pTempStr, 512, "%s0", pTempStr); /* Hex */
+ }
+ if (apidx < (pAd->ApCfg.BssidNum - 1))
+ snprintf(pTempStr, 512, "%s;", pTempStr);
+ }
+ snprintf(pTempStr, 512, "%s\n", pTempStr);
+ offset=strlen(pTempStr);
+ NdisMoveMemory(pDatStr+datoffset,pTempStr,offset);
+ datoffset += offset;
+ }
+
+ snprintf(WepKeyName, sizeof(WepKeyName), "Key%dStr=", index);
+ /*if (rtstrstr(pTempStr, WepKeyName)) */
+ {
+ NdisZeroMemory(pTempStr, 512);
+ offset=0;
+ NdisMoveMemory(pTempStr, WepKeyName, strlen(WepKeyName));
+ tempStrLen = strlen(pTempStr);
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0];
+ if (pCredentail->KeyLength)
+ {
+ NdisMoveMemory(pTempStr + tempStrLen, pCredentail->Key, pCredentail->KeyLength);
+ tempStrLen = strlen(pTempStr);
+ }
+ if (apidx < (pAd->ApCfg.BssidNum - 1))
+ NdisMoveMemory(pTempStr + tempStrLen, ";", 1);
+ tempStrLen += 1;
+ }
+ snprintf(pTempStr, 512, "%s\n", pTempStr);
+ offset=strlen(pTempStr);
+ NdisMoveMemory(pDatStr+datoffset,pTempStr,offset);
+ datoffset += offset;
+ }
+
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ snprintf(WepKeyName, sizeof(WepKeyName), "Key%dStr%d=", index, (apidx + 1));
+ if ((pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11WEPEnabled))
+ {
+ NdisZeroMemory(pTempStr, 512);
+ NdisMoveMemory(pTempStr, WepKeyName, strlen(WepKeyName));
+ tempStrLen = strlen(pTempStr);
+ pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0];
+ NdisMoveMemory(pTempStr + tempStrLen, pCredentail->Key, pCredentail->KeyLength);
+ NdisMoveMemory(pTempStr + tempStrLen+pCredentail->KeyLength, "\n", 1);
+ }
+ offset=tempStrLen+pCredentail->KeyLength+1;
+ NdisMoveMemory(pDatStr+datoffset,pTempStr,offset);
+ datoffset += offset;
+ }
+ }
+ }
+#endif /* CONFIG_AP_SUPPORT */
+ RtmpOSFileWrite(file_w, pDatStr, datoffset);
+ /*RtmpOSFileWrite(file_w, "\n", 1); */
+ }
+ }
+ RtmpOSFileClose(file_w);
+ }
+
+WriteErr:
+ if (pTempStr)
+/* kfree(pTempStr); */
+ os_free_mem(NULL, pTempStr);
+ if (pDatStr)
+/* kfree(pDatStr); */
+ os_free_mem(NULL, pDatStr);
+
+WriteFileOpenErr:
+ RtmpOSFSInfoChange(&osFSInfo, FALSE);
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WscWriteConfToAR9File\n"));
+ return;
+}
+#endif/*CONFIG_AP_SUPPORT*/
+
+static INT wsc_write_dat_file_thread (
+ IN ULONG Context)
+{
+ RTMP_OS_TASK *pTask;
+ RTMP_ADAPTER *pAd;
+ int Status = 0;
+
+ pTask = (RTMP_OS_TASK *)Context;
+ pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask);
+
+ if (pAd == NULL)
+ return 0;
+
+ RtmpOSTaskCustomize(pTask);
+
+ while (pTask && !RTMP_OS_TASK_IS_KILLED(pTask))
+ {
+ RTMPusecDelay(2000);
+
+ if (RtmpOSTaskWait(pAd, pTask, &Status) == FALSE)
+ {
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+ break;
+ }
+
+ if (Status != 0)
+ break;
+
+#ifdef RTMP_MAC_USB
+ /* device had been closed */
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ break;
+#endif /* RTMP_MAC_USB */
+
+ if (pAd->pWscElme && (pAd->pWscElme->MsgLen != 0))
+ {
+ MLME_QUEUE_ELEM *pElme;
+ os_alloc_mem(pAd, (UCHAR **)&pElme, sizeof(MLME_QUEUE_ELEM));
+ if (pElme)
+ {
+ NdisZeroMemory(pElme, sizeof(MLME_QUEUE_ELEM));
+ RTMP_SEM_LOCK(&pAd->WscElmeLock);
+ NdisMoveMemory(pElme, pAd->pWscElme, sizeof(MLME_QUEUE_ELEM));
+ pAd->pWscElme->MsgLen = 0;
+ NdisZeroMemory(pAd->pWscElme->Msg, MGMT_DMA_BUFFER_SIZE);
+ RTMP_SEM_UNLOCK(&pAd->WscElmeLock);
+ WpsSmProcess(pAd, pElme);
+ os_free_mem(NULL, pElme);
+ }
+ }
+
+ if (pAd->WriteWscCfgToDatFile != 0xFF)
+ {
+ UCHAR CurOpMode = AP_MODE;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ WscWriteConfToDatFile(pAd, CurOpMode);
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef INF_AR9
+#ifdef AR9_MAPI_SUPPORT
+ WscWriteConfToAR9File(pAd, CurOpMode);
+#endif /*AR9_MAPI_SUPPORT*/
+#endif /* INF_AR9 */
+#endif/*CONFIG_AP_SUPPORT*/
+ pAd->WriteWscCfgToDatFile = 0xFF;
+ }
+ }
+
+ if (pTask)
+ RtmpOSTaskNotifyToExit(pTask);
+
+ return 0;
+}
+
+
+/*
+ * This kernel thread init in the probe fucntion, so we should kill it when do remove module.
+ */
+BOOLEAN WscThreadExit(RTMP_ADAPTER *pAd)
+{
+ INT ret;
+
+ /*
+ This kernel thread init in the probe fucntion, so kill it when do remove module.
+ */
+ ret = RtmpOSTaskKill(&pAd->wscTask);
+ if (ret == NDIS_STATUS_FAILURE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("kill wsc task failed!\n"));
+ }
+
+ if (pAd->pHmacData)
+ {
+ os_free_mem(NULL, pAd->pHmacData);
+ pAd->pHmacData = NULL;
+ }
+ if (pAd->pWscElme)
+ {
+ os_free_mem(NULL, pAd->pWscElme);
+ pAd->pWscElme = NULL;
+ }
+ NdisFreeSpinLock(&pAd->WscElmeLock);
+#ifdef CONFIG_AP_SUPPORT
+ if ((pAd->OpMode == OPMODE_AP)
+ )
+ {
+ INT ap_idx;
+ UCHAR MaxBssidNum = MAX_MBSSID_NUM(pAd);
+
+ for (ap_idx = 0; ap_idx < MaxBssidNum; ap_idx++)
+ {
+ BOOLEAN Cancelled;
+ PWSC_CTRL pWpsCtrl = &pAd->ApCfg.MBSSID[ap_idx].WscControl;
+ WscStop(pAd, FALSE, pWpsCtrl);
+ //sync by 7610
+#ifdef WSC_V2_SUPPORT
+ if (pWpsCtrl->WscSetupLockTimerRunning)
+ {
+ pWpsCtrl->WscSetupLockTimerRunning = FALSE;
+ RTMPCancelTimer(&pWpsCtrl->WscSetupLockTimer, &Cancelled);
+ }
+#endif /* WSC_V2_SUPPORT */
+
+ pWpsCtrl->WscRxBufLen = 0;
+ if (pWpsCtrl->pWscRxBuf)
+ {
+ os_free_mem(pAd, pWpsCtrl->pWscRxBuf);
+ pWpsCtrl->pWscRxBuf = NULL;
+ }
+ pWpsCtrl->WscTxBufLen = 0;
+ if (pWpsCtrl->pWscTxBuf)
+ {
+ os_free_mem(pAd, pWpsCtrl->pWscTxBuf);
+ pWpsCtrl->pWscTxBuf = NULL;
+ }
+#ifdef WSC_V2_SUPPORT
+ if (pWpsCtrl->WscV2Info.ExtraTlv.pTlvData)
+ {
+ os_free_mem(NULL, pWpsCtrl->WscV2Info.ExtraTlv.pTlvData);
+ pWpsCtrl->WscV2Info.ExtraTlv.pTlvData = NULL;
+ }
+#endif // WSC_V2_SUPPORT //
+ WscClearPeerList(&pWpsCtrl->WscPeerList);
+ NdisFreeSpinLock(&pWpsCtrl->WscPeerListSemLock);
+ }
+#ifdef APCLI_SUPPORT
+ {
+ INT index;
+ WscStop(pAd, TRUE, &pAd->ApCfg.ApCliTab[BSS0].WscControl);
+
+ for(index = 0; index < MAX_APCLI_NUM; index++)
+ {
+ PWSC_CTRL pWpsCtrl = &pAd->ApCfg.ApCliTab[index].WscControl;
+
+ pWpsCtrl->WscTxBufLen = 0;
+ if (pWpsCtrl->pWscTxBuf)
+ os_free_mem(pAd, pWpsCtrl->pWscTxBuf);
+ pWpsCtrl->WscRxBufLen = 0;
+ if (pWpsCtrl->pWscRxBuf)
+ os_free_mem(pAd, pWpsCtrl->pWscRxBuf);
+ WscClearPeerList(&pWpsCtrl->WscPeerList);
+ NdisFreeSpinLock(&pWpsCtrl->WscPeerListSemLock);
+ }
+ }
+#endif // APCLI_SUPPORT //
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /* WSC hardware push button function 0811 */
+ WSC_HDR_BTN_Stop(pAd);
+ return TRUE;
+}
+
+
+/*
+ * This kernel thread init in the probe function.
+ */
+NDIS_STATUS WscThreadInit(RTMP_ADAPTER *pAd)
+{
+ NDIS_STATUS status = NDIS_STATUS_FAILURE;
+ RTMP_OS_TASK *pTask;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-->WscThreadInit()\n"));
+
+ pTask = &pAd->wscTask;
+
+
+ RTMP_OS_TASK_INIT(pTask, "RtmpWscTask", pAd);
+ status = RtmpOSTaskAttach(pTask, wsc_write_dat_file_thread, (ULONG)&pAd->wscTask);
+ if (status == NDIS_STATUS_SUCCESS)
+ {
+ os_alloc_mem(NULL, &pAd->pHmacData, sizeof(CHAR)*(2048));
+ if (pAd->pHmacData == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Wsc HmacData memory alloc failed!\n"));
+ status = FALSE;
+ }
+ NdisAllocateSpinLock(pAd, &pAd->WscElmeLock);
+ os_alloc_mem(NULL, (UCHAR **)&pAd->pWscElme, sizeof(MLME_QUEUE_ELEM));
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("<--WscThreadInit(), status=%d!\n", status));
+
+ return status;
+}
+
+
+/* WSC hardware push button function 0811 */
+/*
+========================================================================
+Routine Description:
+ Initialize the PUSH PUTTION Check Module.
+
+Arguments:
+ ad_p - WLAN control block pointer
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID WSC_HDR_BTN_Init(
+ IN PRTMP_ADAPTER pAd)
+{
+ pAd->CommonCfg.WscHdrPshBtnCheckCount = 0;
+} /* End of WSC_HDR_BTN_Init */
+
+
+/*
+========================================================================
+Routine Description:
+ Stop the PUSH PUTTION Check Module.
+
+Arguments:
+ ad_p - WLAN control block pointer
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID WSC_HDR_BTN_Stop(
+ IN PRTMP_ADAPTER pAd)
+{
+ pAd->CommonCfg.WscHdrPshBtnCheckCount = 0;
+} /* End of WSC_HDR_BTN_Stop */
+
+
+/*
+========================================================================
+Routine Description:
+ Start the PUSH PUTTION Check thread.
+
+Arguments:
+ *Context - WLAN control block pointer
+
+Return Value:
+ 0 - terminate the thread successfully
+
+Note:
+========================================================================
+*/
+#ifdef CONFIG_AP_SUPPORT
+extern INT Set_AP_WscMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+extern INT Set_AP_WscGetConf_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+#endif /* CONFIG_AP_SUPPORT */
+
+/*#ifdef CONFIG_STA_SUPPORT */
+
+VOID WSC_HDR_BTN_CheckHandler(
+ IN PRTMP_ADAPTER pAd)
+{
+ POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
+ BOOLEAN flg_pressed;
+
+#ifdef MT7601
+ if (IS_MT7601(pAd))
+ {
+ MT7601_WSC_HDR_BTN_MR_PRESS_FLG_GET(pAd, flg_pressed);
+ }
+ else
+#endif /* MT7601 */
+ WSC_HDR_BTN_MR_PRESS_FLG_GET(pAd, flg_pressed);
+
+ if (flg_pressed)
+ {
+ /* the button is pressed */
+ if (pAd->CommonCfg.WscHdrPshBtnCheckCount == WSC_HDR_BTN_CONT_TIMES)
+ {
+ /* we only handle once until the button is released */
+ pAd->CommonCfg.WscHdrPshBtnCheckCount = 0;
+
+ /* execute WSC PBC function */
+ DBGPRINT(RT_DEBUG_ERROR, ("wsc> execute WSC PBC...\n"));
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
+ {
+ pObj->ioctl_if = 0;
+ Set_AP_WscMode_Proc(pAd, (PUCHAR)"2"); /* 2: PBC */
+ Set_AP_WscGetConf_Proc(pAd, (PUCHAR)"1"); /* 1: Trigger */
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ return;
+ }
+
+ pAd->CommonCfg.WscHdrPshBtnCheckCount ++;
+ }
+ else
+ {
+ /* the button is released */
+ pAd->CommonCfg.WscHdrPshBtnCheckCount = 0;
+ }
+}
+
+#ifdef WSC_LED_SUPPORT
+/* */
+/* Support WPS LED mode (mode 7, mode 8 and mode 9). */
+/* Ref: User Feedback (page 80, WPS specification 1.0) */
+/* */
+BOOLEAN WscSupportWPSLEDMode(
+ IN PRTMP_ADAPTER pAd)
+{
+ if ((LED_MODE(pAd) == WPS_LED_MODE_7) ||
+ (LED_MODE(pAd) == WPS_LED_MODE_8) ||
+ (LED_MODE(pAd) == WPS_LED_MODE_9) ||
+ (LED_MODE(pAd) == WPS_LED_MODE_11) ||
+ (LED_MODE(pAd) == WPS_LED_MODE_12)
+#ifdef CONFIG_WIFI_LED_SUPPORT
+ ||(LED_MODE(pAd) == WPS_LED_MODE_SHARE)
+#endif /* CONFIG_WIFI_LED_SUPPORT */
+ )
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Support WPS LED mode (The WPS LED mode = %d).\n",
+ __FUNCTION__, LED_MODE(pAd)));
+ return TRUE; /* Support WPS LED mode. */
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Not support WPS LED mode (The WPS LED mode = %d).\n",
+ __FUNCTION__, LED_MODE(pAd)));
+ return FALSE; /* Not support WPS LED mode. */
+ }
+}
+
+BOOLEAN WscSupportWPSLEDMode10(
+ IN PRTMP_ADAPTER pAd)
+{
+ if ((LED_MODE(pAd) == WPS_LED_MODE_10)){
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Support WPS LED mode (The WPS LED mode = %d).\n",
+ __FUNCTION__, LED_MODE(pAd)));
+ return TRUE; /*Support WPS LED mode 10. */
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Not support WPS LED mode (The WPS LED mode = %d).\n",
+ __FUNCTION__, LED_MODE(pAd)));
+ return FALSE; /* Not support WPS LED mode 10. */
+ }
+}
+
+/* */
+/* Whether the WPS AP has security setting or not. */
+/* Note that this function is valid only after the WPS handshaking. */
+/* */
+BOOLEAN WscAPHasSecuritySetting(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl)
+{
+ BOOLEAN bAPHasSecuritySetting = FALSE;
+ UCHAR currentIdx = MAIN_MBSSID;
+
+#ifdef CONFIG_AP_SUPPORT
+ currentIdx = (pWscControl->EntryIfIdx & 0x0F);
+#endif /* CONFIG_AP_SUPPORT */
+
+ switch (pWscControl->WscProfile.Profile[currentIdx].EncrType)
+ {
+ case WSC_ENCRTYPE_NONE:
+ {
+ bAPHasSecuritySetting = FALSE;
+ break;
+ }
+
+ case WSC_ENCRTYPE_WEP:
+ case WSC_ENCRTYPE_TKIP:
+ case (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES):
+ case WSC_ENCRTYPE_AES:
+ {
+ bAPHasSecuritySetting = TRUE;
+ break;
+ }
+
+ default:
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Incorrect encryption types (%d)\n",
+ __FUNCTION__, pWscControl->WscProfile.Profile[currentIdx].EncrType));
+ ASSERT(FALSE);
+ break;
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: WSC Entryption Type = %d\n",
+ __FUNCTION__, pWscControl->WscProfile.Profile[currentIdx].EncrType));
+
+ return bAPHasSecuritySetting;
+}
+
+
+/* */
+/* After the NIC connects with a WPS AP or not, */
+/* the WscLEDTimer timer controls the LED behavior according to LED mode. */
+/* */
+VOID WscLEDTimer(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pWscControl->pAd;
+ UCHAR WPSLEDStatus = 0;
+
+ /* WPS LED mode 7, 8, 11 and 12. */
+ if ((LED_MODE(pAd) == WPS_LED_MODE_7) ||
+ (LED_MODE(pAd) == WPS_LED_MODE_8) ||
+ (LED_MODE(pAd) == WPS_LED_MODE_11) ||
+ (LED_MODE(pAd) == WPS_LED_MODE_12))
+ {
+ WPSLEDStatus = LED_WPS_TURN_LED_OFF;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Turn off the WPS successful LED pattern.\n", __FUNCTION__));
+ }
+ else if ((LED_MODE(pAd) == WPS_LED_MODE_9) /* WPS LED mode 9. */
+#ifdef CONFIG_WIFI_LED_SUPPORT
+ || (LED_MODE(pAd) == WPS_LED_MODE_SHARE)
+#endif /* CONFIG_WIFI_LED_SUPPORT */
+ )
+ {
+ switch (pWscControl->WscLEDMode) /* Last WPS LED state. */
+ {
+
+
+ /* Turn off the blue LED after 300 seconds. */
+ case LED_WPS_SUCCESS:
+ WPSLEDStatus = LED_WPS_TURN_LED_OFF;
+
+ /* Turn on/off the WPS success LED according to AP's encryption algorithm after one second. */
+ RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_TURN_OFF_LED_TIMEOUT);
+ pWscControl->WscLEDTimerRunning = TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_SUCCESS => LED_WPS_TURN_LED_OFF\n", __FUNCTION__));
+ break;
+
+ /* After turn off the blue LED for one second. */
+ /* AP uses an encryption algorithm: */
+ /* a) YES: Turn on the blue LED. */
+ /* b) NO: Turn off the blue LED. */
+ case LED_WPS_TURN_LED_OFF:
+ if ((pWscControl->WscState == WSC_STATE_OFF) &&
+ (pWscControl->WscStatus == STATUS_WSC_CONFIGURED))
+ {
+ if (WscAPHasSecuritySetting(pAd, pWscControl) == TRUE) /* The NIC connects with an AP using an encryption algorithm. */
+ {
+ /* Turn WPS success LED. */
+ WPSLEDStatus = LED_WPS_TURN_ON_BLUE_LED;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_TURN_LED_OFF => LED_WPS_TURN_ON_BLUE_LED\n", __FUNCTION__));
+ }
+ else /* The NIC connects with an AP using OPEN-NONE. */
+ {
+ /* Turn off the WPS LED. */
+ WPSLEDStatus = LED_WPS_TURN_LED_OFF;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_TURN_LED_OFF => LED_WPS_TURN_LED_OFF\n", __FUNCTION__));
+ }
+ }
+ break;
+
+ /* Turn off the amber LED after 15 seconds. */
+ case LED_WPS_ERROR:
+ WPSLEDStatus = LED_WPS_TURN_LED_OFF; /* Turn off the WPS LED. */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_ERROR/LED_WPS_SESSION_OVERLAP_DETECTED => LED_WPS_TURN_LED_OFF\n", __FUNCTION__));
+ break;
+ /* Turn off the amber LED after ~3 seconds. */
+ case LED_WPS_SESSION_OVERLAP_DETECTED:
+ WPSLEDStatus = LED_WPS_TURN_LED_OFF; /* Turn off the WPS LED. */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_SESSION_OVERLAP_DETECTED => LED_WPS_TURN_LED_OFF\n", __FUNCTION__));
+ break;
+
+ default:
+ /* do nothing. */
+ break;
+ }
+
+ if (WPSLEDStatus)
+ RTMPSetLED(pAd, WPSLEDStatus);
+ }
+ else
+ {
+ /* do nothing. */
+ }
+}
+
+
+VOID WscSkipTurnOffLEDTimer(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext;
+
+ /* Allow the NIC to turn off the WPS LED again. */
+ pWscControl->bSkipWPSTurnOffLED = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: Allow the NIC to turn off the WPS LED again.\n", __FUNCTION__));
+}
+
+#endif /* WSC_LED_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+VOID WscUpdatePortCfgTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext;
+ PRTMP_ADAPTER pAd = NULL;
+ BOOLEAN /* bRestart = TRUE,*/ bEnrollee = TRUE;
+ PWSC_CREDENTIAL pCredential = NULL;
+ PMULTISSID_STRUCT pMbss = NULL;
+
+ if (pWscControl == NULL)
+ return;
+
+ pCredential = (PWSC_CREDENTIAL) &pWscControl->WscProfile.Profile[0];
+ pAd = (PRTMP_ADAPTER)pWscControl->pAd;
+
+ if (pAd == NULL)
+ return;
+
+ pMbss = &pAd->ApCfg.MBSSID[pWscControl->EntryIfIdx & 0x0F];
+ if (WscGetAuthMode(pCredential->AuthType) == pMbss->AuthMode &&
+ WscGetWepStatus(pCredential->EncrType) == pMbss->WepStatus &&
+ NdisEqualMemory(pMbss->Ssid, pCredential->SSID.Ssid, pMbss->SsidLen) &&
+ NdisEqualMemory(pWscControl->WpaPsk, pCredential->Key, pCredential->KeyLength))
+ {
+ return;
+ }
+
+ if (pWscControl->WscProfile.ApplyProfileIdx & 0x8000)
+ bEnrollee = FALSE;
+ WscWriteConfToPortCfg(pAd,
+ pWscControl,
+ &pWscControl->WscProfile.Profile[0],
+ bEnrollee);
+ pWscControl->WscProfile.ApplyProfileIdx &= 0x7FFF;
+ {
+ pAd->WriteWscCfgToDatFile = (pWscControl->EntryIfIdx & 0x0F);
+ APStop(pAd);
+ APStartUp(pAd);
+ }
+
+/*#ifdef KTHREAD_SUPPORT */
+/* WAKE_UP(&(pAd->wscTask)); */
+/*#else */
+/* RTMP_SEM_EVENT_UP(&(pAd->wscTask.taskSema)); */
+/*#endif */
+ RtmpOsTaskWakeUp(&(pAd->wscTask));
+
+ return;
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+VOID WscCheckPeerDPID(
+ IN PRTMP_ADAPTER pAd,
+ IN PFRAME_802_11 Fr,
+ IN PUCHAR eid_data,
+ IN INT eid_len)
+{
+ WSC_IE *pWscIE;
+ PUCHAR pData = NULL;
+ INT Len = 0;
+ USHORT DevicePasswordID;
+ PWSC_CTRL pWscCtrl = NULL;
+
+ pData = eid_data + 4;
+ Len = eid_len - 4;
+ while (Len > 0)
+ {
+ WSC_IE WscIE;
+ NdisMoveMemory(&WscIE, pData, sizeof(WSC_IE));
+ /* Check for WSC IEs*/
+ pWscIE = &WscIE;
+
+ /* Check for device password ID, PBC = 0x0004*/
+ if (be2cpu16(pWscIE->Type) == WSC_ID_DEVICE_PWD_ID)
+ {
+ /* Found device password ID*/
+ NdisMoveMemory(&DevicePasswordID, pData + 4, sizeof(DevicePasswordID));
+ DevicePasswordID = be2cpu16(DevicePasswordID);
+ DBGPRINT(RT_DEBUG_INFO, ("%s : DevicePasswordID = 0x%04x\n", __FUNCTION__, DevicePasswordID));
+ if (DevicePasswordID == DEV_PASS_ID_PBC) /* Check for PBC value*/
+ {
+ WscPBC_DPID_FromSTA(pAd, Fr->Hdr.Addr2);
+ hex_dump("PBC STA:", Fr->Hdr.Addr2, MAC_ADDR_LEN);
+ DBGPRINT(RT_DEBUG_TRACE, ("\n"));
+ }
+ else if (DevicePasswordID == DEV_PASS_ID_PIN)
+ {
+#ifdef CONFIG_AP_SUPPORT
+ if ((pAd->OpMode == OPMODE_AP)
+ )
+ {
+ UCHAR ap_idx = 0;
+ for (ap_idx = 0; ap_idx < pAd->ApCfg.BssidNum; ap_idx++)
+ {
+ if (NdisEqualMemory(Fr->Hdr.Addr1, pAd->ApCfg.MBSSID[ap_idx].Bssid, MAC_ADDR_LEN))
+ break;
+ }
+
+ if (ap_idx >= pAd->ApCfg.BssidNum)
+ {
+ break;
+ }
+
+ pWscCtrl = &pAd->ApCfg.MBSSID[ap_idx].WscControl;
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+ /*
+ WSC 2.0 STA will send probe request with WPS IE anyway.
+ Do NOT add this STA to WscPeerList after AP is triggered to do PBC.
+ */
+ if (pWscCtrl &&
+ (!pWscCtrl->bWscTrigger || (pWscCtrl->WscMode != WSC_PBC_MODE)))
+ {
+ RTMP_SEM_LOCK(&pWscCtrl->WscPeerListSemLock);
+ WscInsertPeerEntryByMAC(&pWscCtrl->WscPeerList, Fr->Hdr.Addr2);
+ RTMP_SEM_UNLOCK(&pWscCtrl->WscPeerListSemLock);
+ }
+ }
+
+ break;
+ }
+
+
+ /* Set the offset and look for PBC information*/
+ /* Since Type and Length are both short type, we need to offset 4, not 2*/
+ pData += (be2cpu16(pWscIE->Length) + 4);
+ Len -= (be2cpu16(pWscIE->Length) + 4);
+ }
+}
+
+VOID WscClearPeerList(
+ IN PLIST_HEADER pWscEnList)
+{
+ PLIST_ENTRY pEntry = NULL;
+
+ pEntry = pWscEnList->pHead;
+
+ while (pEntry != NULL)
+ {
+ removeHeadList(pWscEnList);
+ os_free_mem(NULL, pEntry);
+ pEntry = pWscEnList->pHead;
+ }
+
+ return;
+}
+
+PWSC_PEER_ENTRY WscFindPeerEntry(
+ PLIST_HEADER pWscEnList,
+ IN PUCHAR pMacAddr)
+{
+ PWSC_PEER_ENTRY pPeerEntry = NULL;
+ PLIST_ENTRY pListEntry = NULL;
+
+ pListEntry = pWscEnList->pHead;
+ pPeerEntry = (PWSC_PEER_ENTRY)pListEntry;
+ while (pPeerEntry != NULL)
+ {
+ if (NdisEqualMemory(pPeerEntry->mac_addr, pMacAddr, MAC_ADDR_LEN))
+ return pPeerEntry;
+ pListEntry = pListEntry->pNext;
+ pPeerEntry = (PWSC_PEER_ENTRY)pListEntry;
+ }
+
+ return NULL;
+}
+
+VOID WscInsertPeerEntryByMAC(
+ PLIST_HEADER pWscEnList,
+ IN PUCHAR pMacAddr)
+{
+ PWSC_PEER_ENTRY pWscPeer = NULL;
+
+ pWscPeer = WscFindPeerEntry(pWscEnList, pMacAddr);
+ if (pWscPeer)
+ {
+ NdisGetSystemUpTime(&pWscPeer->receive_time);
+ }
+ else
+ {
+ os_alloc_mem(NULL, (UCHAR **)&pWscPeer, sizeof(WSC_PEER_ENTRY));
+ if (pWscPeer)
+ {
+ NdisZeroMemory(pWscPeer, sizeof(WSC_PEER_ENTRY));
+ pWscPeer->pNext = NULL;
+ NdisMoveMemory(pWscPeer->mac_addr, pMacAddr, MAC_ADDR_LEN);
+ NdisGetSystemUpTime(&pWscPeer->receive_time);
+ insertTailList(pWscEnList, (PLIST_ENTRY)pWscPeer);
+ }
+ ASSERT(pWscPeer != NULL);
+ }
+}
+
+#ifdef CONFIG_AP_SUPPORT
+INT WscApShowPeerList(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTRING arg)
+{
+ UCHAR ApIdx = 0;
+ PWSC_CTRL pWscControl = NULL;
+ PWSC_PEER_ENTRY pPeerEntry = NULL;
+ PLIST_ENTRY pListEntry = NULL;
+ PLIST_HEADER pWscEnList = NULL;
+
+ for (ApIdx = 0; ApIdx < pAd->ApCfg.BssidNum; ApIdx++)
+ {
+ pWscControl = &pAd->ApCfg.MBSSID[ApIdx].WscControl;
+ pWscEnList = &pWscControl->WscPeerList;
+
+ if (pWscEnList->size != 0)
+ {
+ WscMaintainPeerList(pAd, pWscControl);
+ RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock);
+ pListEntry = pWscEnList->pHead;
+ pPeerEntry = (PWSC_PEER_ENTRY)pListEntry;
+ while (pPeerEntry != NULL)
+ {
+ printk("MAC:%02x:%02x:%02x:%02x:%02x:%02x\tReveive Time:%lu\n",
+ pPeerEntry->mac_addr[0],
+ pPeerEntry->mac_addr[1],
+ pPeerEntry->mac_addr[2],
+ pPeerEntry->mac_addr[3],
+ pPeerEntry->mac_addr[4],
+ pPeerEntry->mac_addr[5],
+ pPeerEntry->receive_time);
+ pListEntry = pListEntry->pNext;
+ pPeerEntry = (PWSC_PEER_ENTRY)pListEntry;
+ }
+ RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock);
+ }
+ printk("\n");
+ }
+
+ return TRUE;
+}
+#endif // CONFIG_AP_SUPPORT //
+
+
+VOID WscMaintainPeerList(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWpsCtrl)
+{
+ PWSC_PEER_ENTRY pPeerEntry = NULL;
+ PLIST_ENTRY pListEntry = NULL, pTempListEntry = NULL;
+ PLIST_HEADER pWscEnList = NULL;
+ ULONG now_time = 0;
+
+ RTMP_SEM_LOCK(&pWpsCtrl->WscPeerListSemLock);
+ pWscEnList = &pWpsCtrl->WscPeerList;
+
+
+ NdisGetSystemUpTime(&now_time);
+ pListEntry = pWscEnList->pHead;
+ pPeerEntry = (PWSC_PEER_ENTRY)pListEntry;
+
+ while (pPeerEntry != NULL)
+ {
+ if (RTMP_TIME_AFTER(now_time, pPeerEntry->receive_time + (30 * OS_HZ)))
+ {
+ pTempListEntry = pListEntry->pNext;
+ delEntryList(pWscEnList, pListEntry);
+ os_free_mem(pAd, pPeerEntry);
+ pListEntry = pTempListEntry;
+ }
+ else
+ pListEntry = pListEntry->pNext;
+ pPeerEntry = (PWSC_PEER_ENTRY)pListEntry;
+ }
+
+ RTMP_SEM_UNLOCK(&pWpsCtrl->WscPeerListSemLock);
+ return;
+}
+
+VOID WscDelListEntryByMAC(
+ PLIST_HEADER pWscEnList,
+ IN PUCHAR pMacAddr)
+{
+ PLIST_ENTRY pListEntry = NULL;
+ pListEntry = (PLIST_ENTRY)WscFindPeerEntry(pWscEnList, pMacAddr);
+ if (pListEntry)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscDelListEntryByMAC : pMacAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", PRINT_MAC(pMacAddr)));
+ delEntryList(pWscEnList, pListEntry);
+ os_free_mem(NULL, pListEntry);
+ }
+}
+
+VOID WscAssignEntryMAC(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWpsCtrl)
+{
+ PWSC_PEER_ENTRY pPeerEntry = NULL;
+
+ WscMaintainPeerList(pAd, pWpsCtrl);
+
+ RTMP_SEM_LOCK(&pWpsCtrl->WscPeerListSemLock);
+ pPeerEntry = (PWSC_PEER_ENTRY)pWpsCtrl->WscPeerList.pHead;
+
+ NdisZeroMemory(pWpsCtrl->EntryAddr, MAC_ADDR_LEN);
+ if (pPeerEntry)
+ {
+ NdisMoveMemory(pWpsCtrl->EntryAddr, pPeerEntry->mac_addr, MAC_ADDR_LEN);
+ }
+ RTMP_SEM_UNLOCK(&pWpsCtrl->WscPeerListSemLock);
+}
+
+
+/*
+ Get WSC IE data from WSC Peer by Tag.
+*/
+BOOLEAN WscGetDataFromPeerByTag(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pIeData,
+ IN INT IeDataLen,
+ IN USHORT WscTag,
+ OUT PUCHAR pWscBuf,
+ OUT PUSHORT pWscBufLen)
+{
+ PUCHAR pData = pIeData;
+ INT Len = 0;
+ USHORT DataLen = 0;
+ PWSC_IE pWscIE;
+
+ Len = IeDataLen;
+
+ while (Len > 0)
+ {
+ WSC_IE WscIE;
+ NdisMoveMemory(&WscIE, pData, sizeof(WSC_IE));
+ // Check for WSC IEs
+ pWscIE = &WscIE;
+
+ if (be2cpu16(pWscIE->Type) == WscTag)
+ {
+ DataLen = be2cpu16(pWscIE->Length);
+ if (pWscBufLen)
+ *pWscBufLen = DataLen;
+ NdisMoveMemory(pWscBuf, pData + 4, DataLen);
+ return TRUE;
+ }
+
+ // Set the offset and look for next WSC Tag information
+ // Since Type and Length are both short type, we need to offset 4, not 2
+ pData += (be2cpu16(pWscIE->Length) + 4);
+ Len -= (be2cpu16(pWscIE->Length) + 4);
+ }
+
+ return FALSE;
+}
+
+#endif /* WSC_INCLUDED */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/wsc_tlv.c b/cleopatre/devkit/mt7601udrv/common/wsc_tlv.c
new file mode 100644
index 0000000000..495e71e7f0
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/wsc_tlv.c
@@ -0,0 +1,4002 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2006, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ wsc.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Lin 06-08-08 Initial
+ JuemingChen 06-10-30 Do modifications and Add APIs for AP
+*/
+
+#include "rt_config.h"
+
+#ifdef WSC_INCLUDED
+#include "wsc_tlv.h"
+
+static UCHAR Wsc_Personal_String[] = "Wi-Fi Easy and Secure Key Derivation";
+
+#define IV_ENCR_DATA_LEN_512 512
+#define IV_ENCR_DATA_LEN_144 144
+
+#define WSC_TLV_ENT(TLV_PARA) (0x00ff & TLV_PARA)
+#define WSC_TLV_BYTE1(TLV_PARA) (0x000f & TLV_PARA)
+#define WSC_TLV_BYTE2(TLV_PARA) (0x000f & (TLV_PARA >> 4))
+
+/* Global reusable buffer */
+static WSC_TLV_0B wsc_tlv_0b[]=
+{
+ {/*0,*/0},
+ /*AP Channel*/ {/*0x1001,*/ 2}, /* WSC_ID_AP_CHANNEL */
+ /*Association State*/ {/*0x1002,*/ 2}, /* WSC_ID_ASSOC_STATE */
+ /*Authentication Type*/ {/*0x1003,*/ 2}, /* WSC_ID_AUTH_TYPE */
+ /*Authentication Type Flags*/ {/*0x1004,*/ 2}, /* WSC_ID_AUTH_TYPE_FLAGS */
+ /*Authenticator*/ {/*0x1005,*/ 8}, /* WSC_ID_AUTHENTICATOR */
+ {/*0,*/0},
+ {/*0,*/0},
+ /*Config Methods*/ {/*0x1008,*/ 2}, /* WSC_ID_CONFIG_METHODS */
+ /*Configuration Error*/ {/*0x1009,*/ 2}, /* WSC_ID_CONFIG_ERROR */
+ /*Confirmation URL4*/ {/*0x100A,*/ 0x40}, /* <= 64B WSC_ID_CONF_URL4 */
+ /*Confirmation URL6*/ {/*0x100B,*/ 0x4C}, /* <= 76B WSC_ID_CONF_URL6 */
+ /*Connection Type*/ {/*0x100C,*/ 1}, /* WSC_ID_CONN_TYPE */
+ /*Connection Type Flags*/ {/*0x100D,*/ 1}, /* WSC_ID_CONN_TYPE_FLAGS */
+ /*Credential*/ {/*0x100E,*/ 0xff}, /* WSC_ID_CREDENTIAL */
+ /*Encryption Type*/ {/*0x100F,*/ 2}, /* WSC_ID_ENCR_TYPE */
+ /*Encryption Type Flags*/ {/*0x1010,*/ 2}, /* WSC_ID_ENCR_TYPE_FLAGS */
+ /*Device Name*/ {/*0x1011,*/ 0x20}, /* <= 32B WSC_ID_DEVICE_NAME */
+ /*Device Password ID*/ {/*0x1012,*/ 2}, /* WSC_ID_DEVICE_PWD_ID */
+ {/*0,*/0},
+ /*E-Hash1*/ {/*0x1014,*/ 32}, /* WSC_ID_E_HASH1 */
+ /*E-Hash2*/ {/*0x1015,*/ 32}, /* WSC_ID_E_HASH2 */
+ /*E-SNonce1*/ {/*0x1016,*/ 16}, /* WSC_ID_E_SNONCE1 */
+ /*E-SNonce2*/ {/*0x1017,*/ 16}, /* WSC_ID_E_SNONCE2 */
+ /*Encrypted Settings*/ {/*0x1018,*/ 0xff}, /* WSC_ID_ENCR_SETTINGS */
+ {/*0,*/0},
+ /*Enrollee Nonce*/ {/*0x101A,*/ 16}, /* WSC_ID_ENROLLEE_NONCE */
+ /*Feature_ID*/ {/*0x101B,*/ 4}, /* WSC_ID_FEATURE_ID */
+ /*Identity*/ {/*0x101C,*/ 0x50}, /* <= 80B WSC_ID_IDENTITY */
+ {/*0,*/0}, /* WSC_ID_IDENTITY_PROOF */
+ /*Key Wrap Authenticator*/ {/*0x101E,*/ 8}, /* WSC_ID_KEY_WRAP_AUTH */
+ /*Key Identifier*/ {/*0x101F,*/ 16}, /* WSC_ID_KEY_IDENTIFIER */
+ /*MAC Address*/ {/*0x1020,*/ 6}, /* WSC_ID_MAC_ADDR */
+ /*Manufacturer*/ {/*0x1021,*/ 0x40}, /* <= 64B WSC_ID_MANUFACTURER */
+ /*Message Type*/ {/*0x1022,*/ 1}, /* WSC_ID_MSG_TYPE */
+ /*Model Name*/ {/*0x1023,*/ 0x20}, /* <= 32B WSC_ID_MODEL_NAME */
+ /*Model Number*/ {/*0x1024,*/ 0x20}, /* <= 32B WSC_ID_MODEL_NUMBER */
+ {/*0,*/0},
+ /*Network Index*/ {/*0x1026,*/ 1}, /* WSC_ID_NW_INDEX */
+
+ /*
+ Windows 7 WCN test only accept Len of Network Key item in credentail is zero
+ when auth type of AP is OPEN/NONE
+ */
+ /*Network Key*/ {/*0x1027,*/ 0}, /* <= 64B WSC_ID_NW_KEY */
+
+ /*Network Key Index*/ {/*0x1028,*/ 1}, /* WSC_ID_NW_KEY_INDEX */
+ /*New Device Name*/ {/*0x1029,*/ 0x20}, /* <= 32B WSC_ID_NEW_DEVICE_NAME */
+ /*New Password*/ {/*0x102A,*/ 0x40}, /* <= 64B WSC_ID_NEW_PWD */
+ {/*0,*/0},
+ /*OOB Device Password*/ {/*0x102C,*/ 0x3A}, /* <= 58B WSC_ID_OOB_DEV_PWD */
+ /*OS Version*/ {/*0x102D,*/ 4}, /* WSC_ID_OS_VERSION */
+ {/*0,*/0},
+ /*Power Level*/ {/*0x102F,*/ 1}, /* WSC_ID_POWER_LEVEL */
+ /*PSK Current*/ {/*0x1030,*/ 1}, /* WSC_ID_PSK_CURRENT */
+ /*PSK Max*/ {/*0x1031,*/ 1}, /* WSC_ID_PSK_MAX */
+ /*Public Key*/ {/*0x1032,*/ 192}, /* WSC_ID_PUBLIC_KEY */
+ /*Radio Enabled*/ {/*0x1033,*/ 1}, /* WSC_ID_RADIO_ENABLED */
+ /*Reboot*/ {/*0x1034,*/ 1}, /* WSC_ID_REBOOT */
+ /*Registrar Current*/ {/*0x1035,*/ 1}, /* WSC_ID_REGISTRAR_CURRENT */
+ /*Registrar Established*/ {/*0x1036,*/ 1}, /* WSC_ID_REGISTRAR_ESTBLSHD */
+ {/*0,*/0}, /* WSC_ID_REGISTRAR_LIST */
+ /*Registrar Max*/ {/*0x1038,*/ 1}, /* WSC_ID_REGISTRAR_MAX */
+ /*Registrar Nonce*/ {/*0x1039,*/ 16}, /* WSC_ID_REGISTRAR_NONCE */
+ /*Request Type*/ {/*0x103A,*/ 1}, /* WSC_ID_REQ_TYPE */
+ /*Response Type*/ {/*0x103B,*/ 1}, /* WSC_ID_RESP_TYPE */
+ /*RF Bands*/ {/*0x103C,*/ 1}, /* WSC_ID_RF_BAND */
+ /*R-Hash1*/ {/*0x103D,*/ 32}, /* WSC_ID_R_HASH1 */
+ /*R-Hash2*/ {/*0x103E,*/ 32}, /* WSC_ID_R_HASH2 */
+ /*R-SNonce1*/ {/*0x103F,*/ 16}, /* WSC_ID_R_SNONCE1 */
+ /*R-SNonce2*/ {/*0x1040,*/ 16}, /* WSC_ID_R_SNONCE2 */
+ /*Selected Registrar*/ {/*0x1041,*/ 1}, /* WSC_ID_SEL_REGISTRAR */
+ /*Serial Number*/ {/*0x1042,*/ 0x20}, /* <= 32B WSC_ID_SERIAL_NUM */
+ {/*0,*/0},
+ /*Simple Config State*/ {/*0x1044,*/ 1}, /* WSC_ID_SC_STATE */
+ /*SSID*/ {/*0x1045,*/ 0x20}, /* <= 32B WSC_ID_SSID */
+ /*Total Networks*/ {/*0x1046,*/ 1}, /* WSC_ID_TOT_NETWORKS */
+ /*UUID-E*/ {/*0x1047,*/ 16}, /* WSC_ID_UUID_E */
+ /*UUID-R*/ {/*0x1048,*/ 16}, /* WSC_ID_UUID_R */
+ /*WPS Vendor Extension*/ {/*0x1049,*/ 0x400}, /* WSC_ID_VENDOR_EXT */
+ /*Version*/ {/*0x104A,*/ 1}, /* WSC_ID_VERSION */
+ /*X.509 Certificate Request*/ {/*0x104B,*/ 0xff}, /* WSC_ID_X509_CERT_REQ */
+ /*X.509 Certificate*/ {/*0x104C,*/ 0xff}, /* WSC_ID_X509_CERT */
+ /*EAP Identity*/ {/*0x104D,*/ 0x40}, /* <= 64B WSC_ID_EAP_IDENTITY */
+ /*Message Counter*/ {/*0x104E,*/ 8}, /* WSC_ID_MSG_COUNTER */
+ /*Public Key Hash*/ {/*0x104F,*/ 20}, /* WSC_ID_PUBKEY_HASH */
+ /*Rekey Key*/ {/*0x1050,*/ 32}, /* WSC_ID_REKEY_KEY */
+ /*Key Lifetime*/ {/*0x1051,*/ 4}, /* WSC_ID_KEY_LIFETIME */
+ /*Permitted Config Methods*/ {/*0x1052,*/ 2}, /* WSC_ID_PERM_CFG_METHODS */
+ /*Selected Registrar Config Method*/{/*0x1053,*/ 2}, /* WSC_ID_SEL_REG_CFG_METHODS */
+ /*Primary Device Type*/ {/*0x1054,*/ 8}, /* WSC_ID_PRIM_DEV_TYPE */
+ {/*0,*/0}, /* WSC_ID_SEC_DEV_TYPE_LIST */
+ /*Portable Device*/ {/*0x1056,*/ 1}, /* WSC_ID_PORTABLE_DEVICE */
+ /*AP Setup Locked*/ {/*0x1057,*/ 1}, /* WSC_ID_AP_SETUP_LOCKED */
+ {/*0,*/0}, /* WSC_ID_APP_LIST */
+ /*EAP Type*/ {/*0x1059,*/ 0x08}, /* <= 8B WSC_ID_EAP_TYPE */
+ {/*0,*/0},
+ {/*0,*/0},
+ {/*0,*/0},
+ {/*0,*/0},
+ {/*0,*/0},
+ {/*0,*/0},
+ /*Initialization Vector*/ {/*0x1060,*/ 32}, /* WSC_ID_INIT_VECTOR */
+ /*Key Provided Automatically*/ {/*0x1061,*/ 1}, /* WSC_ID_KEY_PROVIDED_AUTO */
+ /*802.1X Enabled*/ {/*0x1062,*/ 1}, /* WSC_ID_8021X_ENABLED */
+ /*<Reserved for WFA> 0x106F ¡V 0x1FFF*/
+ /*<Unavailable> 0x000 ¡V 0x0FFF,0x2000 ¡V 0xFFFF*/
+};
+
+extern UINT8 WPS_DH_G_VALUE[1];
+extern UINT8 WPS_DH_P_VALUE[192];
+
+int AppendWSCTLV(USHORT index, OUT UCHAR * obuf, IN UCHAR * ibuf, IN USHORT varlen)
+{
+ USHORT len, dataLen, tag = cpu2be16(index);
+
+ /*
+ The max len of WPS Vendor Extension is 1024B
+ */
+ dataLen = ( varlen != (USHORT)0 ) ? varlen : wsc_tlv_0b[WSC_TLV_ENT(index)].len;
+
+ NdisMoveMemory(obuf, &tag, 2);
+ len = cpu2be16(dataLen);
+ memcpy(obuf + 2, &len, 2);
+ if (dataLen != 0)
+ memcpy(obuf + 4, ibuf, dataLen);
+ return (dataLen + 4);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process elements encryption settings
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ 1. Recv M4 M5 M6 M7
+
+ ========================================================================
+*/
+static VOID WscParseEncrSettings(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PUCHAR pPlainData,
+ IN INT PlainLength,
+ IN PWSC_CTRL pWscControl)
+{
+ USHORT WscType, WscLen, HmacLen;
+ PUCHAR pData;
+ UCHAR Hmac[8], Temp[32];
+ PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+
+ HmacLen = (USHORT)(PlainLength - 12);
+ pData = pPlainData;
+
+ /* Start to process WSC IEs */
+ while (PlainLength > 4)
+ {
+ WSC_IE TLV_Encr;
+ memcpy((UINT8 *)&TLV_Encr, pData, 4);
+ WscType = be2cpu16(TLV_Encr.Type);
+ WscLen = be2cpu16(TLV_Encr.Length);
+ pData += 4;
+ PlainLength -= 4;
+
+ /* Parse M2 WSC type and store to RegData structure */
+ switch (WscType)
+ {
+ case WSC_ID_E_SNONCE1:
+ /* for verification with our enrollee nonce */
+ NdisMoveMemory(pReg->Es1, pData, WscLen);
+ break;
+
+ case WSC_ID_E_SNONCE2:
+ /* for verification with our enrollee nonce */
+ NdisMoveMemory(pReg->Es2, pData, WscLen);
+ break;
+
+ case WSC_ID_R_SNONCE1:
+ /* for verification with our enrollee nonce */
+ NdisMoveMemory(pReg->Rs1, pData, WscLen);
+ break;
+
+ case WSC_ID_R_SNONCE2:
+ /* for verification with our enrollee nonce */
+ NdisMoveMemory(pReg->Rs2, pData, WscLen);
+ break;
+
+ case WSC_ID_KEY_WRAP_AUTH:
+ NdisMoveMemory(Hmac, pData, WscLen);
+ break;
+
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscParseEncrSettings --> Unknown IE 0x%04x\n", WscType));
+ break;
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ PlainLength -= WscLen;
+ }
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pPlainData, HmacLen, Temp, SHA256_DIGEST_SIZE);
+
+ if (RTMPEqualMemory(Hmac, Temp, 8) != 1)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("WscParseEncrSettings --> HMAC not match\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Temp[0])), (UINT)cpu2be32(*((PUINT) &Temp[4]))));
+ DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process credentials within AP encryption settings
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ 1. Recv M8
+
+ ========================================================================
+*/
+static BOOLEAN WscProcessCredential(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PUCHAR pPlainData,
+ IN INT PlainLength,
+ IN PWSC_CTRL pWscControl)
+{
+ USHORT WscType, WscLen, Cnt = 0, CurrentIdx=0, Idx, tmpVal = 0;
+ PUCHAR pData, pTmp;
+ PWSC_PROFILE pProfile;
+#ifdef WSC_V2_SUPPORT
+ BOOLEAN bReject = FALSE;
+#endif /* WSC_V2_SUPPORT */
+
+ pData = pPlainData;
+
+ /* Cleanup Old contents */
+ NdisZeroMemory(&pWscControl->WscProfile, sizeof(WSC_PROFILE));
+
+ pProfile = (PWSC_PROFILE) &pWscControl->WscProfile;
+ /*CurrentIdx = pWscControl->EntryIfIdx; */
+
+ /* Init Profile number */
+ Cnt = 0;
+
+ hex_dump("WscProcessCredential - PlainData", pPlainData, PlainLength);
+ /* Start to process WSC IEs within credential */
+ while (PlainLength > 4)
+ {
+ WSC_IE TLV_Recv;
+ memcpy((UINT8 *)&TLV_Recv, pData, 4);
+ WscType = be2cpu16(TLV_Recv.Type);
+ WscLen = be2cpu16(TLV_Recv.Length);
+ pData += 4;
+ PlainLength -= 4;
+
+ /* Parse M2 WSC type and store to RegData structure */
+ switch (WscType)
+ {
+ case WSC_ID_NW_INDEX:
+ /* A new profile, add the cnt and save to database */
+ CurrentIdx = Cnt; /* since the index start from 0, we have to minus 1 */
+ Cnt++;
+ break;
+
+ case WSC_ID_SSID:
+ /* Find the exact length of SSID without null terminator */
+ pTmp = pData;
+ for (Idx = 0; Idx < WscLen; Idx++)
+ {
+ if (*(pTmp++) == 0x0)
+ break;
+ }
+ pProfile->Profile[CurrentIdx].SSID.SsidLength = Idx;
+ if (RTMPCheckStrPrintAble((CHAR *)pData, Idx) || (pWscControl->bCheckMultiByte == FALSE))
+ NdisMoveMemory(pProfile->Profile[CurrentIdx].SSID.Ssid, pData, pProfile->Profile[CurrentIdx].SSID.SsidLength);
+ else
+ return FALSE;
+ break;
+
+ case WSC_ID_AUTH_TYPE:
+ tmpVal = get_unaligned((PUSHORT) pData);
+ pProfile->Profile[CurrentIdx].AuthType = cpu2be16(tmpVal); /*cpu2be16(*((PUSHORT) pData));//(UINT8 *)&pReg->RegistrarInfo.AuthTypeFlags */
+ break;
+
+ case WSC_ID_ENCR_TYPE:
+ tmpVal = get_unaligned((PUSHORT) pData);
+ pProfile->Profile[CurrentIdx].EncrType = cpu2be16(tmpVal);/*cpu2be16(*((PUSHORT) pData));//(UINT8 *)&pReg->RegistrarInfo.EncrTypeFlags */
+ break;
+
+ case WSC_ID_NW_KEY_INDEX:
+ /* Netork Key Index: 1 ~ 4 */
+ pProfile->Profile[CurrentIdx].KeyIndex = (*pData);
+ break;
+
+ case WSC_ID_NW_KEY:
+ if (WscLen == 0)
+ break;
+
+ if (RTMPCheckStrPrintAble((CHAR *)pData, WscLen) || (pWscControl->bCheckMultiByte == FALSE))
+ {
+ pProfile->Profile[CurrentIdx].KeyLength = WscLen;
+ NdisMoveMemory(pProfile->Profile[CurrentIdx].Key, pData, pProfile->Profile[CurrentIdx].KeyLength);
+ }
+ else
+ return FALSE;
+ break;
+
+ case WSC_ID_MAC_ADDR:
+ /*
+ Some AP (ex. Buffalo WHR-G300N WPS AP) would change BSSID during WPS processing.
+ STA shall not change MacAddr of credential form AP.
+ */
+ RTMPMoveMemory(pProfile->Profile[CurrentIdx].MacAddr, pData, MAC_ADDR_LEN);
+ break;
+
+ case WSC_ID_KEY_WRAP_AUTH:
+ /* Not used here, since we already verify it at decryption */
+ break;
+
+ case WSC_ID_CREDENTIAL:
+ /* Credential IE, The WscLen include all length within profile, we need to modify it */
+ /* to be able to parse all profile fields */
+ WscLen = 0;
+ break;
+
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("WscProcessCredential --> Unknown IE 0x%04x\n", WscType));
+ break;
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ PlainLength -= WscLen;
+ }
+
+ /* Svae the total number */
+ pProfile->ProfileCnt = (UINT)Cnt;
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /*
+ Check all credentials
+ */
+ for (Idx = 0; Idx < pProfile->ProfileCnt; Idx++)
+ {
+ PWSC_CREDENTIAL pCredential = &pProfile->Profile[Idx];
+ /*if ((pCredential->EncrType != WSC_ENCRTYPE_WEP) && (pCredential->EncrType != WSC_ENCRTYPE_TKIP)) */
+ if (pCredential->EncrType == WSC_ENCRTYPE_WEP)
+ {
+ bReject = TRUE;
+ /* Cleanup contents */
+ NdisZeroMemory(&pWscControl->WscProfile, sizeof(WSC_PROFILE));
+ }
+ }
+
+ if (bReject)
+ return FALSE;
+ }
+#endif /* WSC_V2_SUPPORT */
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscProcessCredential --> %d profile retrieved from credential\n", Cnt));
+ return TRUE;
+}
+
+/* return 0 to success ,1 to failed */
+int WscDeriveKey (
+ unsigned char *kdk, unsigned int kdk_len,
+ unsigned char *prsnlString, unsigned int str_len,
+ unsigned char *key, unsigned int keyBits )
+{
+ unsigned int i = 0, iterations = 0;
+ unsigned char input[64], output[128];
+ unsigned char hmac[32];
+ unsigned int temp;
+
+ iterations = ((keyBits/8) + 32 - 1)/32;
+
+ /*Prepare the input buffer. During the iterations, we need only replace the */
+ /*value of i at the start of the buffer. */
+ temp = cpu2be32(i);
+ memcpy(input, &temp, 4);
+ memcpy(input+4, prsnlString, str_len);
+
+ temp = cpu2be32(keyBits);
+ memcpy(input+4+str_len, &temp, 4);
+
+ for(i = 0; i < iterations; i++)
+ {
+ /*Set the current value of i at the start of the input buffer */
+ temp = cpu2be32(i+1); /*i should start at 1 */
+ memcpy(input,&temp,4);
+ RT_HMAC_SHA256(kdk, kdk_len, input, 4+str_len+4, hmac, SHA256_DIGEST_SIZE);
+ memcpy(output+i*32, hmac, 32);
+ }
+
+ /*Sanity check */
+ if(keyBits/8 > (32*iterations))
+ {
+
+ return 1; /*failed */
+ }
+
+ memcpy(key, output, 80);
+
+ return 0; /*success */
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build WSC M1 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - rewrite buffer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after Rx EAP-Req(ID)
+ 1. Change the correct parameters
+ 2. Build M1
+
+ ========================================================================
+*/
+int BuildMessageM1(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ OUT VOID *pbuf)
+{
+ UCHAR TB[1];
+ INT Len = 0, templen = 0;
+ PUCHAR pData = (PUCHAR)pbuf;
+ PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+ INT idx;
+ USHORT ConfigError = 0, ConfigMethods = 0;
+#ifdef WSC_V2_SUPPORT
+ PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
+#endif /* WSC_V2_SUPPORT */
+ UCHAR CurOpMode = 0xFF;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Message Type, M1 */
+ TB[0] = WSC_ID_MESSAGE_M1;
+ templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 3. UUID_E, last 6 bytes use MAC */
+ /*templen = AppendWSCTLV(WSC_ID_UUID_E, pData, pReg->EnrolleeInfo.Uuid, 0); */
+ templen = AppendWSCTLV(WSC_ID_UUID_E, pData, &pWscControl->Wsc_Uuid_E[0], 0);
+ pData += templen;
+ Len += templen;
+
+ /* 4. MAC address */
+ templen = AppendWSCTLV(WSC_ID_MAC_ADDR, pData, pReg->SelfInfo.MacAddr, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Enrollee Nonce, first generate and save to Wsc Control Block */
+ for (idx = 0; idx < 16; idx++)
+ {
+ pReg->SelfNonce[idx] = RandomByte(pAdapter);
+ pReg->EnrolleeNonce[idx] = pReg->SelfNonce[idx];
+ }
+ /* 5. Enrollee Nonce, first generate and save to Wsc Control Block */
+ NdisMoveMemory(pReg->EnrolleeNonce, pReg->SelfNonce, 16);
+ templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->SelfNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 6. Public Key, 192 bytes */
+ templen = AppendWSCTLV(WSC_ID_PUBLIC_KEY, pData, pReg->Pke, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 7. Authentication Type Flags */
+ templen = AppendWSCTLV(WSC_ID_AUTH_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.AuthTypeFlags, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 8. Encryption Type Flags */
+ templen = AppendWSCTLV(WSC_ID_ENCR_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.EncrTypeFlags, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 9. Connection Type Flag ESS */
+ templen = AppendWSCTLV(WSC_ID_CONN_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0);
+ pData += templen;
+ Len += templen;
+
+ /*10. Config Method */
+ /*pReg->SelfInfo.ConfigMethods = cpu2be16(pWscControl->WscConfigMethods);*/
+ ConfigMethods = pWscControl->WscConfigMethods;
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /*
+ AP MUST NOT support using PBC to add an external Registrar
+ */
+ if (CurOpMode == AP_MODE)
+ {
+ ConfigMethods = (pWscControl->WscConfigMethods & 0x210F); //sync by 7610
+ }
+ }
+ else
+#endif /* WSC_V2_SUPPORT */
+ {
+ /*
+ WSC 1.0 WCN logo testing has AP PBC Enrollee testing item.
+ We cannot remove PBC capability here.
+ */
+ ConfigMethods = (pWscControl->WscConfigMethods & 0x00FF);
+ }
+
+ ConfigMethods = cpu2be16(ConfigMethods);
+ templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&ConfigMethods, 0);
+ pData += templen;
+ Len += templen;
+
+ /*11. Simple Config State (Not Configured) */
+ if (CurOpMode == AP_MODE)
+ pReg->SelfInfo.ScState = pWscControl->WscConfStatus;
+ templen = AppendWSCTLV(WSC_ID_SC_STATE, pData, (UINT8 *)&pReg->SelfInfo.ScState, 0);
+ pData += templen;
+ Len += templen;
+
+ /*12. Manufacture */
+ templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((PSTRING) pReg->SelfInfo.Manufacturer));
+ pData += templen;
+ Len += templen;
+
+ /*13. Model Name */
+ templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((PSTRING) pReg->SelfInfo.ModelName));
+ pData += templen;
+ Len += templen;
+
+ /*14. Model Number */
+ templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((PSTRING) pReg->SelfInfo.ModelNumber));
+ pData += templen;
+ Len += templen;
+
+ /*15. Serial Number */
+ templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((PSTRING) pReg->SelfInfo.SerialNumber));
+ pData += templen;
+ Len += templen;
+
+ /*16. Primary Device Type */
+ templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0);
+ pData += templen;
+ Len += templen;
+
+ /*17. Device Name */
+ templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((PSTRING) pReg->SelfInfo.DeviceName));
+ pData += templen;
+ Len += templen;
+
+ /*18. RF Band */
+ templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&pReg->SelfInfo.RfBand, 0);
+ pData += templen;
+ Len += templen;
+
+ /*19. Associate state (Not associated) */
+ templen = AppendWSCTLV(WSC_ID_ASSOC_STATE, pData, (UINT8 *)&pReg->SelfInfo.AssocState, 0);
+ pData += templen;
+ Len += templen;
+
+ /*20. Device Password ID */
+ templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pReg->SelfInfo.DevPwdId, 0);
+ pData += templen;
+ Len += templen;
+
+ /*21. Configure Error */
+ templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&ConfigError, 0);
+ pData += templen;
+ Len += templen;
+
+ /*22. OS Version Not associated) */
+ templen = AppendWSCTLV(WSC_ID_OS_VERSION, pData, (UINT8 *)&pReg->SelfInfo.OsVersion, 0);
+ pData += templen;
+ Len += templen;
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /* Version2 */
+ WscGenV2Msg(pWscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+
+
+#ifdef WSC_V2_SUPPORT
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscControl->WscV2Info.bEnableWpsV2 && pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+#endif /* WSC_V2_SUPPORT */
+ //sync by 7610
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM1 - bUPnPMsgTimerRunning = %d, pWscControl->WscUseUPnP = %d, pWscControl->EapMsgRunning = %d\n",
+ pWscControl->WscUPnPNodeInfo.bUPnPMsgTimerRunning,
+ pWscControl->WscUseUPnP,
+ pWscControl->EapMsgRunning));
+
+ /* Fixed WCN vista logo 2 registrar test item issue. */
+ /* Also prevent that WCN GetDeviceInfo disturbs EAP processing. */
+ if (pWscControl->WscUPnPNodeInfo.bUPnPMsgTimerRunning ||
+ (pWscControl->WscUseUPnP && pWscControl->EapMsgRunning))
+ ;
+ else
+ {
+ /* Copy the content to Regdata for lasttx information */
+ pReg->LastTx.Length = Len;
+ NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
+ }
+
+ pWscControl->WscRetryCount = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM1.\n"));
+ return Len;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build WSC M2 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - rewrite buffer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after M1
+ 1. Change the correct parameters
+ 2. Build M2
+
+ ========================================================================
+*/
+int BuildMessageM2(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ OUT VOID *pbuf)
+{
+ UCHAR TB[1];
+ INT Len = 0, templen = 0;
+ PUCHAR pData = (PUCHAR)pbuf, pAuth;
+ PWSC_REG_DATA pReg;
+ UCHAR DHKey[32], KDK[32], KdkInput[38], KdfKey[80];
+ INT DH_Len;
+ INT HmacLen = 0;
+ INT idx;
+ USHORT ConfigMethods;
+#ifdef WSC_V2_SUPPORT
+ PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
+#endif /* WSC_V2_SUPPORT */
+
+ pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+
+ DH_Len = sizeof(pReg->SecretKey);
+ RT_DH_SecretKey_Generate (
+ pReg->Pke, sizeof(pReg->Pke),
+ WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE),
+ pReg->EnrolleeRandom, sizeof(pReg->EnrolleeRandom),
+ pReg->SecretKey, (UINT *) &DH_Len);
+ RT_SHA256(&pReg->SecretKey[0], 192, &DHKey[0]);
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Message Type, M2 */
+ TB[0] = WSC_ID_MESSAGE_M2;
+ templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* fixed config Windows 7 issue */
+ /* Enrollee Nonce, first generate and save to Wsc Control Block */
+ for (idx = 0; idx < 16; idx++)
+ {
+ pReg->SelfNonce[idx] = RandomByte(pAdapter);
+ pReg->RegistrarNonce[idx] = pReg->SelfNonce[idx];
+ }
+
+ /* 3. Enrollee Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 4. Registrar Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* UUID, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_UUID_R, pData, pReg->SelfInfo.Uuid, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Publikc Key */
+ templen = AppendWSCTLV(WSC_ID_PUBLIC_KEY, pData, pReg->Pkr, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Authentication Type Flags */
+ templen = AppendWSCTLV(WSC_ID_AUTH_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.AuthTypeFlags, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Encrypt Type */
+ templen = AppendWSCTLV(WSC_ID_ENCR_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.EncrTypeFlags, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Connection Type */
+ templen = AppendWSCTLV(WSC_ID_CONN_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Config Method */
+ ConfigMethods = pWscControl->WscConfigMethods;
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ //sync by 7610
+ /*
+ In WPS 2.0.0
+ In Test Item 4.1.1 ,Step 13
+ On the sniffer device, verify that the M2 message that the APUT sends includes
+ the Configuration Methods attribute. The Configuration Methods attribute in the
+ WSC IE must reflect the correct configuration methods that the Internal Registrar
+ supports.
+ */
+ }
+ else
+ {
+ ConfigMethods = (pWscControl->WscConfigMethods & 0x00FF);
+ }
+#endif /* WSC_V2_SUPPORT */
+ ConfigMethods = cpu2be16(ConfigMethods);
+ templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&ConfigMethods, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Manufacture Name */
+ templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((PSTRING) pReg->SelfInfo.Manufacturer));
+ pData += templen;
+ Len += templen;
+
+ /* Model Name */
+ templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((PSTRING) pReg->SelfInfo.ModelName));
+ pData += templen;
+ Len += templen;
+
+ /* Model Number */
+ templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((PSTRING) pReg->SelfInfo.ModelNumber));
+ pData += templen;
+ Len += templen;
+
+ /* Serial Number */
+ templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((PSTRING) pReg->SelfInfo.SerialNumber));
+ pData += templen;
+ Len += templen;
+
+ /* Prime Device Type */
+ templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Device Name */
+ templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((PSTRING) pReg->SelfInfo.DeviceName));
+ pData += templen;
+ Len += templen;
+
+ /* RF Band */
+ templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&pReg->SelfInfo.RfBand, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Assoc State */
+ templen = AppendWSCTLV(WSC_ID_ASSOC_STATE, pData, (UINT8 *)&pReg->SelfInfo.AssocState, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Config Error */
+ templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&pReg->SelfInfo.ConfigError, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Device Password ID */
+ templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pReg->SelfInfo.DevPwdId, 0);
+ pData += templen;
+ Len += templen;
+
+ /* OS Version */
+ templen = AppendWSCTLV(WSC_ID_OS_VERSION, pData, (UINT8 *)&pReg->SelfInfo.OsVersion, 0);
+ pData += templen;
+ Len += templen;
+
+
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /* Version2 */
+ WscGenV2Msg(pWscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+ /* Create KDK input data */
+ NdisMoveMemory(&KdkInput[0], &pReg->EnrolleeNonce[0], 16);
+ NdisMoveMemory(&KdkInput[16], &pReg->PeerInfo.MacAddr[0], 6);
+ NdisMoveMemory(&KdkInput[22], pReg->RegistrarNonce, 16);
+
+ /* Generate the KDK */
+ RT_HMAC_SHA256(DHKey, 32, KdkInput, 38, KDK, SHA256_DIGEST_SIZE);
+
+ /* KDF */
+ WscDeriveKey(KDK, 32, Wsc_Personal_String, (sizeof(Wsc_Personal_String) - 1), KdfKey, 640);
+
+ /* Assign Key from KDF */
+ NdisMoveMemory(pReg->AuthKey, &KdfKey[0], 32);
+ NdisMoveMemory(pReg->KeyWrapKey, &KdfKey[32], 16);
+ NdisMoveMemory(pReg->Emsk, &KdfKey[48], 32);
+
+ /* Combine last TX & RX message contents and validate the HMAC */
+ /* We have to exclude last 12 bytes from last receive since it's authenticator value */
+ HmacLen = Len + pReg->LastRx.Length;
+ if (pAdapter->pHmacData)
+ {
+ pAuth = (PUCHAR) pAdapter->pHmacData;
+ NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
+ pAuth += pReg->LastRx.Length;
+ NdisMoveMemory(pAuth, pbuf, Len);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
+ }
+ /* 22. Hmac */
+ templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Copy the content to Regdata for lasttx information */
+ pReg->LastTx.Length = Len;
+ NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
+
+ pWscControl->WscRetryCount = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM2.\n"));
+ return Len;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build WSC M2D Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - rewrite buffer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after M1 process Error
+ 1. Change the correct parameters
+ 2. Build M2D
+
+ ========================================================================
+*/
+int BuildMessageM2D(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ OUT VOID *pbuf)
+{
+ UCHAR TB[1];
+ INT Len = 0, templen = 0;
+ PUCHAR pData = (PUCHAR)pbuf;
+ PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+#ifdef WSC_V2_SUPPORT
+ PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
+#endif /* WSC_V2_SUPPORT */
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Message Type, M2D */
+ TB[0] = WSC_ID_MESSAGE_M2D;
+ templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 3. Enrollee Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 4. Registrar Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->SelfNonce, 0);
+ /*templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0); */
+ pData += templen;
+ Len += templen;
+
+ /* UUID, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_UUID_R, pData, pReg->SelfInfo.Uuid, 0);
+ pData += templen;
+ Len += templen;
+
+
+ /* 7. Authentication Type Flags */
+ templen = AppendWSCTLV(WSC_ID_AUTH_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.AuthTypeFlags, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Encrypt Type */
+ templen = AppendWSCTLV(WSC_ID_ENCR_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.EncrTypeFlags, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Connection Type */
+ templen = AppendWSCTLV(WSC_ID_CONN_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Config Methods */
+ templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&pReg->SelfInfo.ConfigMethods, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Manufacturer Name */
+ templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((PSTRING) pReg->SelfInfo.Manufacturer));
+ pData += templen;
+ Len += templen;
+
+ /* Model Name */
+ templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((PSTRING) pReg->SelfInfo.ModelName));
+ pData += templen;
+ Len += templen;
+
+ /* Model Number */
+ templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((PSTRING) pReg->SelfInfo.ModelNumber));
+ pData += templen;
+ Len += templen;
+
+ /* Serial Number */
+ templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((PSTRING) pReg->SelfInfo.SerialNumber));
+ pData += templen;
+ Len += templen;
+
+ /* Prime Device Type */
+ templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Device Name */
+ templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((PSTRING) pReg->SelfInfo.DeviceName));
+ pData += templen;
+ Len += templen;
+
+ /* RF Band */
+ templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&pReg->SelfInfo.RfBand, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Assoc State */
+ templen = AppendWSCTLV(WSC_ID_ASSOC_STATE, pData, (UINT8 *)&pReg->SelfInfo.AssocState, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Config Error */
+ templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&pReg->SelfInfo.ConfigError, 0);
+ pData += templen;
+ Len += templen;
+
+ /* OS Version */
+ templen = AppendWSCTLV(WSC_ID_OS_VERSION, pData, (UINT8 *)&pReg->SelfInfo.OsVersion, 0);
+ pData += templen;
+ Len += templen;
+
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /* Version2 */
+ WscGenV2Msg(pWscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+ pWscControl->WscRetryCount = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM2D.\n"));
+ return Len;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build WSC M3 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - rewrite buffer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after M2
+ 1. Change the correct parameters
+ 2. Build M3
+
+ ========================================================================
+*/
+int BuildMessageM3(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ OUT VOID *pbuf)
+{
+ UCHAR TB[32];
+ INT Len = 0, templen = 0;
+ PUCHAR pData = (PUCHAR)pbuf, pAuth;
+ PWSC_REG_DATA pReg = NULL;
+ INT HmacLen;
+ UCHAR *pHash=NULL;
+#ifdef WSC_V2_SUPPORT
+ PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
+#endif /* WSC_V2_SUPPORT */
+
+/* pHash = kmalloc(512, MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)&pHash, 512);
+ if(NULL == pHash)
+ return Len;
+ pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Message Type, M3 */
+ TB[0] = WSC_ID_MESSAGE_M3;
+ templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 3. Registrar Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 4. E-Hash1 */
+ /* */
+ /* Generate PSK1 */
+ if (pReg->PinCodeLen == 4)
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pReg->PIN, 2, TB, SHA256_DIGEST_SIZE);
+ else
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pReg->PIN, 4, TB, SHA256_DIGEST_SIZE);
+
+ /* Copy first 16 bytes to PSK1 */
+ NdisMoveMemory(pReg->Psk1, TB, 16);
+
+ /* Create input for E-Hash1 */
+ NdisMoveMemory(pHash, pReg->Es1, 16);
+ NdisMoveMemory(pHash + 16, pReg->Psk1, 16);
+ NdisMoveMemory(pHash + 32, pReg->Pke, 192);
+ NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
+
+ /* Generate E-Hash1 */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->EHash1, SHA256_DIGEST_SIZE);
+
+ templen = AppendWSCTLV(WSC_ID_E_HASH1, pData, pReg->EHash1, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 5. E-Hash2 */
+ /* */
+ /* Generate PSK2 */
+ if (pReg->PinCodeLen == 4)
+ RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[2], 2, TB, SHA256_DIGEST_SIZE);
+ else
+ RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[4], 4, TB, SHA256_DIGEST_SIZE);
+
+ /* Copy first 16 bytes to PSK2 */
+ NdisMoveMemory(pReg->Psk2, TB, 16);
+
+ /* Create input for E-Hash2 */
+ NdisMoveMemory(pHash, pReg->Es2, 16);
+ NdisMoveMemory(pHash + 16, pReg->Psk2, 16);
+ NdisMoveMemory(pHash + 32, pReg->Pke, 192);
+ NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
+
+ /* Generate E-Hash2 */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->EHash2, SHA256_DIGEST_SIZE);
+
+ templen = AppendWSCTLV(WSC_ID_E_HASH2, pData, pReg->EHash2, 0);
+ pData += templen;
+ Len += templen;
+
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /* Version2 */
+ WscGenV2Msg(pWscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+ /*
+ Generate authenticator
+ Combine last TX & RX message contents and validate the HMAC
+ */
+ HmacLen = Len + pReg->LastRx.Length;
+ if (pAdapter->pHmacData)
+ {
+ pAuth = (PUCHAR) pAdapter->pHmacData;
+ NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
+ pAuth += pReg->LastRx.Length;
+ NdisMoveMemory(pAuth, pbuf, Len);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, TB, SHA256_DIGEST_SIZE);
+ }
+
+ templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Copy the content to Regdata for lasttx information */
+ pReg->LastTx.Length = Len;
+ NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
+
+ if(NULL != pHash)
+/* kfree(pHash); */
+ os_free_mem(NULL, pHash);
+
+ pWscControl->WscRetryCount = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM3 : \n"));
+ return Len;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build WSC M4 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - rewrite buffer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after M3
+ 1. Change the correct parameters
+ 2. Build M4
+
+ ========================================================================
+*/
+int BuildMessageM4(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ OUT VOID *pbuf)
+{
+ UCHAR TB[32];
+ INT Len = 0, templen = 0;
+ PUCHAR pData = (PUCHAR)pbuf, pAuth;
+ PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+ INT HmacLen;
+ UCHAR KDK[32];
+ UCHAR Plain[128]; /*, IV_EncrData[144];//IV len 16,EncrData len 128 */
+ UCHAR *IV_EncrData = NULL;/*IV len 16,EncrData len 128 */
+ INT PlainLen = 0, EncrLen;
+ UCHAR *pHash=NULL;
+#ifdef WSC_V2_SUPPORT
+ PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
+#endif /* WSC_V2_SUPPORT */
+
+/* pHash = kmalloc(512, MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)&pHash, 512);
+ if(NULL == pHash)
+ return Len;
+
+ os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_144);
+ if (IV_EncrData == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ goto LabelErr;
+ }
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Message Type, M4 */
+ TB[0] = WSC_ID_MESSAGE_M4;
+ templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 3. Enrollee Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 4. R-Hash1 */
+ /* */
+ /* Generate PSK1 */
+ if (pReg->PinCodeLen == 4)
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pReg->PIN, 2, TB, SHA256_DIGEST_SIZE);
+ else
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pReg->PIN, 4, TB, SHA256_DIGEST_SIZE);
+
+ /* Copy first 16 bytes to PSK1 */
+ NdisMoveMemory(pReg->Psk1, TB, 16);
+
+ /* Create input for R-Hash1 */
+ NdisMoveMemory(pHash, pReg->Es1, 16);
+ NdisMoveMemory(pHash + 16, pReg->Psk1, 16);
+ NdisMoveMemory(pHash + 32, pReg->Pke, 192);
+ NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
+
+ /* Generate R-Hash1 */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->RHash1, SHA256_DIGEST_SIZE);
+
+ templen = AppendWSCTLV(WSC_ID_R_HASH1, pData, pReg->RHash1, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 5. R-Hash2 */
+ /* */
+ /* Generate PSK2 */
+ if (pReg->PinCodeLen == 4)
+ RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[2], 2, TB, SHA256_DIGEST_SIZE);
+ else
+ RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[4], 4, TB, SHA256_DIGEST_SIZE);
+
+ /* Copy first 16 bytes to PSK2 */
+ NdisMoveMemory(pReg->Psk2, TB, 16);
+
+ /* Create input for R-Hash2 */
+ NdisMoveMemory(pHash, pReg->Es2, 16);
+ NdisMoveMemory(pHash + 16, pReg->Psk2, 16);
+ NdisMoveMemory(pHash + 32, pReg->Pke, 192);
+ NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
+
+ /* Generate R-Hash2 */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->RHash2, SHA256_DIGEST_SIZE);
+
+ templen = AppendWSCTLV(WSC_ID_R_HASH2, pData, pReg->RHash2, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 6a. Encrypted R-S1 */
+ /* Prepare plain text */
+ PlainLen += AppendWSCTLV(WSC_ID_R_SNONCE1, &Plain[0], pReg->Es1, 0);
+
+ /* Generate HMAC */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE);
+ PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0);
+
+ /* 6b. Encrypted Settings */
+ /* Encrypt data */
+ EncrLen = IV_ENCR_DATA_LEN_144 - 16;
+ AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen);
+ templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, &IV_EncrData[0], 16 + EncrLen);/*IVLen + EncrLen */
+ pData += templen;
+ Len += templen;
+
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /* Version2 */
+ WscGenV2Msg(pWscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+ /*
+ Combine last TX & RX message contents and validate the HMAC
+ We have to exclude last 12 bytes from last receive since it's authenticator value
+ */
+ HmacLen = Len + pReg->LastRx.Length;
+ if (pAdapter->pHmacData)
+ {
+ pAuth = (PUCHAR) pAdapter->pHmacData;
+ NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
+ pAuth += pReg->LastRx.Length;
+ NdisMoveMemory(pAuth, pbuf, Len);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
+ }
+
+ templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Copy the content to Regdata for lasttx information */
+ pReg->LastTx.Length = Len;
+ NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
+
+LabelErr:
+ if(NULL != pHash)
+/* kfree(pHash); */
+ os_free_mem(NULL, pHash);
+
+ pWscControl->WscRetryCount = 0;
+
+ if (IV_EncrData != NULL)
+ os_free_mem(NULL, IV_EncrData);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM4 : \n"));
+ return Len;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build WSC M5 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - rewrite buffer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after M4
+ 1. Change the correct parameters
+ 2. Build M5
+
+ ========================================================================
+*/
+int BuildMessageM5(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ OUT VOID *pbuf)
+{
+ UCHAR TB[32];
+ INT Len = 0, templen = 0;
+ PUCHAR pData = (PUCHAR)pbuf;
+ PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+ PUCHAR pAuth;
+ INT HmacLen;
+ UCHAR Plain[128]; /*, IV_EncrData[144];//IV len 16,EncrData len 128 */
+ UCHAR *IV_EncrData = NULL;/*IV len 16,EncrData len 128 */
+ INT PlainLen=0, EncrLen;
+#ifdef WSC_V2_SUPPORT
+ PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
+#endif /* WSC_V2_SUPPORT */
+
+ /* allocate memory */
+ os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_144);
+ if (IV_EncrData == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ return 0;
+ }
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Message Type, M5 */
+ TB[0] = WSC_ID_MESSAGE_M5;
+ templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 3. Registrar Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 4a. Encrypted E-S1 */
+ /* Prepare plain text */
+ PlainLen += AppendWSCTLV(WSC_ID_E_SNONCE1, &Plain[0], pReg->Es1, 0);
+
+ /* Generate HMAC */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE);
+ PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0);
+
+ /* 4b. Encrypted Settings */
+ /* Encrypt data */
+ EncrLen = IV_ENCR_DATA_LEN_144 - 16;
+ AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen);
+ templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, &IV_EncrData[0], 16 + EncrLen);/*IVLen + EncrLen */
+ pData += templen;
+ Len += templen;
+
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /* Version2 */
+ WscGenV2Msg(pWscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+ /*
+ Generate authenticator
+ Combine last TX & RX message contents and validate the HMAC
+ */
+ HmacLen = Len + pReg->LastRx.Length;
+ if (pAdapter->pHmacData)
+ {
+ pAuth = (PUCHAR) pAdapter->pHmacData;
+ NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
+ pAuth += pReg->LastRx.Length;
+ NdisMoveMemory(pAuth, pbuf, Len);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, TB, SHA256_DIGEST_SIZE);
+ }
+
+ templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Copy the content to Regdata for lasttx information */
+ pReg->LastTx.Length = Len;
+ NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
+
+ pWscControl->WscRetryCount = 0;
+
+ if (IV_EncrData != NULL)
+ os_free_mem(NULL, IV_EncrData);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM5 : \n"));
+ return Len;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build WSC M6 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - rewrite buffer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after M5
+ 1. Change the correct parameters
+ 2. Build M6
+
+ ========================================================================
+*/
+int BuildMessageM6(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ OUT VOID *pbuf)
+{
+ UCHAR TB[32];
+ INT Len = 0, templen = 0;
+ PUCHAR pData = (PUCHAR)pbuf, pAuth;
+ PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+ INT HmacLen;
+ UCHAR KDK[32];
+ UCHAR Plain[128]; /*, IV_EncrData[144];//IV len 16,EncrData len 128 */
+ UCHAR *IV_EncrData = NULL;/*IV len 16,EncrData len 128 */
+ INT PlainLen = 0, EncrLen;
+#ifdef WSC_V2_SUPPORT
+ PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
+#endif /* WSC_V2_SUPPORT */
+
+
+ /* allocate memory */
+ os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, 144);
+ if (IV_EncrData == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ return 0;
+ }
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Message Type, M6 */
+ TB[0] = WSC_ID_MESSAGE_M6;
+ templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 3. Enrollee Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 4a. Encrypted R-S2 */
+ /* Prepare plain text */
+ PlainLen += AppendWSCTLV(WSC_ID_R_SNONCE2, &Plain[0], pReg->Es2, 0);
+
+ /* Generate HMAC */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE);
+ PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0);
+
+ /* 4b. Encrypted Settings */
+ /* Encrypt data */
+ EncrLen = IV_ENCR_DATA_LEN_144 - 16;
+ AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen);
+ templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, &IV_EncrData[0], 16 + EncrLen);/*IVLen + EncrLen */
+ pData += templen;
+ Len += templen;
+
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /* Version2 */
+ WscGenV2Msg(pWscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+ /*
+ Combine last TX & RX message contents and validate the HMAC
+ We have to exclude last 12 bytes from last receive since it's authenticator value
+ */
+ HmacLen = Len + pReg->LastRx.Length;
+ if (pAdapter->pHmacData)
+ {
+ pAuth = (PUCHAR) pAdapter->pHmacData;
+ NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
+ pAuth += pReg->LastRx.Length;
+ NdisMoveMemory(pAuth, pbuf, Len);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
+ }
+
+ templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Copy the content to Regdata for lasttx information */
+ pReg->LastTx.Length = Len;
+ NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
+
+ /* Copy the content to Regdata for lasttx information */
+ pReg->LastTx.Length = Len;
+ NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
+
+ pWscControl->WscRetryCount = 0;
+
+ if (IV_EncrData != NULL)
+ os_free_mem(NULL, IV_EncrData);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM6 : \n"));
+ return Len;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build WSC M7 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - rewrite buffer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after M6
+ 1. Change the correct parameters
+ 2. Build M7
+
+ ========================================================================
+*/
+int BuildMessageM7(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ OUT VOID *pbuf)
+{
+ UCHAR TB[32];
+ INT Len = 0, templen = 0;
+ PUCHAR pData = (PUCHAR)pbuf, pAuth;
+ PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+ INT HmacLen;
+ UCHAR Plain[256], *IV_EncrData=NULL;/*IV len 16 ,EncrData len */
+ INT PlainLen=0, EncrLen;
+#ifdef WSC_V2_SUPPORT
+ PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
+#endif /* WSC_V2_SUPPORT */
+ UCHAR CurOpMode = 0xFF;
+
+/* IV_EncrData = kmalloc(512, MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_512);
+ if(NULL == IV_EncrData)
+ return 0;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Message Type, M7 */
+ TB[0] = WSC_ID_MESSAGE_M7;
+ templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 3. Registrar Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 4a. Encrypted E-S2 */
+ /* Prepare plain text */
+ PlainLen += AppendWSCTLV(WSC_ID_E_SNONCE2, &Plain[0], pReg->Es2, 0);
+
+ /* Marvell WPS AP doesn't accept STA includes profile in M7. 20070604 */
+ if ((CurOpMode == AP_MODE) &&
+ (pWscControl->EntryIfIdx < MIN_NET_DEVICE_FOR_APCLI))
+ {
+ USHORT authType;
+ USHORT encyType;
+ PWSC_CREDENTIAL pCredential = &pWscControl->WscProfile.Profile[0];
+ WscCreateProfileFromCfg(pAdapter, ENROLLEE_ACTION | AP_MODE, pWscControl, &pWscControl->WscProfile);
+
+ authType = pCredential->AuthType;
+ encyType = pCredential->EncrType;
+ /*
+ Some Win7 WSC 1.0 STA has problem to receive mixed authType and encyType.
+ We need to check STA is WSC 1.0 or WSC 2.0 here.
+ If STA is WSC 1.0, re-assign authType and encyType.
+ */
+ if (pWscControl->RegData.PeerInfo.Version2 == 0)
+ {
+ if (authType == (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK))
+ authType = WSC_AUTHTYPE_WPA2PSK;
+ if (encyType == (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES))
+ encyType = WSC_ENCRTYPE_AES;
+ }
+ authType = cpu2be16(authType);
+ encyType = cpu2be16(encyType);
+ PlainLen += AppendWSCTLV(WSC_ID_SSID, &Plain[PlainLen], pCredential->SSID.Ssid, pCredential->SSID.SsidLength);
+ PlainLen += AppendWSCTLV(WSC_ID_MAC_ADDR, &Plain[PlainLen], pCredential->MacAddr, 0);
+ PlainLen += AppendWSCTLV(WSC_ID_AUTH_TYPE, &Plain[PlainLen], (UINT8 *)&authType, 0);
+ PlainLen += AppendWSCTLV(WSC_ID_ENCR_TYPE, &Plain[PlainLen], (UINT8 *)&encyType, 0);
+ PlainLen += AppendWSCTLV(WSC_ID_NW_KEY_INDEX, &Plain[PlainLen], &pCredential->KeyIndex, 0);
+ PlainLen += AppendWSCTLV(WSC_ID_NW_KEY, &Plain[PlainLen], pCredential->Key, pCredential->KeyLength);
+ }
+
+ /* Generate HMAC */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE);
+ PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0);
+
+ /* 4b. Encrypted Settings */
+ /* Encrypt data */
+ EncrLen = IV_ENCR_DATA_LEN_512 - 16;
+ AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen);
+ templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, IV_EncrData, 16 + EncrLen);/*IVLen + EncrLen */
+ pData += templen;
+ Len += templen;
+
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /* Version2 */
+ WscGenV2Msg(pWscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+ /*
+ Generate authenticator
+ Combine last TX & RX message contents and validate the HMAC
+ */
+ HmacLen = Len + pReg->LastRx.Length;
+ if (pAdapter->pHmacData)
+ {
+ pAuth = (PUCHAR) pAdapter->pHmacData;
+ NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
+ pAuth += pReg->LastRx.Length;
+ NdisMoveMemory(pAuth, pbuf, Len);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, TB, SHA256_DIGEST_SIZE);
+ }
+
+ templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* Copy the content to Regdata for lasttx information */
+ pReg->LastTx.Length = Len;
+ NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
+
+ if(NULL != IV_EncrData)
+/* kfree(IV_EncrData); */
+ os_free_mem(NULL, IV_EncrData);
+
+ pWscControl->WscRetryCount = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM7 : \n"));
+ return Len;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build WSC M8 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - rewrite buffer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after M7
+ 1. Change the correct parameters
+ 2. Build M8
+
+ ========================================================================
+*/
+int BuildMessageM8(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ OUT VOID *pbuf)
+{
+/* UCHAR TB[256]; */
+ UCHAR *TB = NULL;
+ INT Len = 0, templen = 0;
+ PUCHAR pData = (PUCHAR)pbuf, pAuth;
+ PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+ INT HmacLen;
+ UCHAR KDK[32];
+ UCHAR /* Plain[300], */ *IV_EncrData=NULL;/*IV len 16 ,EncrData len */
+ UCHAR *Plain = NULL;
+ INT CerLen = 0, PlainLen = 0, EncrLen;
+ PWSC_CREDENTIAL pCredential = NULL;
+ USHORT AuthType = 0;
+ USHORT EncrType = 0;
+#ifdef CONFIG_AP_SUPPORT
+ UCHAR apidx = (pWscControl->EntryIfIdx & 0x0F);
+#endif /* CONFIG_AP_SUPPORT */
+#ifdef WSC_V2_SUPPORT
+ PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
+#endif /* WSC_V2_SUPPORT */
+ UCHAR CurOpMode = 0xFF;
+
+/* IV_EncrData = kmalloc(512, MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_512);
+ if(NULL == IV_EncrData)
+ return 0;
+
+ os_alloc_mem(NULL, (UCHAR **)&TB, 256);
+ if (TB == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ goto LabelErr;
+ }
+ os_alloc_mem(NULL, (UCHAR **)&Plain, 300);
+ if (Plain == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
+ goto LabelErr;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Message Type, M8 */
+ TB[0] = WSC_ID_MESSAGE_M8;
+ templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 3. Enrollee Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
+ pData += templen;
+ Len += templen;
+
+#ifdef CONFIG_AP_SUPPORT
+ if (CurOpMode == AP_MODE)
+ {
+ WscCreateProfileFromCfg(pAdapter, REGISTRAR_ACTION | AP_MODE, pWscControl, &pWscControl->WscProfile);
+ pCredential = &pAdapter->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0];
+ }
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ /* 4a. Encrypted R-S1 */
+ CerLen += AppendWSCTLV(WSC_ID_NW_INDEX, &TB[0], (PUCHAR)"1", 0);
+
+ if (pCredential == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pWscControl == NULL!\n", __FUNCTION__));
+ goto LabelErr;
+ }
+
+ AuthType = pCredential->AuthType;
+ EncrType = pCredential->EncrType;
+ /*
+ Some Win7 WSC 1.0 STA has problem to receive mixed authType and encyType.
+ We need to check STA is WSC 1.0 or WSC 2.0 here.
+ If STA is WSC 1.0, re-assign authType and encyType.
+ */
+ if (pWscControl->RegData.PeerInfo.Version2 == 0)
+ {
+ if (AuthType == (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK))
+ AuthType = WSC_AUTHTYPE_WPA2PSK;
+ if (EncrType == (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES))
+ EncrType = WSC_ENCRTYPE_AES;
+ }
+
+ AuthType = cpu2be16(AuthType);
+ EncrType = cpu2be16(EncrType);
+ CerLen += AppendWSCTLV(WSC_ID_SSID, &TB[CerLen], pCredential->SSID.Ssid, pCredential->SSID.SsidLength);
+ CerLen += AppendWSCTLV(WSC_ID_AUTH_TYPE, &TB[CerLen], (UINT8 *)&AuthType, 0);
+ CerLen += AppendWSCTLV(WSC_ID_ENCR_TYPE, &TB[CerLen], (UINT8 *)&EncrType, 0);
+ CerLen += AppendWSCTLV(WSC_ID_NW_KEY_INDEX, &TB[CerLen], &pCredential->KeyIndex, 0);
+ CerLen += AppendWSCTLV(WSC_ID_NW_KEY, &TB[CerLen], pCredential->Key, pCredential->KeyLength);
+ CerLen += AppendWSCTLV(WSC_ID_MAC_ADDR, &TB[CerLen], pCredential->MacAddr, 0);
+
+ /* Prepare plain text */
+ if ((CurOpMode == AP_MODE)
+ )
+ {
+ /* Reguired attribute item in M8 if Enrollee is STA. */
+ PlainLen += AppendWSCTLV(WSC_ID_CREDENTIAL, &Plain[0], TB, CerLen);
+ }
+
+ /* Generate HMAC */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE);
+ PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0);
+
+ /* 4b. Encrypted Settings */
+ /* Encrypt data */
+ EncrLen = IV_ENCR_DATA_LEN_512 - 16;
+ AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen);
+ templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, IV_EncrData, 16 + EncrLen);/*IVLen + EncrLen */
+ pData += templen;
+ Len += templen;
+
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /* Version2 */
+ WscGenV2Msg(pWscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+ /*
+ Combine last TX & RX message contents and validate the HMAC
+ We have to exclude last 12 bytes from last receive since it's authenticator value
+ */
+ HmacLen = Len + pReg->LastRx.Length;
+ if (pAdapter->pHmacData)
+ {
+ pAuth = (PUCHAR) pAdapter->pHmacData;
+ NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
+ pAuth += pReg->LastRx.Length;
+ NdisMoveMemory(pAuth, pbuf, Len);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
+ }
+
+ templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0);
+ pData += templen;
+ Len += templen;
+
+LabelErr:
+ if(NULL != IV_EncrData)
+/* kfree(IV_EncrData); */
+ os_free_mem(NULL, IV_EncrData);
+
+ pWscControl->WscRetryCount = 0;
+
+ if (TB != NULL)
+ os_free_mem(NULL, TB);
+ if (Plain != NULL)
+ os_free_mem(NULL, Plain);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM8 : \n"));
+ return Len;
+}
+
+int BuildMessageDONE(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ OUT VOID *pbuf)
+{
+ UCHAR TB[1];
+ INT Len = 0, templen = 0;
+ PUCHAR pData = (PUCHAR)pbuf;
+ PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+#ifdef WSC_V2_SUPPORT
+ PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
+#endif /* WSC_V2_SUPPORT */
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Message Type, WSC DONE */
+ TB[0] = WSC_MSG_WSC_DONE;
+ templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 3. Enrollee Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 4. Registrar Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
+ pData += templen;
+ Len += templen;
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /* Version2 */
+ WscGenV2Msg(pWscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+ pWscControl->WscRetryCount = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageDONE : \n"));
+ return Len;
+}
+
+int BuildMessageACK(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ OUT VOID *pbuf)
+{
+ UCHAR TB[1];
+ INT Len = 0, templen = 0;
+ PUCHAR pData = (PUCHAR)pbuf;
+ PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+#ifdef WSC_V2_SUPPORT
+ PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
+#endif /* WSC_V2_SUPPORT */
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Message Type, WSC ACK */
+ TB[0] = WSC_MSG_WSC_ACK;
+ templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 3. Enrollee Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 4. Registrar Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
+ pData += templen;
+ Len += templen;
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /* Version2 */
+ WscGenV2Msg(pWscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+ pWscControl->WscRetryCount = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageACK : \n"));
+ return Len;
+}
+
+int BuildMessageNACK(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ OUT VOID *pbuf)
+{
+ UCHAR TB[2];
+ INT Len = 0, templen = 0;
+ PUCHAR pData = (PUCHAR)pbuf;
+ PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
+ USHORT ConfigError = htons(pReg->SelfInfo.ConfigError);
+#ifdef WSC_V2_SUPPORT
+ PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
+#endif /* WSC_V2_SUPPORT */
+
+ /* 1. Version */
+ templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 2. Message Type, WSC NACK */
+ TB[0] = WSC_ID_MESSAGE_NACK;
+ templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 3. Enrollee Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 4. Registrar Nonce, 16 bytes */
+ templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
+ pData += templen;
+ Len += templen;
+
+ /* 5. Error */
+ templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&ConfigError, 0);
+ pData += templen;
+ Len += templen;
+
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ /* Version2 */
+ WscGenV2Msg(pWscControl,
+ FALSE,
+ NULL,
+ 0,
+ &pData,
+ &Len);
+
+ /* Extra attribute that is not defined in WSC Sepc. */
+ if (pWscTLV->pTlvData && pWscTLV->TlvLen)
+ {
+ templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
+ pData += templen;
+ Len += templen;
+ }
+ }
+#endif /* WSC_V2_SUPPORT */
+
+ pWscControl->WscRetryCount = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageNACK : \n"));
+ return Len;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process WSC M1 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - recv buffer
+ Length - recv Length
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after Rx M1
+ 1. Change the correct parameters
+ 2. Process M1
+
+ ========================================================================
+*/
+int ProcessMessageM1(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ IN VOID *precv,
+ IN INT Length,
+ OUT PWSC_REG_DATA pReg)
+{
+ int ret = WSC_ERROR_NO_ERROR, DH_Len = 0, idx;
+ PUCHAR pData = NULL;
+ USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0};
+ UCHAR CurOpMode = 0xFF;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ pReg->PeerInfo.Version2 = 0;
+
+ DH_Len = sizeof(pReg->Pkr);
+ /* Enrollee 192 random bytes for DH key generation */
+ for (idx = 0; idx < 192; idx++)
+ pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAdapter);
+
+ RT_DH_PublicKey_Generate (
+ WPS_DH_G_VALUE, sizeof(WPS_DH_G_VALUE),
+ WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE),
+ pWscControl->RegData.EnrolleeRandom, sizeof(pWscControl->RegData.EnrolleeRandom),
+ pReg->Pkr, (UINT *) &DH_Len);
+
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_E))] |= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_E));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MAC_ADDR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MAC_ADDR));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SC_STATE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_SC_STATE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] |= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] |= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION));
+ /* Copy the content to Regdata for lastRx information */
+ /* Length must include authenticator IE size */
+ pReg->LastRx.Length = Length;
+ NdisMoveMemory(pReg->LastRx.Data, precv, Length);
+ pData = pReg->LastRx.Data;
+
+ NdisZeroMemory(&pWscControl->WscPeerInfo, sizeof(WSC_PEER_DEV_INFO));
+
+ /* Start to process WSC IEs */
+ while (Length > 4)
+ {
+ WSC_IE TLV_Recv;
+ memcpy((UINT8 *)&TLV_Recv, pData, 4);
+ WscType = be2cpu16(TLV_Recv.Type);
+ WscLen = be2cpu16(TLV_Recv.Length);
+ pData += 4;
+ Length -= 4;
+
+ /* Parse M1 WSC type and store to RegData structure */
+ switch (WscType)
+ {
+ case WSC_ID_VERSION:
+ if(pReg->SelfInfo.Version != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
+ break;
+
+ case WSC_ID_MSG_TYPE:
+ if(WSC_ID_MESSAGE_M1 != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
+ break;
+
+ case WSC_ID_UUID_E:
+ NdisMoveMemory(pReg->PeerInfo.Uuid, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_E))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_E));
+ break;
+
+ case WSC_ID_MAC_ADDR:
+ NdisMoveMemory(pReg->PeerInfo.MacAddr, pData, WscLen);
+ NdisMoveMemory(pWscControl->WscPeerInfo.WscPeerMAC, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MAC_ADDR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MAC_ADDR));
+ break;
+
+ case WSC_ID_ENROLLEE_NONCE:
+ NdisMoveMemory(pReg->EnrolleeNonce, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
+ break;
+
+ case WSC_ID_PUBLIC_KEY:
+ /* Get Enrollee Public Key */
+ NdisMoveMemory(pReg->Pke, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY));
+ break;
+
+ case WSC_ID_AUTH_TYPE_FLAGS:
+ pReg->PeerInfo.AuthTypeFlags = *((PUSHORT) pData);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS));
+ break;
+
+ case WSC_ID_ENCR_TYPE_FLAGS:
+ pReg->PeerInfo.EncrTypeFlags = *((PUSHORT) pData);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS));
+ break;
+
+ case WSC_ID_CONN_TYPE_FLAGS:
+ pReg->PeerInfo.ConnTypeFlags = *pData;
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS));
+ break;
+
+ case WSC_ID_CONFIG_METHODS:
+ pReg->PeerInfo.ConfigMethods = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS));
+ break;
+
+ case WSC_ID_SC_STATE:
+ pReg->PeerInfo.ScState = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SC_STATE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_SC_STATE));
+ break;
+
+ case WSC_ID_MANUFACTURER:
+ NdisMoveMemory(&pReg->PeerInfo.Manufacturer, pData, WscLen);
+ NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerManufacturer, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER));
+ break;
+
+ case WSC_ID_MODEL_NAME:
+ NdisMoveMemory(&pReg->PeerInfo.ModelName, pData, WscLen);
+ NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelName, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME));
+ break;
+
+ case WSC_ID_MODEL_NUMBER:
+ NdisMoveMemory(&pReg->PeerInfo.ModelNumber, pData, WscLen);
+ NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelNumber, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER));
+ break;
+
+ case WSC_ID_SERIAL_NUM:
+ NdisMoveMemory(&pReg->PeerInfo.SerialNumber, pData, WscLen);
+ NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerSerialNumber, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM));
+ break;
+
+ case WSC_ID_PRIM_DEV_TYPE:
+ NdisMoveMemory(&pReg->PeerInfo.PriDeviceType, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE));
+ break;
+
+ case WSC_ID_DEVICE_NAME:
+ NdisMoveMemory(&pReg->PeerInfo.DeviceName, pData, WscLen);
+ NdisMoveMemory(pWscControl->WscPeerInfo.WscPeerDeviceName, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME));
+ break;
+
+ case WSC_ID_RF_BAND:
+ pReg->PeerInfo.RfBand = *pData;
+ /*if() ret = WSC_ERROR_CHAN24_NOT_SUPP; */
+ /*if() ret = WSC_ERROR_CHAN50_NOT_SUPP; */
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND));
+ break;
+
+ case WSC_ID_ASSOC_STATE:
+ pReg->PeerInfo.AssocState = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE));
+ break;
+
+ case WSC_ID_CONFIG_ERROR:
+ pReg->PeerInfo.ConfigError = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR));
+ break;
+
+ case WSC_ID_DEVICE_PWD_ID:
+ DBGPRINT(RT_DEBUG_TRACE, (" WPS Registrar DPID %04x\n",pReg->SelfInfo.DevPwdId));
+ if(WSC_DEVICEPWDID_DEFAULT == get_unaligned((PUSHORT) pData))/**(PUSHORT) pData) */
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Rx WPS DPID PIN\n"));
+ pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PIN);
+ }
+ else if(WSC_DEVICEPWDID_PUSH_BTN == get_unaligned((PUSHORT) pData))/**(PUSHORT) pData) */
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Rx WPS DPID PBC\n"));
+ pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PBC);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Rx WPS DPID unsupport\n"));
+ }
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID));
+ break;
+
+ case WSC_ID_OS_VERSION:
+ pReg->PeerInfo.OsVersion = get_unalignedlong((PULONG) pData);/**((PULONG) pData); */
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION));
+ break;
+
+ case WSC_ID_VENDOR_EXT:
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ UCHAR tmp_data_len = 0;
+ WscParseV2SubItem(WFA_EXT_ID_VERSION2, pData, WscLen, &pReg->PeerInfo.Version2, &tmp_data_len);
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM1 --> Version2 = %x\n", pReg->PeerInfo.Version2));
+ }
+#endif // WSC_V2_SUPPORT //
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM1 --> Unknown IE 0x%04x\n", WscType));
+ break;
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ Length -= WscLen;
+ }
+
+ if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] )
+ ret = WSC_ERROR_WANTING_FIELD;
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM1 : \n"));
+ return ret;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process WSC M2 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - rewrite buffer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after Rx M2
+ 1. Change the correct parameters
+ 2. Process M2
+
+ ========================================================================
+*/
+int ProcessMessageM2(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ IN VOID *precv,
+ IN INT Length,
+ IN UCHAR apidx,
+ OUT PWSC_REG_DATA pReg)
+{
+ int ret = WSC_ERROR_NO_ERROR;
+ INT HmacLen;
+ UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32];
+ UCHAR DHKey[32], KdkInput[38], KdfKey[80];
+ INT DH_Len;
+ PUCHAR pData = NULL;
+ USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0};
+ MAC_TABLE_ENTRY *pEntry = NULL;
+ UCHAR CurOpMode = 0xFF;
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ CurOpMode = AP_MODE;
+#endif /* CONFIG_AP_SUPPORT */
+
+
+ pReg->PeerInfo.Version2 = 0;
+
+ RTMPZeroMemory(KDK, 32);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_R))] |= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_R));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] |= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] |= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
+ /* Copy the content to Regdata for lastRx information */
+ /* Length must include authenticator IE size */
+ pReg->LastRx.Length = Length;
+ NdisMoveMemory(pReg->LastRx.Data, precv, Length);
+ pData = pReg->LastRx.Data;
+
+ pEntry = MacTableLookup(pAdapter, pReg->PeerInfo.MacAddr);
+
+ NdisZeroMemory(&pWscControl->WscPeerInfo, sizeof(WSC_PEER_DEV_INFO));
+
+ /* Start to process WSC IEs */
+ while (Length > 4)
+ {
+ WSC_IE TLV_Recv;
+ memcpy((UINT8 *)&TLV_Recv, pData, 4);
+ WscType = be2cpu16(TLV_Recv.Type);
+ WscLen = be2cpu16(TLV_Recv.Length);
+ pData += 4;
+ Length -= 4;
+
+ /* Parse M2 WSC type and store to RegData structure */
+ switch (WscType)
+ {
+ case WSC_ID_VERSION:
+ if(pReg->SelfInfo.Version != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
+ break;
+
+ case WSC_ID_MSG_TYPE:
+ if(WSC_ID_MESSAGE_M2 != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
+ break;
+
+ case WSC_ID_ENROLLEE_NONCE:
+ /* for verification with our enrollee nonce */
+ if (RTMPCompareMemory(pReg->SelfNonce, pData, WscLen) != 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Rx M2 Compare enrollee nonce mismatched \n"));
+ }
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
+ break;
+
+ case WSC_ID_REGISTRAR_NONCE:
+ NdisMoveMemory(pReg->RegistrarNonce, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE));
+ break;
+
+ case WSC_ID_UUID_R:
+ NdisMoveMemory(pReg->PeerInfo.Uuid, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_R))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_R));
+ break;
+
+ case WSC_ID_PUBLIC_KEY:
+ /* Get Registrar Public Key */
+ NdisMoveMemory(&pReg->Pkr, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY));
+ break;
+
+ case WSC_ID_AUTH_TYPE_FLAGS:
+ pReg->PeerInfo.AuthTypeFlags = get_unaligned((PUSHORT) pData);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS));
+ break;
+
+ case WSC_ID_ENCR_TYPE_FLAGS:
+ pReg->PeerInfo.EncrTypeFlags = get_unaligned((PUSHORT) pData);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS));
+ break;
+
+ case WSC_ID_CONN_TYPE_FLAGS:
+ pReg->PeerInfo.ConnTypeFlags = *pData;
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS));
+ break;
+
+ case WSC_ID_CONFIG_METHODS:
+ pReg->PeerInfo.ConfigMethods = get_unaligned((PUSHORT) pData);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS));
+ break;
+
+ case WSC_ID_MANUFACTURER:
+ NdisMoveMemory(&pReg->PeerInfo.Manufacturer, pData, WscLen);
+ NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerManufacturer, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER));
+ break;
+
+ case WSC_ID_MODEL_NAME:
+ NdisMoveMemory(&pReg->PeerInfo.ModelName, pData, WscLen);
+ NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelName, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME));
+ break;
+
+ case WSC_ID_MODEL_NUMBER:
+ NdisMoveMemory(&pReg->PeerInfo.ModelNumber, pData, WscLen);
+ NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelNumber, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER));
+ break;
+
+ case WSC_ID_SERIAL_NUM:
+ NdisMoveMemory(&pReg->PeerInfo.SerialNumber, pData, WscLen);
+ NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerSerialNumber, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM));
+ break;
+
+ case WSC_ID_PRIM_DEV_TYPE:
+ NdisMoveMemory(&pReg->PeerInfo.PriDeviceType, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE));
+ break;
+
+ case WSC_ID_DEVICE_NAME:
+ NdisMoveMemory(&pReg->PeerInfo.DeviceName, pData, WscLen);
+ NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerDeviceName, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME));
+ break;
+
+ case WSC_ID_RF_BAND:
+ pReg->PeerInfo.RfBand = *pData;
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND));
+ break;
+
+ case WSC_ID_ASSOC_STATE:
+ pReg->PeerInfo.AssocState = get_unaligned((PUSHORT) pData);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE));
+ break;
+
+ case WSC_ID_CONFIG_ERROR:
+ pReg->PeerInfo.ConfigError = get_unaligned((PUSHORT) pData);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR));
+ break;
+
+ case WSC_ID_DEVICE_PWD_ID:
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID));
+ break;
+
+ case WSC_ID_OS_VERSION:
+ pReg->PeerInfo.OsVersion = get_unalignedlong((PULONG) pData);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION));
+ break;
+
+ case WSC_ID_AUTHENTICATOR:
+ NdisMoveMemory(Hmac, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
+ break;
+
+ case WSC_ID_VENDOR_EXT:
+#ifdef WSC_V2_SUPPORT
+ if (pWscControl->WscV2Info.bEnableWpsV2)
+ {
+ UCHAR tmp_data_len = 0;
+ WscParseV2SubItem(WFA_EXT_ID_VERSION2, pData, WscLen, &pReg->PeerInfo.Version2, &tmp_data_len);
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 --> Version2 = %x\n", pReg->PeerInfo.Version2));
+ }
+#endif // WSC_V2_SUPPORT //
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 --> Unknown IE 0x%04x\n", WscType));
+ break;
+ }
+
+ NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerMAC, &pWscControl->RegData.PeerInfo.MacAddr, 6);
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ Length -= WscLen;
+ }
+
+
+ DH_Len = sizeof(pReg->SecretKey);
+ RT_DH_SecretKey_Generate (
+ pReg->Pkr, sizeof(pReg->Pkr),
+ WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE),
+ pReg->EnrolleeRandom, sizeof(pReg->EnrolleeRandom),
+ pReg->SecretKey, (UINT *) &DH_Len);
+
+ /* Compute the DHKey based on the DH secret */
+ RT_SHA256(&pReg->SecretKey[0], 192, &DHKey[0]);
+
+ /* Create KDK input data */
+ NdisMoveMemory(&KdkInput[0], pReg->SelfNonce, 16);
+
+ NdisMoveMemory(&KdkInput[16], pReg->SelfInfo.MacAddr, 6);
+
+ NdisMoveMemory(&KdkInput[22], pReg->RegistrarNonce, 16);
+
+ /* Generate the KDK */
+ RT_HMAC_SHA256(DHKey, 32, KdkInput, 38, KDK, SHA256_DIGEST_SIZE);
+
+ /* KDF */
+ WscDeriveKey(KDK, 32, Wsc_Personal_String, (sizeof(Wsc_Personal_String) - 1), KdfKey, 640);
+
+ /* Assign Key from KDF */
+ NdisMoveMemory(pReg->AuthKey, &KdfKey[0], 32);
+ NdisMoveMemory(pReg->KeyWrapKey, &KdfKey[32], 16);
+ NdisMoveMemory(pReg->Emsk, &KdfKey[48], 32);
+
+ /* Combine last TX & RX message contents and validate the HMAC */
+ /* We have to exclude last 12 bytes from last receive since it's authenticator value */
+ HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
+ if (pAdapter->pHmacData)
+ {
+ NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
+ NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
+ }
+
+ if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM2 --> HMAC not match\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
+ DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
+ ret = WSC_ERROR_HMAC_FAIL;
+ }
+
+ if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] )
+ ret = WSC_ERROR_WANTING_FIELD;
+
+/* out : */
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 : \n"));
+ return ret;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process WSC M2D Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - rewrite buffer
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after Rx M2D
+ 1. Change the correct parameters
+ 2. Process M2D
+
+ ========================================================================
+*/
+int ProcessMessageM2D(
+ IN PRTMP_ADAPTER pAdapter,
+ IN VOID *precv,
+ IN INT Length,
+ OUT PWSC_REG_DATA pReg)
+{
+ int ret = WSC_ERROR_NO_ERROR;
+ PUCHAR pData = NULL;
+ USHORT WscType, WscLen;
+
+ /* Copy the content to Regdata for lastRx information */
+ /* Length must include authenticator IE size */
+ pReg->LastRx.Length = Length;
+ NdisMoveMemory(pReg->LastRx.Data, precv, Length);
+ pData = pReg->LastRx.Data;
+
+ /* Start to process WSC IEs */
+ while (Length > 4)
+ {
+ WSC_IE TLV_Recv;
+ memcpy((UINT8 *)&TLV_Recv, pData, 4);
+ WscType = be2cpu16(TLV_Recv.Type);
+ WscLen = be2cpu16(TLV_Recv.Length);
+ pData += 4;
+ Length -= 4;
+
+ /* Parse M2 WSC type and store to RegData structure */
+ switch (WscType)
+ {
+ case WSC_ID_VERSION:
+ if(pReg->SelfInfo.Version != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
+ break;
+
+ case WSC_ID_MSG_TYPE:
+ if(WSC_ID_MESSAGE_M2D != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
+ break;
+
+ case WSC_ID_ENROLLEE_NONCE:
+ /* for verification with our enrollee nonce */
+ if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Rx M2 Compare enrollee nonce mismatched \n"));
+ }
+ break;
+
+ case WSC_ID_REGISTRAR_NONCE:
+ NdisMoveMemory(pReg->RegistrarNonce, pData, WscLen);
+ break;
+
+ case WSC_ID_UUID_R:
+ NdisMoveMemory(pReg->PeerInfo.Uuid, pData, WscLen);
+ break;
+
+ case WSC_ID_PUBLIC_KEY:
+ /* There shall be no Public transmitted in M2D */
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2D --> Receive WSC_ID_PUBLIC_KEY!! werid!\n"));
+ break;
+
+ case WSC_ID_AUTH_TYPE_FLAGS:
+ pReg->PeerInfo.AuthTypeFlags = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
+ break;
+
+ case WSC_ID_ENCR_TYPE_FLAGS:
+ pReg->PeerInfo.EncrTypeFlags = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
+ break;
+
+ case WSC_ID_CONN_TYPE_FLAGS:
+ pReg->PeerInfo.ConnTypeFlags = *pData;
+ break;
+
+ case WSC_ID_CONFIG_METHODS:
+ pReg->PeerInfo.ConfigMethods = be2cpu16(get_unaligned((PUSHORT) pData));/*be2cpu16(*((PUSHORT) pData)); */
+ break;
+
+ case WSC_ID_MANUFACTURER:
+ NdisMoveMemory(&pReg->PeerInfo.Manufacturer, pData, WscLen);
+ break;
+
+ case WSC_ID_MODEL_NAME:
+ NdisMoveMemory(&pReg->PeerInfo.ModelName, pData, WscLen);
+ break;
+
+ case WSC_ID_MODEL_NUMBER:
+ NdisMoveMemory(&pReg->PeerInfo.ModelNumber, pData, WscLen);
+ break;
+
+ case WSC_ID_SERIAL_NUM:
+ NdisMoveMemory(&pReg->PeerInfo.SerialNumber, pData, WscLen);
+ break;
+
+ case WSC_ID_PRIM_DEV_TYPE:
+ NdisMoveMemory(&pReg->PeerInfo.PriDeviceType, pData, WscLen);
+ break;
+
+ case WSC_ID_DEVICE_NAME:
+ NdisMoveMemory(&pReg->PeerInfo.DeviceName, pData, WscLen);
+ break;
+
+ case WSC_ID_RF_BAND:
+ pReg->PeerInfo.RfBand = *pData;
+ break;
+
+ case WSC_ID_ASSOC_STATE:
+ pReg->PeerInfo.AssocState = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
+ break;
+
+ case WSC_ID_CONFIG_ERROR:
+ pReg->PeerInfo.ConfigError = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
+ break;
+
+ case WSC_ID_DEVICE_PWD_ID:
+ break;
+
+ case WSC_ID_OS_VERSION:
+ pReg->PeerInfo.OsVersion = get_unalignedlong((PULONG)pData);
+ break;
+
+ case WSC_ID_AUTHENTICATOR:
+ /* No authenticator in M2D */
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2D --> Unknown IE 0x%04x\n", WscType));
+ break;
+
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ Length -= WscLen;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2D : \n"));
+ return ret;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process WSC M3 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - recv buffer
+ Length - recv Length
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after Rx M3
+ 1. Change the correct parameters
+ 2. Process M3
+
+ ========================================================================
+*/
+int ProcessMessageM3(
+ IN PRTMP_ADAPTER pAdapter,
+ IN VOID *precv,
+ IN INT Length,
+ OUT PWSC_REG_DATA pReg)
+{
+ int ret = WSC_ERROR_NO_ERROR;
+ INT HmacLen;
+ UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32];
+ PUCHAR pData = NULL;
+ USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0};
+
+ RTMPZeroMemory(KDK, 32);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH1))] |= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH1));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH2))] |= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH2));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
+
+ /* Copy the content to Regdata for lastRx information */
+ /* Length must include authenticator IE size */
+ pReg->LastRx.Length = Length;
+ NdisMoveMemory(pReg->LastRx.Data, precv, Length);
+ pData = pReg->LastRx.Data;
+
+ /* Start to process WSC IEs */
+ while (Length > 4)
+ {
+ WSC_IE TLV_Recv;
+ memcpy((UINT8 *)&TLV_Recv, pData, 4);
+ WscType = be2cpu16(TLV_Recv.Type);
+ WscLen = be2cpu16(TLV_Recv.Length);
+ pData += 4;
+ Length -= 4;
+
+ /* Parse M3 WSC type and store to RegData structure */
+ switch (WscType)
+ {
+ case WSC_ID_VERSION:
+ if(pReg->SelfInfo.Version != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
+ break;
+
+ case WSC_ID_MSG_TYPE:
+ if(WSC_ID_MESSAGE_M3 != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
+ break;
+
+ case WSC_ID_REGISTRAR_NONCE:
+ /* for verification with our Registrar nonce */
+ if (RTMPCompareMemory(pReg->RegistrarNonce, pData, WscLen) != 0)
+ DBGPRINT(RT_DEBUG_TRACE, ("Rx M3 Compare Registrar nonce mismatched \n"));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE));
+ break;
+
+ case WSC_ID_E_HASH1:
+ NdisMoveMemory(&pReg->EHash1[0], pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH1))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH1));
+ break;
+
+ case WSC_ID_E_HASH2:
+ NdisMoveMemory(&pReg->EHash2[0], pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH2))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH2));
+ break;
+
+ case WSC_ID_AUTHENTICATOR:
+ NdisMoveMemory(Hmac, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM3 --> Unknown IE 0x%04x\n", WscType));
+ break;
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ Length -= WscLen;
+ }
+
+ /* Combine last TX & RX message contents and validate the HMAC */
+ /* We have to exclude last 12 bytes from last receive since it's authenticator value */
+ HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
+ if (pAdapter->pHmacData)
+ {
+ NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
+ NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
+ }
+
+ if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM3 --> HMAC not match\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
+ DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
+ ret = WSC_ERROR_HMAC_FAIL;
+ }
+
+ if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] )
+ ret = WSC_ERROR_WANTING_FIELD;
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM3 : \n"));
+ return ret;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process WSC M4 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - recv buffer
+ Length - recv Length
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after Rx M4
+ 1. Change the correct parameters
+ 2. Process M4
+
+ ========================================================================
+*/
+int ProcessMessageM4(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ IN VOID *precv,
+ IN INT Length,
+ OUT PWSC_REG_DATA pReg)
+{
+ int ret = WSC_ERROR_NO_ERROR;
+ INT HmacLen;
+ UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32], RHash[32];
+ INT EncrLen;
+ PUCHAR pData = NULL;
+ UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */
+ UCHAR *pHash=NULL;/*Reuse IV_DecrData memory */
+ USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0};
+
+ RTMPZeroMemory(KDK, 32);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH1))] |= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH1));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH2))] |= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH2));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
+
+/* IV_DecrData = kmalloc(512, MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 512);
+ if(NULL == IV_DecrData)
+ {
+ ret = WSC_ERROR_CAN_NOT_ALLOCMEM;
+ return ret;
+ }
+ pHash = IV_DecrData;
+ /* Copy the content to Regdata for lastRx information */
+ /* Length must include authenticator IE size */
+ pReg->LastRx.Length = Length;
+ NdisMoveMemory(pReg->LastRx.Data, precv, Length);
+ pData = pReg->LastRx.Data;
+
+ /* Start to process WSC IEs */
+ while (Length > 4)
+ {
+ WSC_IE TLV_Recv;
+ memcpy((UINT8 *)&TLV_Recv, pData, 4);
+ WscType = be2cpu16(TLV_Recv.Type);
+ WscLen = be2cpu16(TLV_Recv.Length);
+ pData += 4;
+ Length -= 4;
+
+ /* Parse M2 WSC type and store to RegData structure */
+ switch (WscType)
+ {
+ case WSC_ID_VERSION:
+ if(pReg->SelfInfo.Version != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
+ break;
+
+ case WSC_ID_MSG_TYPE:
+ if(WSC_ID_MESSAGE_M4 != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
+ break;
+
+ case WSC_ID_ENROLLEE_NONCE:
+ /* for verification with our enrollee nonce */
+ if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0)
+ DBGPRINT(RT_DEBUG_TRACE, ("Rx M4 Compare enrollee nonce mismatched \n"));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
+ break;
+
+ case WSC_ID_R_HASH1:
+ NdisMoveMemory(&pReg->RHash1, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH1))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH1));
+ break;
+
+ case WSC_ID_R_HASH2:
+ NdisMoveMemory(&pReg->RHash2, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH2))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH2));
+ break;
+
+ case WSC_ID_ENCR_SETTINGS:
+ /* There shall have smoe kind of length check */
+ if (WscLen <= 16)
+ break;
+ if (WscLen > 512)
+ {
+ /* ApEncrSetting is not enough */
+ DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen));
+ break;
+ }
+ NdisMoveMemory(IV_DecrData, pData, WscLen);
+ EncrLen = sizeof(pReg->ApEncrSettings);
+ AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen);
+ DBGPRINT(RT_DEBUG_TRACE, ("M4 ApEncrSettings len = %d\n ", EncrLen));
+
+ /* Parse encryption settings */
+ WscParseEncrSettings(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS));
+ break;
+
+ case WSC_ID_AUTHENTICATOR:
+ NdisMoveMemory(Hmac, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM4 --> Unknown IE 0x%04x\n", WscType));
+ break;
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ Length -= WscLen;
+ }
+
+ /* Verify R-Hash1 */
+ /* Create input for R-Hash1 */
+ NdisMoveMemory(pHash, pReg->Rs1, 16);
+ NdisMoveMemory(pHash + 16, pReg->Psk1, 16);
+ NdisMoveMemory(pHash + 32, pReg->Pke, 192);
+ NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
+
+ /* Generate R-Hash1 */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, RHash, SHA256_DIGEST_SIZE);
+
+ if (RTMPCompareMemory(pReg->RHash1, RHash, 32) != 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM4 --> RHash1 not matched\n"));
+ ret = WSC_ERROR_DEV_PWD_AUTH_FAIL;
+ goto out;
+ }
+
+ /* Combine last TX & RX message contents and validate the HMAC */
+ /* We have to exclude last 12 bytes from last receive since it's authenticator value */
+ HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
+ if (pAdapter->pHmacData)
+ {
+ NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
+ NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
+ }
+
+ if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM4 --> HMAC not match\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
+ DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
+ ret = WSC_ERROR_HMAC_FAIL;
+ }
+
+ if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] )
+ ret = WSC_ERROR_WANTING_FIELD;
+out :
+ if(NULL != IV_DecrData)
+/* kfree(IV_DecrData); */
+ os_free_mem(NULL, IV_DecrData);
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM4 : \n"));
+ return ret;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process WSC M5 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - recv buffer
+ Length - recv Length
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after Rx M5
+ 1. Change the correct parameters
+ 2. Process M5
+
+ ========================================================================
+*/
+int ProcessMessageM5(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ IN VOID *precv,
+ IN INT Length,
+ OUT PWSC_REG_DATA pReg)
+{
+ int ret = WSC_ERROR_NO_ERROR;
+ INT HmacLen;
+ UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32], EHash[32];
+ INT EncrLen;
+ PUCHAR pData = NULL;
+ UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */
+ UCHAR *pHash=NULL;/*Reuse IV_DecrData memory */
+ USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0};
+
+ RTMPZeroMemory(KDK, 32);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
+
+/* IV_DecrData = kmalloc(512, MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 512);
+ if(NULL == IV_DecrData)
+ {
+ ret = WSC_ERROR_CAN_NOT_ALLOCMEM;
+ return ret;
+ }
+ pHash = IV_DecrData;
+ /* Copy the content to Regdata for lastRx information */
+ /* Length must include authenticator IE size */
+ pReg->LastRx.Length = Length;
+ NdisMoveMemory(pReg->LastRx.Data, precv, Length);
+ pData = pReg->LastRx.Data;
+
+ /* Start to process WSC IEs */
+ while (Length > 4)
+ {
+ WSC_IE TLV_Recv;
+ memcpy((UINT8 *)&TLV_Recv, pData, 4);
+ WscType = be2cpu16(TLV_Recv.Type);
+ WscLen = be2cpu16(TLV_Recv.Length);
+ pData += 4;
+ Length -= 4;
+
+ /* Parse M2 WSC type and store to RegData structure */
+ switch (WscType)
+ {
+ case WSC_ID_VERSION:
+ if(pReg->SelfInfo.Version != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
+ break;
+
+ case WSC_ID_MSG_TYPE:
+ if(WSC_ID_MESSAGE_M5 != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
+ break;
+
+ case WSC_ID_REGISTRAR_NONCE:
+ /* for verification with our Registrar nonce */
+ if (RTMPCompareMemory(pReg->RegistrarNonce, pData, WscLen) != 0)
+ DBGPRINT(RT_DEBUG_TRACE, ("Rx M5 Compare Registrar nonce mismatched \n"));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE));
+ break;
+
+ case WSC_ID_ENCR_SETTINGS:
+ /* There shall have smoe kind of length check */
+ if (WscLen <= 16)
+ break;
+ if (WscLen > 512)
+ {
+ /* ApEncrSetting is not enough */
+ DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen));
+ break;
+ }
+ NdisMoveMemory(IV_DecrData, pData, WscLen);
+ EncrLen = sizeof(pReg->ApEncrSettings);
+ AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen);
+ DBGPRINT(RT_DEBUG_TRACE, ("M5 ApEncrSettings len = %d\n ", EncrLen));
+
+ /* Parse encryption settings */
+ WscParseEncrSettings(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS));
+ break;
+
+ case WSC_ID_AUTHENTICATOR:
+ NdisMoveMemory(Hmac, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM4 --> Unknown IE 0x%04x\n", WscType));
+ break;
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ Length -= WscLen;
+ }
+
+ /* Combine last TX & RX message contents and validate the HMAC */
+ /* We have to exclude last 12 bytes from last receive since it's authenticator value */
+ HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
+ if (pAdapter->pHmacData)
+ {
+ NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
+ NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
+ }
+
+ /* Verify E-Hash1 */
+ /* Create input for E-Hash1 */
+ NdisMoveMemory(pHash, pReg->Es1, 16);
+ NdisMoveMemory(pHash + 16, pReg->Psk1, 16);
+ NdisMoveMemory(pHash + 32, pReg->Pke, 192);
+ NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
+
+ /* Generate E-Hash1 */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, EHash, SHA256_DIGEST_SIZE);
+
+ if (RTMPCompareMemory(pReg->EHash1, EHash, 32) != 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM5 --> EHash1 not matched\n"));
+ pReg->SelfInfo.ConfigError = WSC_ERROR_HASH_FAIL;
+ ret = WSC_ERROR_HASH_FAIL;
+ goto out;
+ }
+
+ if (pAdapter->pHmacData)
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
+
+ if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM5 --> HMAC not match\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
+ DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
+ ret = WSC_ERROR_HMAC_FAIL;
+ }
+ if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] )
+ ret = WSC_ERROR_WANTING_FIELD;
+out :
+ if(NULL != IV_DecrData)
+/* kfree(IV_DecrData); */
+ os_free_mem(NULL, IV_DecrData);
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM5 : \n"));
+ return ret;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process WSC M6 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - recv buffer
+ Length - recv Length
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after Rx M6
+ 1. Change the correct parameters
+ 2. Process M6
+
+ ========================================================================
+*/
+int ProcessMessageM6(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ IN VOID *precv,
+ IN INT Length,
+ OUT PWSC_REG_DATA pReg)
+{
+ int ret = WSC_ERROR_NO_ERROR;
+ INT HmacLen;
+ UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32], RHash[32];
+ INT EncrLen;
+ PUCHAR pData = NULL;
+ UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */
+ UCHAR *pHash=NULL;/*Reuse IV_DecrData memory */
+ USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0};
+
+ RTMPZeroMemory(KDK, 32);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
+
+/* IV_DecrData = kmalloc(512, MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 512);
+ if(NULL == IV_DecrData)
+ {
+ ret = WSC_ERROR_CAN_NOT_ALLOCMEM;
+ return ret;
+ }
+ pHash = IV_DecrData;
+ /* Copy the content to Regdata for lastRx information */
+ /* Length must include authenticator IE size */
+ pReg->LastRx.Length = Length;
+ NdisMoveMemory(pReg->LastRx.Data, precv, Length);
+ pData = pReg->LastRx.Data;
+
+ /* Start to process WSC IEs */
+ while (Length > 4)
+ {
+ WSC_IE TLV_Recv;
+ memcpy((UINT8 *)&TLV_Recv, pData, 4);
+ WscType = cpu2be16(TLV_Recv.Type);
+ WscLen = cpu2be16(TLV_Recv.Length);
+ pData += 4;
+ Length -= 4;
+
+ /* Parse M2 WSC type and store to RegData structure */
+ switch (WscType)
+ {
+ case WSC_ID_VERSION:
+ if(pReg->SelfInfo.Version != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
+ break;
+
+ case WSC_ID_MSG_TYPE:
+ if(WSC_ID_MESSAGE_M6 != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
+ break;
+
+ case WSC_ID_ENROLLEE_NONCE:
+ /* for verification with our enrollee nonce */
+ if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0)
+ DBGPRINT(RT_DEBUG_TRACE, ("Rx M6 Compare enrollee nonce mismatched \n"));
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
+ break;
+
+ case WSC_ID_ENCR_SETTINGS:
+ /* There shall have smoe kind of length check */
+ if (WscLen <= 16)
+ break;
+ if (WscLen > 512)
+ {
+ /* ApEncrSetting is not enough */
+ DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen));
+ break;
+ }
+ NdisMoveMemory(IV_DecrData, pData, WscLen);
+ EncrLen = sizeof(pReg->ApEncrSettings);
+ AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen);
+ DBGPRINT(RT_DEBUG_TRACE, ("M6 ApEncrSettings len = %d\n ", EncrLen));
+
+ /* Parse encryption settings */
+ WscParseEncrSettings(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS));
+ break;
+
+ case WSC_ID_AUTHENTICATOR:
+ NdisMoveMemory(Hmac, pData, WscLen);
+ FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM6 --> Unknown IE 0x%04x\n", WscType));
+ break;
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ Length -= WscLen;
+ }
+
+ /* Verify R-Hash2 */
+ /* Create input for R-Hash1 */
+ NdisMoveMemory(pHash, pReg->Rs2, 16);
+ NdisMoveMemory(pHash + 16, pReg->Psk2, 16);
+ NdisMoveMemory(pHash + 32, pReg->Pke, 192);
+ NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
+
+ /* Generate R-Hash2 */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, RHash, SHA256_DIGEST_SIZE);
+
+ if (RTMPCompareMemory(pReg->RHash2, RHash, 32) != 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM6 --> RHash2 not matched\n"));
+ ret = WSC_ERROR_DEV_PWD_AUTH_FAIL;
+ goto out;
+ }
+
+ /* Combine last TX & RX message contents and validate the HMAC */
+ /* We have to exclude last 12 bytes from last receive since it's authenticator value */
+ HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
+ if (pAdapter->pHmacData)
+ {
+ NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
+ NdisMoveMemory(pAdapter->pHmacData+ pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
+ }
+
+ if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM6 --> HMAC not match\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
+ DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
+ ret = WSC_ERROR_HMAC_FAIL;
+ }
+
+ if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] )
+ ret = WSC_ERROR_WANTING_FIELD;
+out:
+ if(NULL != IV_DecrData)
+/* kfree(IV_DecrData); */
+ os_free_mem(NULL, IV_DecrData);
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM6 : \n"));
+ return ret;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process WSC M7 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - recv buffer
+ Length - recv Length
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after Rx M7
+ 1. Change the correct parameters
+ 2. Process M7
+
+ ========================================================================
+*/
+int ProcessMessageM7(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ IN VOID *precv,
+ IN INT Length,
+ OUT PWSC_REG_DATA pReg)
+{
+ int ret = WSC_ERROR_NO_ERROR;
+ INT HmacLen;
+ UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32];
+ INT EncrLen;
+ PUCHAR pData = NULL;
+ USHORT WscType, WscLen;
+ UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */
+
+ RTMPZeroMemory(KDK, 32);
+/* IV_DecrData = kmalloc(1024, MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 1024);
+ if(NULL == IV_DecrData)
+ {
+ ret = WSC_ERROR_CAN_NOT_ALLOCMEM;
+ return ret;
+ }
+ /* Copy the content to Regdata for lastRx information */
+ /* Length must include authenticator IE size */
+ pReg->LastRx.Length = Length;
+ NdisMoveMemory(pReg->LastRx.Data, precv, Length);
+ pData = pReg->LastRx.Data;
+
+ /* Start to process WSC IEs */
+ while (Length > 4)
+ {
+ WSC_IE TLV_Recv;
+ memcpy((UINT8 *)&TLV_Recv, pData, 4);
+ WscType = be2cpu16(TLV_Recv.Type);
+ WscLen = be2cpu16(TLV_Recv.Length);
+ pData += 4;
+ Length -= 4;
+
+ /* Parse M2 WSC type and store to RegData structure */
+ switch (WscType)
+ {
+ case WSC_ID_VERSION:
+ if(pReg->SelfInfo.Version != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
+ break;
+
+ case WSC_ID_MSG_TYPE:
+ if(WSC_ID_MESSAGE_M7 != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
+ break;
+
+ case WSC_ID_REGISTRAR_NONCE:
+ /* for verification with our Registrar nonce */
+ if (RTMPCompareMemory(pReg->RegistrarNonce, pData, WscLen) != 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Rx M5 Compare Registrar nonce mismatched \n"));
+ }
+ break;
+
+ case WSC_ID_ENCR_SETTINGS:
+ /* There shall have smoe kind of length check */
+ if (WscLen <= 16)
+ break;
+ if (WscLen > 1024)
+ {
+ /* ApEncrSetting is not enough */
+ DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen));
+ break;
+ }
+ NdisMoveMemory(IV_DecrData, pData, WscLen);
+ EncrLen = sizeof(pReg->ApEncrSettings);
+ AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen);
+ DBGPRINT(RT_DEBUG_TRACE, ("M7 ApEncrSettings len = %d\n ", EncrLen));
+
+
+ /* Parse encryption settings */
+ WscParseEncrSettings(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl);
+
+ break;
+
+ case WSC_ID_AUTHENTICATOR:
+ NdisMoveMemory(Hmac, pData, WscLen);
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM7 --> Unknown IE 0x%04x\n", WscType));
+ break;
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ Length -= WscLen;
+ }
+
+ /* Combine last TX & RX message contents and validate the HMAC */
+ /* We have to exclude last 12 bytes from last receive since it's authenticator value */
+ HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
+ if (pAdapter->pHmacData)
+ {
+ NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
+ NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
+ }
+ if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM7 --> HMAC not match\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
+ DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
+ ret = WSC_ERROR_HMAC_FAIL;
+ }
+
+ if(NULL != IV_DecrData)
+/* kfree(IV_DecrData); */
+ os_free_mem(NULL, IV_DecrData);
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM7 : \n"));
+ return ret;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process WSC M8 Message
+
+ Arguments:
+ pAdapter - NIC Adapter pointer
+ pbuf - recv buffer
+ Length - recv Length
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Actions after Rx M8
+ 1. Change the correct parameters
+ 2. Process M8
+
+ ========================================================================
+*/
+int ProcessMessageM8(
+ IN PRTMP_ADAPTER pAdapter,
+ IN VOID *precv,
+ IN INT Length,
+ IN PWSC_CTRL pWscControl)
+{
+ int ret = WSC_ERROR_NO_ERROR;
+ INT HmacLen;
+ UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32];
+ INT EncrLen;
+ PUCHAR pData = NULL;
+ USHORT WscType, WscLen;
+ UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */
+ PWSC_REG_DATA pReg = &pWscControl->RegData;
+
+ RTMPZeroMemory(KDK, 32);
+/* IV_DecrData = kmalloc(1024, MEM_ALLOC_FLAG); */
+ os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 1024);
+ if(NULL == IV_DecrData)
+ {
+ ret = WSC_ERROR_CAN_NOT_ALLOCMEM;
+ return ret;
+ }
+ /* Copy the content to Regdata for lastRx information */
+ /* Length must include authenticator IE size */
+ pReg->LastRx.Length = Length;
+ NdisMoveMemory(pReg->LastRx.Data, precv, Length);
+ pData = pReg->LastRx.Data;
+
+ /* Start to process WSC IEs */
+ while (Length > 4)
+ {
+ WSC_IE TLV_Recv;
+ memcpy((UINT8 *)&TLV_Recv, pData, 4);
+ WscType = be2cpu16(TLV_Recv.Type);
+ WscLen = be2cpu16(TLV_Recv.Length);
+ pData += 4;
+ Length -= 4;
+
+ /* Parse M8 WSC type and store to RegData structure */
+ switch (WscType)
+ {
+ case WSC_ID_VERSION:
+ if(pReg->SelfInfo.Version != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
+ break;
+
+ case WSC_ID_MSG_TYPE:
+ if(WSC_ID_MESSAGE_M8 != *pData)
+ DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
+ break;
+
+ case WSC_ID_ENROLLEE_NONCE:
+ /* for verification with our enrollee nonce */
+ if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Rx M8 Compare enrollee nonce mismatched \n"));
+ }
+ break;
+
+ case WSC_ID_ENCR_SETTINGS:
+ /* There shall have smoe kind of length check */
+ if (WscLen <= 16)
+ break;
+ if (WscLen > 1024)
+ {
+ /* ApEncrSetting is not enough */
+ DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen));
+ break;
+ }
+ NdisMoveMemory(IV_DecrData, pData, WscLen);
+ EncrLen = sizeof(pReg->ApEncrSettings);
+ AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen);
+ DBGPRINT(RT_DEBUG_TRACE, ("M8 ApEncrSettings len = %d\n ", EncrLen));
+
+ /* Parse encryption settings */
+ if (WscProcessCredential(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl) == FALSE)
+ {
+ if(NULL != IV_DecrData)
+ os_free_mem(NULL, IV_DecrData);
+ return WSC_ERROR_SETUP_LOCKED;
+ }
+
+ break;
+
+ case WSC_ID_AUTHENTICATOR:
+ NdisMoveMemory(Hmac, pData, WscLen);
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM8 --> Unknown IE 0x%04x\n", WscType));
+ break;
+ }
+
+ /* Offset to net WSC Ie */
+ pData += WscLen;
+ Length -= WscLen;
+ }
+
+ /* Combine last TX & RX message contents and validate the HMAC */
+ /* We have to exclude last 12 bytes from last receive since it's authenticator value */
+ HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
+ if (pAdapter->pHmacData)
+ {
+ NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
+ NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
+
+ /* Validate HMAC, reuse KDK buffer */
+ RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
+ }
+ if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM8 --> HMAC not match\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
+ DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
+ ret = WSC_ERROR_HMAC_FAIL;
+ }
+
+ if(NULL != IV_DecrData)
+/* kfree(IV_DecrData); */
+ os_free_mem(NULL, IV_DecrData);
+ DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM8 : \n"));
+ return ret;
+}
+
+#endif /* WSC_INCLUDED */
+
diff --git a/cleopatre/devkit/mt7601udrv/common/wsc_ufd.c b/cleopatre/devkit/mt7601udrv/common/wsc_ufd.c
new file mode 100644
index 0000000000..6f50290593
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/wsc_ufd.c
@@ -0,0 +1,598 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2006, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ wsc_ufd.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+*/
+
+#include "rt_config.h"
+
+#ifdef WSC_INCLUDED
+
+static const STRING *XML_DECLARE_START = "<?xml";
+static const STRING *XML_DECLARE_END = "?>";
+static const STRING *XML_SSID_START = "<ssid";
+static const STRING *XML_SSID_END = "</ssid>";
+static const STRING *XML_AUTH_START = "<authentication>";
+static const STRING *XML_AUTH_END = "</authentication>";
+static const STRING *XML_ENCR_START = "<encryption>";
+static const STRING *XML_ENCR_END = "</encryption>";
+static const STRING *XML_KEY_START = "<networkKey";
+static const STRING *XML_KEY_END = "</networkKey>";
+static const STRING *XML_KEY_INDEX_START = "<keyIndex>";
+static const STRING *XML_KEY_INDEX_END = "</keyIndex>";
+
+static const STRING *XML_GUID_MARK = "CFG_GUID";
+static const STRING *XML_AP_GUID_MARK = "CFG_AP_GUID";
+static const STRING *XML_SSID_MARK = "CFG_SSID";
+static const STRING *XML_AUTH_MARK = "CFG_AUTH";
+static const STRING *XML_ENCR_MARK = "CFG_ENCR";
+static const STRING *XML_KEY_MARK = "CFG_KEY";
+
+static const STRING *XML_TEMPLATE =
+"<?xml version=\"1.0\"?>\n"
+"<wirelessProfile>\n"
+" <config>\n"
+" <configId>CFG_GUID"
+"</configId>\n"
+" <configAuthorId>CFG_AP_GUID"
+"</configAuthorId>\n"
+" <configAuthor>Ralink WPS AP</configAuthor>\n"
+" </config>\n"
+" <ssid xml:space=\"preserve\">CFG_SSID"
+"</ssid>\n"
+" <connectionType>ESS</connectionType>\n"
+" <channel2Dot4>0</channel2Dot4>\n"
+" <channel5Dot0>0</channel5Dot0>\n"
+" <primaryProfile>\n"
+" <authentication>CFG_AUTH"
+"</authentication>\n"
+" <encryption>CFG_ENCR"
+"</encryption>\n"
+" <networkKey xml:space=\"preserve\">CFG_KEY"
+"</networkKey>\n"
+" <keyProvidedAutomatically>0</keyProvidedAutomatically>\n"
+" <ieee802Dot1xEnabled>0</ieee802Dot1xEnabled>\n"
+" </primaryProfile>\n"
+"</wirelessProfile>\n";
+
+
+static struct {
+ PSTRING auth_str;
+ USHORT auth_type;
+} *PWSC_UFD_AUTH_TYPE, WSC_UFD_AUTH_TYPE[] = {
+ {"open", WSC_AUTHTYPE_OPEN},
+ {"shared", WSC_AUTHTYPE_SHARED},
+ {"WPA", WSC_AUTHTYPE_WPA},
+ {"WPA2", WSC_AUTHTYPE_WPA2},
+ {"WPAPSK", WSC_AUTHTYPE_WPAPSK},
+ {"WPA2PSK", WSC_AUTHTYPE_WPA2PSK},
+ {NULL,}
+};
+
+
+static struct {
+ PSTRING encr_str;
+ USHORT encr_type;
+} *PWSC_UFD_ENCR_TYPE, WSC_UFD_ENCR_TYPE[] = {
+ {"none", WSC_ENCRTYPE_NONE},
+ {"WEP", WSC_ENCRTYPE_WEP},
+ {"TKIP", WSC_ENCRTYPE_TKIP},
+ {"AES", WSC_ENCRTYPE_AES},
+ {NULL,}
+};
+
+
+BOOLEAN WscPassXmlDeclare(
+ INOUT STRING **pXmlData)
+{
+ STRING *ptr;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("======> WscPassXmlDeclare\n"));
+
+ ptr = rtstrstr(*pXmlData, (PSTRING)XML_DECLARE_START);
+ if (ptr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscPassXmlDeclare: missing XML Declare <?xml\n"));
+ return FALSE;
+ }
+
+ ptr = rtstrstr(*pXmlData, (PSTRING)XML_DECLARE_END);
+ if (ptr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("XML syntax error: missing XML Declare ?>\n"));
+ return FALSE;
+ }
+
+ (*pXmlData) = ptr + strlen(XML_DECLARE_END);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<====== WscPassXmlDeclare\n"));
+
+ return TRUE;
+}
+
+
+BOOLEAN WscGetXmlSSID(
+ IN STRING *pXmlData,
+ OUT NDIS_802_11_SSID *pSsid)
+{
+ STRING *ptr, *pBuffer = pXmlData;
+
+ ptr = rtstrstr(pBuffer, (PSTRING)XML_SSID_START);
+ if (ptr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlSSID: missing <ssid\n"));
+ return FALSE;
+ }
+
+ pBuffer = ptr + strlen(XML_SSID_START);
+
+ ptr = rtstrstr(pBuffer, ">");
+ if (ptr)
+ {
+ pBuffer = ptr + 1;
+ }
+
+ ptr = rtstrstr(pBuffer, (PSTRING)XML_SSID_END);
+ if (ptr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlSSID: missing </ssid>\n"));
+ return FALSE;
+ }
+
+ pSsid->SsidLength = (UINT)(ptr - pBuffer);
+ RTMPZeroMemory(pSsid->Ssid, NDIS_802_11_LENGTH_SSID);
+ if ((pSsid->SsidLength > 0) && (pSsid->SsidLength < 33))
+ {
+ RTMPMoveMemory(pSsid->Ssid, pBuffer, pSsid->SsidLength);
+ }
+ else
+ {
+ pSsid->SsidLength = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+BOOLEAN WscGetXmlAuth(
+ IN STRING *pXmlData,
+ OUT USHORT *pAuthType)
+{
+ STRING *ptr, *pBuffer = pXmlData;
+ STRING AuthStr[10] = {0};
+ UINT AuthStrLen = 0;
+
+ *pAuthType = 0;
+ ptr = rtstrstr(pBuffer, (PSTRING)XML_AUTH_START);
+ if (ptr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlAuth: missing %s\n", XML_AUTH_START));
+ return FALSE;
+ }
+
+ pBuffer = ptr + strlen(XML_AUTH_START);
+
+ ptr = rtstrstr(pBuffer, (PSTRING)XML_AUTH_END);
+ if (ptr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlAuth: missing %s\n", XML_AUTH_END));
+ return FALSE;
+ }
+
+ AuthStrLen = (UINT)(ptr - pBuffer);
+ if ((AuthStrLen > 0) && (AuthStrLen <= 10))
+ {
+ RTMPMoveMemory(AuthStr, pBuffer, AuthStrLen);
+
+ for (PWSC_UFD_AUTH_TYPE = WSC_UFD_AUTH_TYPE; PWSC_UFD_AUTH_TYPE->auth_str; PWSC_UFD_AUTH_TYPE++)
+ {
+ if (strcmp(AuthStr, PWSC_UFD_AUTH_TYPE->auth_str) == 0)
+ {
+ *pAuthType = PWSC_UFD_AUTH_TYPE->auth_type;
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+BOOLEAN WscGetXmlEncr(
+ IN STRING *pXmlData,
+ OUT USHORT *pEncrType)
+{
+ STRING *ptr, *pBuffer = pXmlData;
+ STRING EncrStr[10] = {0};
+ UINT EncrStrLen = 0;
+
+ *pEncrType = 0;
+ ptr = rtstrstr(pBuffer, (PSTRING)XML_ENCR_START);
+ if (ptr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlEncr: missing %s\n", XML_ENCR_START));
+ return FALSE;
+ }
+
+ pBuffer = ptr + strlen(XML_ENCR_START);
+
+ ptr = rtstrstr(pBuffer, (PSTRING)XML_ENCR_END);
+ if (ptr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlEncr: missing %s\n", XML_ENCR_END));
+ return FALSE;
+ }
+
+ EncrStrLen = (UINT)(ptr - pBuffer);
+ if ((EncrStrLen > 0) && (EncrStrLen <= 10))
+ {
+ RTMPMoveMemory(EncrStr, pBuffer, EncrStrLen);
+
+ for (PWSC_UFD_ENCR_TYPE = WSC_UFD_ENCR_TYPE; PWSC_UFD_ENCR_TYPE->encr_str; PWSC_UFD_ENCR_TYPE++)
+ {
+ if (strcmp(EncrStr, PWSC_UFD_ENCR_TYPE->encr_str) == 0)
+ {
+ *pEncrType = PWSC_UFD_ENCR_TYPE->encr_type;
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+BOOLEAN WscGetXmlKey(
+ IN STRING *pXmlData,
+ OUT UCHAR *pKey,
+ OUT USHORT *pKeyLen)
+{
+ STRING *ptr, *pBuffer = pXmlData;
+ UINT KeyLen = 0;
+
+ ptr = rtstrstr(pBuffer, (PSTRING)XML_KEY_START);
+ if (ptr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlKey: missing %s\n", XML_KEY_START));
+ return FALSE;
+ }
+
+ pBuffer = ptr + strlen(XML_KEY_START);
+
+ ptr = rtstrstr(pBuffer, ">");
+ if (ptr)
+ {
+ pBuffer = ptr + 1;
+ }
+
+ ptr = rtstrstr(pBuffer, (PSTRING)XML_KEY_END);
+ if (ptr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlKey: missing %s\n", XML_KEY_END));
+ return FALSE;
+ }
+
+ KeyLen = (UINT)(ptr - pBuffer);
+ if ((KeyLen >= 8) && (KeyLen <= 64))
+ {
+ RTMPMoveMemory(pKey, pBuffer, KeyLen);
+ *pKeyLen = KeyLen;
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+BOOLEAN WscGetXmlKeyIndex(
+ IN STRING *pXmlData,
+ OUT UCHAR *pKeyIndex)
+{
+ STRING *ptr, *pBuffer = pXmlData;
+
+ *pKeyIndex = 1;
+ ptr = rtstrstr(pBuffer, (PSTRING)XML_KEY_INDEX_START);
+ if (ptr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlKeyIndex: missing %s\n", XML_KEY_INDEX_START));
+ return FALSE;
+ }
+
+ pBuffer = ptr + strlen(XML_KEY_INDEX_START);
+
+ ptr = rtstrstr(pBuffer, (PSTRING)XML_KEY_INDEX_END);
+ if (ptr == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlKeyIndex: missing %s\n", XML_KEY_INDEX_END));
+ return FALSE;
+ }
+
+ *pKeyIndex = *(--ptr) - 0x30;
+
+ return TRUE;
+}
+
+
+
+BOOLEAN WscReadProfileFromUfdFile(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR ApIdx,
+ IN PSTRING pUfdFileName)
+{
+ PWSC_CREDENTIAL pCredential = &pAd->ApCfg.MBSSID[ApIdx].WscControl.WscProfile.Profile[0];
+ RTMP_OS_FS_INFO osFSInfo;
+ RTMP_OS_FD file_r;
+ ssize_t rv, fileLen = 0;
+ PSTRING pXmlData = NULL;
+ BOOLEAN RV = TRUE;
+
+ if (pUfdFileName == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> %s: pUfdFileName is NULL\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ RtmpOSFSInfoChange(&osFSInfo, TRUE);
+
+ file_r = RtmpOSFileOpen(pUfdFileName, O_RDONLY, 0);
+ if (IS_FILE_OPEN_ERR(file_r))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> %s: Error opening file %s\n", __FUNCTION__, pUfdFileName));
+ return FALSE;
+ }
+ else
+ {
+ char tempStr[64] = {0};
+ while((rv = RtmpOSFileRead(file_r, tempStr, 64)) > 0)
+ {
+ fileLen += rv;
+ }
+ os_alloc_mem(pAd, (UCHAR **)&pXmlData, fileLen+1);
+ if (pXmlData == NULL)
+ {
+ RtmpOSFileClose(file_r);
+ RtmpOSFSInfoChange(&osFSInfo, FALSE);
+ DBGPRINT(RT_DEBUG_TRACE, ("pXmlData kmalloc fail. (fileLen = %d)\n", fileLen));
+ return FALSE;
+ }
+ RTMPZeroMemory(pXmlData, fileLen+1);
+ RtmpOSFileSeek(file_r, 0);
+ rv = RtmpOSFileRead(file_r, (PSTRING)pXmlData, fileLen);
+ RtmpOSFileClose(file_r);
+ if (rv != fileLen)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSFileRead fail, fileLen = %d\n", fileLen));
+ RtmpOSFSInfoChange(&osFSInfo, FALSE);
+ goto ReadErr;
+ }
+ }
+
+ RtmpOSFSInfoChange(&osFSInfo, FALSE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscReadProfileFromUfdFile\n"));
+ if (WscPassXmlDeclare(&pXmlData))
+ {
+ if (WscGetXmlSSID(pXmlData, &pCredential->SSID))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("SSID = %s(%d)\n", pCredential->SSID.Ssid, pCredential->SSID.SsidLength));
+ }
+ else
+ {
+ RV = FALSE;
+ goto FreeXmlData;
+ }
+
+ if (WscGetXmlAuth(pXmlData, &pCredential->AuthType))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Credential.AuthType = 0x%04x\n", pCredential->AuthType));
+ }
+ else
+ {
+ RV = FALSE;
+ goto FreeXmlData;
+ }
+
+ if (WscGetXmlEncr(pXmlData, &pCredential->EncrType))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Credential.EncrType = 0x%04x\n", pCredential->EncrType));
+ }
+ else
+ {
+ RV = FALSE;
+ goto FreeXmlData;
+ }
+
+ pCredential->KeyLength = 0;
+ RTMPZeroMemory(pCredential->Key, 64);
+ if (WscGetXmlKey(pXmlData, pCredential->Key, &pCredential->KeyLength))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Credential.Key = %s (%d)\n", pCredential->Key, pCredential->KeyLength));
+ }
+ else
+ {
+ RV = FALSE;
+ goto FreeXmlData;
+ }
+
+ /*
+ If we cannot find keyIndex in .wfc file, use default value 1.
+ */
+ if (WscGetXmlKeyIndex(pXmlData, &pCredential->KeyIndex))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("pCredential->KeyIndex = %d\n", pCredential->KeyIndex));
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WscReadProfileFromUfdFile OK\n"));
+
+ WscWriteConfToPortCfg(pAd,
+ &pAd->ApCfg.MBSSID[ApIdx].WscControl,
+ &pAd->ApCfg.MBSSID[ApIdx].WscControl.WscProfile.Profile[0], TRUE);
+
+ pAd->WriteWscCfgToDatFile = ApIdx;
+
+ RtmpOsTaskWakeUp(&(pAd->wscTask));
+
+FreeXmlData:
+ if (pXmlData)
+ os_free_mem(NULL, pXmlData);
+
+ return RV;
+ }
+
+ReadErr:
+ if (pXmlData)
+ os_free_mem(NULL, pXmlData);
+ return FALSE;
+}
+
+
+BOOLEAN WscWriteProfileToUfdFile(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR ApIdx,
+ IN PSTRING pUfdFileName)
+{
+ PWSC_CTRL pWscControl = &pAd->ApCfg.MBSSID[ApIdx].WscControl;
+ PWSC_CREDENTIAL pCredential = &pWscControl->WscProfile.Profile[0];
+ RTMP_OS_FS_INFO osFSInfo;
+ RTMP_OS_FD file_w;
+ PSTRING offset, pXmlTemplate = (PSTRING)XML_TEMPLATE;
+ BOOLEAN bFound = FALSE, bRtn = TRUE;
+ UCHAR Guid[UUID_LEN_HEX];
+ UCHAR Guid_Str[UUID_LEN_STR];
+
+ if (pUfdFileName == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> %s: pUfdFileName is NULL\n", __FUNCTION__));
+ return FALSE;
+ }
+
+ RtmpOSFSInfoChange(&osFSInfo, TRUE);
+
+ file_w = RtmpOSFileOpen(pUfdFileName, O_WRONLY|O_TRUNC|O_CREAT, 0);
+ if (IS_FILE_OPEN_ERR(file_w))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> %s: Error opening file %s\n", __FUNCTION__, pUfdFileName));
+ return FALSE;
+ }
+ else
+ {
+ WscCreateProfileFromCfg(pAd, AP_MODE, pWscControl, &pWscControl->WscProfile);
+
+ WscGenerateUUID(pAd, &Guid[0], &Guid_Str[0], ApIdx, TRUE);
+
+ if ((offset = rtstrstr(pXmlTemplate, (PSTRING)XML_GUID_MARK)) != NULL)
+ {
+ RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)(offset - pXmlTemplate));
+ RtmpOSFileWrite(file_w, (PSTRING)&Guid_Str[0], (int)UUID_LEN_STR);
+ pXmlTemplate = offset + strlen(XML_GUID_MARK);
+ }
+
+ if ((offset = rtstrstr(pXmlTemplate, (PSTRING)XML_AP_GUID_MARK)) != NULL)
+ {
+ RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)(offset - pXmlTemplate));
+ RtmpOSFileWrite(file_w, (PSTRING)&pWscControl->Wsc_Uuid_Str[0], (int)UUID_LEN_STR);
+ pXmlTemplate = offset + strlen(XML_AP_GUID_MARK);
+ }
+ if ((offset = rtstrstr(pXmlTemplate, (PSTRING)XML_SSID_MARK)) != NULL)
+ {
+ RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)(offset - pXmlTemplate));
+ RtmpOSFileWrite(file_w, (PSTRING)&pCredential->SSID.Ssid[0], (int)pCredential->SSID.SsidLength);
+ pXmlTemplate = offset + strlen(XML_SSID_MARK);
+ }
+ if ((offset = rtstrstr(pXmlTemplate, (PSTRING)XML_AUTH_MARK)) != NULL)
+ {
+ RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)(offset - pXmlTemplate));
+ for (PWSC_UFD_AUTH_TYPE = WSC_UFD_AUTH_TYPE; PWSC_UFD_AUTH_TYPE->auth_str; PWSC_UFD_AUTH_TYPE++)
+ {
+ if (PWSC_UFD_AUTH_TYPE->auth_type == pCredential->AuthType)
+ {
+ RtmpOSFileWrite(file_w,
+ (PSTRING)PWSC_UFD_AUTH_TYPE->auth_str,
+ (int)strlen(PWSC_UFD_AUTH_TYPE->auth_str));
+ bFound = TRUE;
+ break;
+ }
+ }
+ pXmlTemplate = offset + strlen(XML_AUTH_MARK);
+ if (bFound == FALSE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> %s: Unknow Auth Type(=%x)\n", __FUNCTION__, pCredential->AuthType));
+ bRtn = FALSE;
+ goto out;
+ }
+ }
+ if ((offset = rtstrstr(pXmlTemplate, (PSTRING)XML_ENCR_MARK)) != NULL)
+ {
+ bFound = FALSE;
+ RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)(offset - pXmlTemplate));
+ for (PWSC_UFD_ENCR_TYPE = WSC_UFD_ENCR_TYPE; PWSC_UFD_ENCR_TYPE->encr_str; PWSC_UFD_ENCR_TYPE++)
+ {
+ if (PWSC_UFD_ENCR_TYPE->encr_type == pCredential->EncrType)
+ {
+ RtmpOSFileWrite(file_w,
+ (PSTRING)PWSC_UFD_ENCR_TYPE->encr_str,
+ (int)strlen(PWSC_UFD_ENCR_TYPE->encr_str));
+ bFound = TRUE;
+ }
+ }
+ pXmlTemplate = offset + strlen(XML_ENCR_MARK);
+ if (bFound == FALSE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> %s: Unknow Encr Type(=%x)\n", __FUNCTION__, pCredential->EncrType));
+ bRtn = FALSE;
+ goto out;
+ }
+ }
+ if ((offset = rtstrstr(pXmlTemplate, (PSTRING)XML_KEY_MARK)) != NULL)
+ {
+ if (pCredential->EncrType != WSC_ENCRTYPE_NONE)
+ {
+ RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)(offset - pXmlTemplate));
+ RtmpOSFileWrite(file_w,
+ (PSTRING)pCredential->Key,
+ (int)pCredential->KeyLength);
+ pXmlTemplate = offset + strlen(XML_KEY_MARK);
+ }
+ else
+ {
+ RtmpOSFileWrite(file_w, (PSTRING)XML_ENCR_END, (int)strlen(XML_ENCR_END));
+ RtmpOSFileWrite(file_w, (PSTRING)"\n", (int)1);
+ pXmlTemplate = offset + strlen(XML_KEY_MARK) + strlen(XML_KEY_END) + 1; /* 1: '\n' */
+ }
+ }
+ RtmpOSFileWrite(file_w, (PSTRING)pXmlTemplate, (int)strlen(pXmlTemplate));
+ }
+
+out:
+ RtmpOSFileClose(file_w);
+ RtmpOSFSInfoChange(&osFSInfo, FALSE);
+
+ return bRtn;
+}
+
+
+#endif /* WSC_INCLUDED */
diff --git a/cleopatre/devkit/mt7601udrv/common/wsc_v2.c b/cleopatre/devkit/mt7601udrv/common/wsc_v2.c
new file mode 100644
index 0000000000..8165dd7b04
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/common/wsc_v2.c
@@ -0,0 +1,408 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2006, Ralink Technology, Inc.
+ *
+ * All rights reserved. Ralink's source code is an unpublished work and the
+ * use of a copyright notice does not imply otherwise. This source code
+ * contains confidential trade secret material of Ralink Tech. Any attemp
+ * or participation in deciphering, decoding, reverse engineering or in any
+ * way altering the source code is stricitly prohibited, unless the prior
+ * written consent of Ralink Technology, Inc. is obtained.
+ ***************************************************************************
+
+ Module Name:
+ wsc_v2.c
+*/
+
+#include "rt_config.h"
+
+#ifdef WSC_V2_SUPPORT
+#include "wsc_tlv.h"
+
+BOOLEAN WscAppendV2SubItem(
+ IN UCHAR SubID,
+ IN PUCHAR pData,
+ IN UCHAR DataLen,
+ OUT PUCHAR pOutBuf,
+ OUT PUCHAR pOutBufLen);
+
+#ifdef CONFIG_AP_SUPPORT
+VOID WscOnOff(
+ IN PRTMP_ADAPTER pAd,
+ IN INT ApIdx,
+ IN BOOLEAN bOff)
+{
+ PWSC_V2_INFO pWpsV2Info = &pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscControl.WscV2Info;
+ if (bOff)
+ {
+ /*
+ AP must not support WEP in WPS V2
+ */
+ pWpsV2Info->bWpsEnable = FALSE;
+ pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscIEBeacon.ValueLen = 0;
+ pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscIEProbeResp.ValueLen = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("WscOnOff - OFF.\n"));
+ }
+ else
+ {
+ pWpsV2Info->bWpsEnable = TRUE;
+ if (pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscControl.WscConfMode != WSC_DISABLE)
+ {
+ INT IsAPConfigured;
+ IsAPConfigured = pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscControl.WscConfStatus;
+ WscBuildBeaconIE(pAd, IsAPConfigured, FALSE, 0, 0, (ApIdx & 0x0F), NULL, 0, AP_MODE);
+ WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, ApIdx, NULL, 0, AP_MODE);
+ DBGPRINT(RT_DEBUG_TRACE, ("WscOnOff - ON.\n"));
+ }
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("WscOnOff - bWpsEnable = %d\n", pWpsV2Info->bWpsEnable));
+}
+
+VOID WscAddEntryToAclList(
+ IN PRTMP_ADAPTER pAd,
+ IN INT ApIdx,
+ IN PUCHAR pMacAddr)
+{
+ PRT_802_11_ACL pACL = NULL;
+ INT i;
+ BOOLEAN bFound = FALSE;
+
+ pACL = &pAd->ApCfg.MBSSID[ApIdx].AccessControlList;
+
+ if ((pACL->Policy == 0) ||
+ (pACL->Policy == 2))
+ return;
+
+ if (pACL->Num >= (MAX_NUM_OF_ACL_LIST - 1))
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("The AccessControlList is full, and no more entry can join the list!\n"));
+ return;
+ }
+
+ for (i=0; i<pACL->Num; i++)
+ {
+ if (NdisEqualMemory(pACL->Entry[i].Addr, pMacAddr, MAC_ADDR_LEN))
+ bFound = TRUE;
+ }
+ if (bFound == FALSE)
+ {
+ NdisMoveMemory(pACL->Entry[i].Addr, pMacAddr, MAC_ADDR_LEN);
+ pACL->Num++;
+ }
+}
+
+VOID WscSetupLockTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext;
+ PRTMP_ADAPTER pAd = NULL;
+
+ if (pWscControl == NULL)
+ return;
+
+ pAd = (PRTMP_ADAPTER)pWscControl->pAd;
+
+ if (pAd == NULL)
+ return;
+
+ pWscControl->bSetupLock = FALSE;
+ pWscControl->WscSetupLockTimerRunning = FALSE;
+ pWscControl->PinAttackCount = 0;
+
+ WscBuildBeaconIE(pAd,
+ pWscControl->WscConfStatus,
+ FALSE,
+ 0,
+ 0,
+ (pWscControl->EntryIfIdx & 0xF),
+ NULL,
+ 0,
+ AP_MODE);
+ WscBuildProbeRespIE(pAd,
+ WSC_MSGTYPE_AP_WLAN_MGR,
+ pWscControl->WscConfStatus,
+ FALSE,
+ 0,
+ 0,
+ pWscControl->EntryIfIdx,
+ NULL,
+ 0,
+ AP_MODE);
+
+ APUpdateBeaconFrame(pAd, pWscControl->EntryIfIdx & 0x0F);
+ DBGPRINT(RT_DEBUG_TRACE, ("WscSetupLockTimeout!\n"));
+
+ return;
+}
+
+VOID WscCheckPinAttackCount(
+ IN PRTMP_ADAPTER pAd,
+ IN PWSC_CTRL pWscControl)
+{
+ BOOLEAN bCancelled;
+
+ if ((pWscControl->EntryIfIdx & MIN_NET_DEVICE_FOR_APCLI)
+ )
+ {
+ /*
+ APCLI and P2P CLI don't need to do PIN attack checking.
+ */
+ return;
+ }
+
+ /*
+ If a static PIN is used,
+ the AP must track multiple failed attempts to authenticate an external Registrar and then enter a lock-down state
+ (This state is signified by setting the attribute AP Setup Locked to TRUE).
+ After at most 10 failed, consecutive attempts, with no time limitation, from any number of external Registrars,
+ the AP shall revert to a locked down state, and the AP shall remain in the locked down state indefinitely
+ (i.e., until the user intervenes to unlock AP's PIN for use by external Registrars)
+ */
+ pWscControl->PinAttackCount++;
+ if (pWscControl->PinAttackCount >= pWscControl->MaxPinAttack)
+ {
+ pWscControl->bSetupLock = TRUE;
+ if (pWscControl->WscSetupLockTimerRunning)
+ {
+ RTMPCancelTimer(&pWscControl->WscSetupLockTimer, &bCancelled);
+ pWscControl->WscSetupLockTimerRunning = FALSE;
+ }
+
+ if (pWscControl->PinAttackCount < WSC_LOCK_FOREVER_PIN_ATTACK)
+ {
+ pWscControl->WscSetupLockTimerRunning = TRUE;
+ RTMPSetTimer(&pWscControl->WscSetupLockTimer, pWscControl->SetupLockTime*60*1000);
+ }
+ //pWscControl->PinAttackCount = 0;
+
+ WscBuildBeaconIE(pAd,
+ pWscControl->WscConfStatus,
+ FALSE,
+ 0,
+ 0,
+ (pWscControl->EntryIfIdx & 0xF),
+ NULL,
+ 0,
+ AP_MODE);
+ WscBuildProbeRespIE(pAd,
+ WSC_MSGTYPE_AP_WLAN_MGR,
+ pWscControl->WscConfStatus,
+ FALSE,
+ 0,
+ 0,
+ pWscControl->EntryIfIdx,
+ NULL,
+ 0,
+ AP_MODE);
+
+ APUpdateBeaconFrame(pAd, pWscControl->EntryIfIdx & 0x0F);
+ }
+}
+
+#endif /* CONFIG_AP_SUPPORT */
+
+/*
+ Vendor ID: 0x00372A
+ Subelements ID (one-octet)
+ Version2 0x00
+ AuthorizedMACs 0x01
+ Network Key Shareable 0x02
+ Request to Enroll 0x03
+ Settings Delay Time 0x04
+ Reserved for future use 0x05 to 0xFF
+ Length (one-octet) - number of octets in the payload of this subelment
+ Version2 1B
+ AuthorizedMACs <=30B
+ Network Key Shareable Bool
+ Request to Enroll Bool
+ Settings Delay Time 1B
+*/
+BOOLEAN WscGenV2Msg(
+ IN PWSC_CTRL pWpsCtrl,
+ IN BOOLEAN bSelRegistrar,
+ IN PUCHAR pAuthorizedMACs,
+ IN INT AuthorizedMACsLen,
+ OUT UCHAR **pOutBuf,
+ OUT INT *pOutBufLen)
+{
+ PUCHAR pWscV2Msg = NULL;
+ USHORT WscV2MsgLen = 0;
+ PWSC_REG_DATA pReg = &pWpsCtrl->RegData;
+ INT templen = 0;
+
+ os_alloc_mem(NULL, (UCHAR **)&pWscV2Msg, 128);
+ if (pWscV2Msg)
+ {
+ UCHAR TmpLen = 0;
+ pWscV2Msg[0] = 0x00;
+ pWscV2Msg[1] = 0x37;
+ pWscV2Msg[2] = 0x2A;
+
+ /* Version2 */
+ WscAppendV2SubItem(WFA_EXT_ID_VERSION2, &pReg->SelfInfo.Version2, 1, pWscV2Msg+3, &TmpLen);
+ WscV2MsgLen += (3 + (USHORT)TmpLen);
+
+ if (bSelRegistrar)
+ {
+ /*
+ Authorized MACs
+ Registrars (both internal and external) shall add the AuthorizedMACs subelement,
+ this applies to all Configuration Methods, including PIN, PBC and NFC.
+ */
+ if (pAuthorizedMACs)
+ {
+ WscAppendV2SubItem( WFA_EXT_ID_AUTHORIZEDMACS,
+ pAuthorizedMACs,
+ AuthorizedMACsLen,
+ pWscV2Msg+WscV2MsgLen,
+ &TmpLen );
+ WscV2MsgLen += (USHORT)TmpLen;
+ }
+ else
+ {
+ WscAppendV2SubItem( WFA_EXT_ID_AUTHORIZEDMACS,
+ BROADCAST_ADDR,
+ MAC_ADDR_LEN,
+ pWscV2Msg+WscV2MsgLen,
+ &TmpLen );
+ WscV2MsgLen += (USHORT)TmpLen;
+ }
+ }
+
+ templen = AppendWSCTLV(WSC_ID_VENDOR_EXT, (*pOutBuf), (UINT8 *)pWscV2Msg, WscV2MsgLen);
+ (*pOutBuf) += templen;
+ (*pOutBufLen) += templen;
+
+ os_free_mem(NULL, pWscV2Msg);
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOLEAN WscAppendV2SubItem(
+ IN UCHAR SubID,
+ IN PUCHAR pData,
+ IN UCHAR DataLen,
+ OUT PUCHAR pOutBuf,
+ OUT PUCHAR pOutBufLen)
+{
+ PUCHAR pBuf = NULL;
+ os_alloc_mem(NULL, &pBuf, DataLen + 10);
+ if (pBuf)
+ {
+ pBuf[0] = SubID;
+ pBuf[1] = DataLen;
+ NdisMoveMemory(pBuf+2, pData, DataLen);
+ *pOutBufLen = (DataLen + 2);
+ NdisMoveMemory(pOutBuf, pBuf, *pOutBufLen);
+ os_free_mem(NULL, pBuf);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOLEAN WscParseV2SubItem(
+ IN UCHAR SubID,
+ IN PUCHAR pData,
+ IN USHORT DataLen,
+ OUT PUCHAR pOutBuf,
+ OUT PUCHAR pOutBufLen)
+{
+ PEID_STRUCT pEid;
+ USHORT Length = 0;
+ pEid = (PEID_STRUCT) (pData + 3);
+ hex_dump("WscParseV2SubItem - pData", (pData+3), DataLen-3);
+ while ((Length + 2 + pEid->Len) <= (DataLen-3))
+ {
+ if (pEid->Eid == SubID)
+ {
+ *pOutBufLen = pEid->Len;
+ NdisMoveMemory(pOutBuf, &pEid->Octet[0], pEid->Len);
+ return TRUE;
+ }
+ Length = Length + 2 + pEid->Len;
+ pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+ }
+ return FALSE;
+}
+
+VOID WscSendEapFragAck(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ IN PMAC_TABLE_ENTRY pEntry)
+{
+ if (pEntry == NULL)
+ {
+ ASSERT(pEntry!=NULL);
+ return;
+ }
+ if (IS_ENTRY_CLIENT(pEntry))
+ {
+ pWscControl->bWscLastOne = TRUE;
+ if (pAdapter->OpMode == OPMODE_AP)
+ WscSendMessage(pAdapter, WSC_OPCODE_FRAG_ACK, NULL, 0, pWscControl, AP_MODE, EAP_CODE_REQ);
+ else
+ {
+ if (ADHOC_ON(pAdapter) && (pWscControl->WscConfMode == WSC_REGISTRAR))
+ WscSendMessage(pAdapter, WSC_OPCODE_FRAG_ACK, NULL, 0, pWscControl, STA_MODE, EAP_CODE_REQ);
+ else
+ WscSendMessage(pAdapter, WSC_OPCODE_FRAG_ACK, NULL, 0, pWscControl, STA_MODE, EAP_CODE_RSP);
+ }
+ }
+ else if (IS_ENTRY_APCLI(pEntry))
+ WscSendMessage(pAdapter, WSC_OPCODE_FRAG_ACK, NULL, 0, pWscControl, AP_CLIENT_MODE, EAP_CODE_REQ);
+}
+
+VOID WscSendEapFragData(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PWSC_CTRL pWscControl,
+ IN PMAC_TABLE_ENTRY pEntry)
+{
+ INT DataLen = 0;
+ PUCHAR pData = NULL;
+
+ if (pEntry == NULL)
+ {
+ ASSERT(pEntry!=NULL);
+ return;
+ }
+
+ pData = pWscControl->pWscCurBufIdx;
+ pWscControl->bWscLastOne = TRUE;
+ if (pWscControl->WscTxBufLen > pWscControl->WscFragSize)
+ {
+ pWscControl->bWscLastOne = FALSE;
+ DataLen = pWscControl->WscFragSize;
+ pWscControl->WscTxBufLen -= pWscControl->WscFragSize;
+ pWscControl->pWscCurBufIdx = (pWscControl->pWscCurBufIdx + pWscControl->WscFragSize);
+ }
+ else
+ {
+ DataLen = pWscControl->WscTxBufLen;
+ pWscControl->pWscCurBufIdx = NULL;
+ pWscControl->WscTxBufLen = 0;
+ }
+
+#ifdef CONFIG_AP_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
+ {
+ if (IS_ENTRY_APCLI(pEntry))
+ WscSendMessage(pAdapter, WSC_OPCODE_MSG, pData, DataLen, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP);
+ else
+ WscSendMessage(pAdapter, WSC_OPCODE_MSG, pData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ);
+ }
+#endif // CONFIG_AP_SUPPORT //
+
+}
+
+#endif /* WSC_V2_SUPPORT */
+