2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
31 Handle association related requests either from WSTA or from local MLME
35 -------- ---------- ----------------------------------------------
36 Jan Lee 2006 created for rt2860
39 #include "../rt_config.h"
43 static VOID
ReservedAction(
45 IN MLME_QUEUE_ELEM
*Elem
);
48 ==========================================================================
50 association state machine init, including state transition and timer init
52 S - pointer to the association state machine
54 The state machine looks like the following
57 MT2_MLME_DISASSOC_REQ mlme_disassoc_req_action
58 MT2_PEER_DISASSOC_REQ peer_disassoc_action
59 MT2_PEER_ASSOC_REQ drop
60 MT2_PEER_REASSOC_REQ drop
61 MT2_CLS3ERR cls3err_action
62 ==========================================================================
64 VOID
ActionStateMachineInit(
67 OUT STATE_MACHINE_FUNC Trans
[])
69 StateMachineInit(S
, (STATE_MACHINE_FUNC
*)Trans
, MAX_ACT_STATE
, MAX_ACT_MSG
, (STATE_MACHINE_FUNC
)Drop
, ACT_IDLE
, ACT_MACHINE_BASE
);
71 StateMachineSetAction(S
, ACT_IDLE
, MT2_PEER_SPECTRUM_CATE
, (STATE_MACHINE_FUNC
)PeerSpectrumAction
);
72 StateMachineSetAction(S
, ACT_IDLE
, MT2_PEER_QOS_CATE
, (STATE_MACHINE_FUNC
)PeerQOSAction
);
74 StateMachineSetAction(S
, ACT_IDLE
, MT2_PEER_DLS_CATE
, (STATE_MACHINE_FUNC
)ReservedAction
);
76 StateMachineSetAction(S
, ACT_IDLE
, MT2_PEER_BA_CATE
, (STATE_MACHINE_FUNC
)PeerBAAction
);
77 StateMachineSetAction(S
, ACT_IDLE
, MT2_PEER_HT_CATE
, (STATE_MACHINE_FUNC
)PeerHTAction
);
78 StateMachineSetAction(S
, ACT_IDLE
, MT2_MLME_ADD_BA_CATE
, (STATE_MACHINE_FUNC
)MlmeADDBAAction
);
79 StateMachineSetAction(S
, ACT_IDLE
, MT2_MLME_ORI_DELBA_CATE
, (STATE_MACHINE_FUNC
)MlmeDELBAAction
);
80 StateMachineSetAction(S
, ACT_IDLE
, MT2_MLME_REC_DELBA_CATE
, (STATE_MACHINE_FUNC
)MlmeDELBAAction
);
82 StateMachineSetAction(S
, ACT_IDLE
, MT2_PEER_PUBLIC_CATE
, (STATE_MACHINE_FUNC
)PeerPublicAction
);
83 StateMachineSetAction(S
, ACT_IDLE
, MT2_PEER_RM_CATE
, (STATE_MACHINE_FUNC
)PeerRMAction
);
85 StateMachineSetAction(S
, ACT_IDLE
, MT2_MLME_QOS_CATE
, (STATE_MACHINE_FUNC
)MlmeQOSAction
);
86 StateMachineSetAction(S
, ACT_IDLE
, MT2_MLME_DLS_CATE
, (STATE_MACHINE_FUNC
)MlmeDLSAction
);
87 StateMachineSetAction(S
, ACT_IDLE
, MT2_ACT_INVALID
, (STATE_MACHINE_FUNC
)MlmeInvalidAction
);
92 IN MLME_QUEUE_ELEM
*Elem
)
95 MLME_ADDBA_REQ_STRUCT
*pInfo
;
97 PUCHAR pOutBuffer
= NULL
;
100 FRAME_ADDBA_REQ Frame
;
102 BA_ORI_ENTRY
*pBAEntry
= NULL
;
104 pInfo
= (MLME_ADDBA_REQ_STRUCT
*)Elem
->Msg
;
105 NdisZeroMemory(&Frame
, sizeof(FRAME_ADDBA_REQ
));
107 if(MlmeAddBAReqSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
, Addr
))
109 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer
); //Get an unused nonpaged memory
110 if(NStatus
!= NDIS_STATUS_SUCCESS
)
112 DBGPRINT(RT_DEBUG_TRACE
,("BA - MlmeADDBAAction() allocate memory failed \n"));
116 Idx
= pAd
->MacTab
.Content
[pInfo
->Wcid
].BAOriWcidArray
[pInfo
->TID
];
119 MlmeFreeMemory(pAd
, pOutBuffer
);
120 DBGPRINT(RT_DEBUG_ERROR
,("BA - MlmeADDBAAction() can't find BAOriEntry \n"));
125 pBAEntry
=&pAd
->BATable
.BAOriEntry
[Idx
];
130 ActHeaderInit(pAd
, &Frame
.Hdr
, pInfo
->pAddr
, pAd
->CurrentAddress
, pAd
->CommonCfg
.Bssid
);
132 ActHeaderInit(pAd
, &Frame
.Hdr
, pAd
->CommonCfg
.Bssid
, pAd
->CurrentAddress
, pInfo
->pAddr
);
135 Frame
.Category
= CATEGORY_BA
;
136 Frame
.Action
= ADDBA_REQ
;
137 Frame
.BaParm
.AMSDUSupported
= 0;
138 Frame
.BaParm
.BAPolicy
= IMMED_BA
;
139 Frame
.BaParm
.TID
= pInfo
->TID
;
140 Frame
.BaParm
.BufSize
= pInfo
->BaBufSize
;
141 Frame
.Token
= pInfo
->Token
;
142 Frame
.TimeOutValue
= pInfo
->TimeOutValue
;
143 Frame
.BaStartSeq
.field
.FragNum
= 0;
144 Frame
.BaStartSeq
.field
.StartSeq
= pAd
->MacTab
.Content
[pInfo
->Wcid
].TxSeq
[pInfo
->TID
];
146 *(USHORT
*)(&Frame
.BaParm
) = cpu2le16(*(USHORT
*)(&Frame
.BaParm
));
147 Frame
.TimeOutValue
= cpu2le16(Frame
.TimeOutValue
);
148 Frame
.BaStartSeq
.word
= cpu2le16(Frame
.BaStartSeq
.word
);
150 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
151 sizeof(FRAME_ADDBA_REQ
), &Frame
,
153 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
154 MlmeFreeMemory(pAd
, pOutBuffer
);
156 DBGPRINT(RT_DEBUG_TRACE
, ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", Frame
.BaStartSeq
.field
.StartSeq
, FrameLen
, Frame
.BaParm
.BufSize
));
161 ==========================================================================
163 send DELBA and delete BaEntry if any
165 Elem - MLME message MLME_DELBA_REQ_STRUCT
167 IRQL = DISPATCH_LEVEL
169 ==========================================================================
171 VOID
MlmeDELBAAction(
172 IN PRTMP_ADAPTER pAd
,
173 IN MLME_QUEUE_ELEM
*Elem
)
175 MLME_DELBA_REQ_STRUCT
*pInfo
;
176 PUCHAR pOutBuffer
= NULL
;
177 PUCHAR pOutBuffer2
= NULL
;
180 FRAME_DELBA_REQ Frame
;
184 pInfo
= (MLME_DELBA_REQ_STRUCT
*)Elem
->Msg
;
185 // must send back DELBA
186 NdisZeroMemory(&Frame
, sizeof(FRAME_DELBA_REQ
));
187 DBGPRINT(RT_DEBUG_TRACE
, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo
->Initiator
));
189 if(MlmeDelBAReqSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
))
191 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer
); //Get an unused nonpaged memory
192 if(NStatus
!= NDIS_STATUS_SUCCESS
)
194 DBGPRINT(RT_DEBUG_ERROR
,("BA - MlmeDELBAAction() allocate memory failed 1. \n"));
198 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer2
); //Get an unused nonpaged memory
199 if(NStatus
!= NDIS_STATUS_SUCCESS
)
201 MlmeFreeMemory(pAd
, pOutBuffer
);
202 DBGPRINT(RT_DEBUG_ERROR
, ("BA - MlmeDELBAAction() allocate memory failed 2. \n"));
206 // SEND BAR (Send BAR to refresh peer reordering buffer.)
207 Idx
= pAd
->MacTab
.Content
[pInfo
->Wcid
].BAOriWcidArray
[pInfo
->TID
];
209 BarHeaderInit(pAd
, &FrameBar
, pAd
->MacTab
.Content
[pInfo
->Wcid
].Addr
, pAd
->CurrentAddress
);
211 FrameBar
.StartingSeq
.field
.FragNum
= 0; // make sure sequence not clear in DEL funciton.
212 FrameBar
.StartingSeq
.field
.StartSeq
= pAd
->MacTab
.Content
[pInfo
->Wcid
].TxSeq
[pInfo
->TID
]; // make sure sequence not clear in DEL funciton.
213 FrameBar
.BarControl
.TID
= pInfo
->TID
; // make sure sequence not clear in DEL funciton.
214 FrameBar
.BarControl
.ACKPolicy
= IMMED_BA
; // make sure sequence not clear in DEL funciton.
215 FrameBar
.BarControl
.Compressed
= 1; // make sure sequence not clear in DEL funciton.
216 FrameBar
.BarControl
.MTID
= 0; // make sure sequence not clear in DEL funciton.
218 MakeOutgoingFrame(pOutBuffer2
, &FrameLen
,
219 sizeof(FRAME_BAR
), &FrameBar
,
221 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer2
, FrameLen
);
222 MlmeFreeMemory(pAd
, pOutBuffer2
);
223 DBGPRINT(RT_DEBUG_TRACE
,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n"));
230 ActHeaderInit(pAd
, &Frame
.Hdr
, pAd
->MacTab
.Content
[pInfo
->Wcid
].Addr
, pAd
->CurrentAddress
, pAd
->CommonCfg
.Bssid
);
232 ActHeaderInit(pAd
, &Frame
.Hdr
, pAd
->CommonCfg
.Bssid
, pAd
->CurrentAddress
, pAd
->MacTab
.Content
[pInfo
->Wcid
].Addr
);
235 Frame
.Category
= CATEGORY_BA
;
236 Frame
.Action
= DELBA
;
237 Frame
.DelbaParm
.Initiator
= pInfo
->Initiator
;
238 Frame
.DelbaParm
.TID
= pInfo
->TID
;
239 Frame
.ReasonCode
= 39; // Time Out
240 *(USHORT
*)(&Frame
.DelbaParm
) = cpu2le16(*(USHORT
*)(&Frame
.DelbaParm
));
241 Frame
.ReasonCode
= cpu2le16(Frame
.ReasonCode
);
243 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
244 sizeof(FRAME_DELBA_REQ
), &Frame
,
246 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
247 MlmeFreeMemory(pAd
, pOutBuffer
);
248 DBGPRINT(RT_DEBUG_TRACE
, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo
->Initiator
));
253 IN PRTMP_ADAPTER pAd
,
254 IN MLME_QUEUE_ELEM
*Elem
)
259 IN PRTMP_ADAPTER pAd
,
260 IN MLME_QUEUE_ELEM
*Elem
)
264 VOID
MlmeInvalidAction(
265 IN PRTMP_ADAPTER pAd
,
266 IN MLME_QUEUE_ELEM
*Elem
)
268 //PUCHAR pOutBuffer = NULL;
269 //Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11
273 IN PRTMP_ADAPTER pAd
,
274 IN MLME_QUEUE_ELEM
*Elem
)
279 IN PRTMP_ADAPTER pAd
,
280 IN MLME_QUEUE_ELEM
*Elem
)
282 UCHAR Action
= Elem
->Msg
[LENGTH_802_11
+1];
287 PeerAddBAReqAction(pAd
,Elem
);
290 PeerAddBARspAction(pAd
,Elem
);
293 PeerDelBAAction(pAd
,Elem
);
298 VOID
PeerPublicAction(
299 IN PRTMP_ADAPTER pAd
,
300 IN MLME_QUEUE_ELEM
*Elem
)
302 if (Elem
->Wcid
>= MAX_LEN_OF_MAC_TABLE
)
307 static VOID
ReservedAction(
308 IN PRTMP_ADAPTER pAd
,
309 IN MLME_QUEUE_ELEM
*Elem
)
313 if (Elem
->MsgLen
<= LENGTH_802_11
)
318 Category
= Elem
->Msg
[LENGTH_802_11
];
319 DBGPRINT(RT_DEBUG_TRACE
,("Rcv reserved category(%d) Action Frame\n", Category
));
320 hex_dump("Reserved Action Frame", &Elem
->Msg
[0], Elem
->MsgLen
);
324 IN PRTMP_ADAPTER pAd
,
325 IN MLME_QUEUE_ELEM
*Elem
)
331 static VOID
respond_ht_information_exchange_action(
332 IN PRTMP_ADAPTER pAd
,
333 IN MLME_QUEUE_ELEM
*Elem
)
335 PUCHAR pOutBuffer
= NULL
;
338 FRAME_HT_INFO HTINFOframe
, *pFrame
;
342 // 2. Always send back ADDBA Response
343 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer
); //Get an unused nonpaged memory
345 if (NStatus
!= NDIS_STATUS_SUCCESS
)
347 DBGPRINT(RT_DEBUG_TRACE
,("ACTION - respond_ht_information_exchange_action() allocate memory failed \n"));
352 pFrame
= (FRAME_HT_INFO
*) &Elem
->Msg
[0];
353 pAddr
= pFrame
->Hdr
.Addr2
;
355 NdisZeroMemory(&HTINFOframe
, sizeof(FRAME_HT_INFO
));
356 // 2-1. Prepare ADDBA Response frame.
359 ActHeaderInit(pAd
, &HTINFOframe
.Hdr
, pAddr
, pAd
->CurrentAddress
, pAd
->CommonCfg
.Bssid
);
361 ActHeaderInit(pAd
, &HTINFOframe
.Hdr
, pAd
->CommonCfg
.Bssid
, pAd
->CurrentAddress
, pAddr
);
364 HTINFOframe
.Category
= CATEGORY_HT
;
365 HTINFOframe
.Action
= HT_INFO_EXCHANGE
;
366 HTINFOframe
.HT_Info
.Request
= 0;
367 HTINFOframe
.HT_Info
.Forty_MHz_Intolerant
= pAd
->CommonCfg
.HtCapability
.HtCapInfo
.Forty_Mhz_Intolerant
;
368 HTINFOframe
.HT_Info
.STA_Channel_Width
= pAd
->CommonCfg
.AddHTInfo
.AddHtInfo
.RecomWidth
;
370 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
371 sizeof(FRAME_HT_INFO
), &HTINFOframe
,
374 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
375 MlmeFreeMemory(pAd
, pOutBuffer
);
379 IN PRTMP_ADAPTER pAd
,
380 IN MLME_QUEUE_ELEM
*Elem
)
382 UCHAR Action
= Elem
->Msg
[LENGTH_802_11
+1];
384 if (Elem
->Wcid
>= MAX_LEN_OF_MAC_TABLE
)
389 case NOTIFY_BW_ACTION
:
390 DBGPRINT(RT_DEBUG_TRACE
,("ACTION - HT Notify Channel bandwidth action----> \n"));
392 if(pAd
->StaActive
.SupportedPhyInfo
.bHtEnable
== FALSE
)
394 // Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps
395 // sending BW_Notify Action frame, and cause us to linkup and linkdown.
396 // In legacy mode, don't need to parse HT action frame.
397 DBGPRINT(RT_DEBUG_TRACE
,("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n",
398 Elem
->Msg
[LENGTH_802_11
+2] ));
402 if (Elem
->Msg
[LENGTH_802_11
+2] == 0) // 7.4.8.2. if value is 1, keep the same as supported channel bandwidth.
403 pAd
->MacTab
.Content
[Elem
->Wcid
].HTPhyMode
.field
.BW
= 0;
408 DBGPRINT(RT_DEBUG_TRACE
,("ACTION - SMPS action----> \n"));
409 if (((Elem
->Msg
[LENGTH_802_11
+2]&0x1) == 0))
411 pAd
->MacTab
.Content
[Elem
->Wcid
].MmpsMode
= MMPS_ENABLE
;
413 else if (((Elem
->Msg
[LENGTH_802_11
+2]&0x2) == 0))
415 pAd
->MacTab
.Content
[Elem
->Wcid
].MmpsMode
= MMPS_STATIC
;
419 pAd
->MacTab
.Content
[Elem
->Wcid
].MmpsMode
= MMPS_DYNAMIC
;
422 DBGPRINT(RT_DEBUG_TRACE
,("Aid(%d) MIMO PS = %d\n", Elem
->Wcid
, pAd
->MacTab
.Content
[Elem
->Wcid
].MmpsMode
));
423 // rt2860c : add something for smps change.
428 case MIMO_CHA_MEASURE_ACTION
:
430 case HT_INFO_EXCHANGE
:
432 HT_INFORMATION_OCTET
*pHT_info
;
434 pHT_info
= (HT_INFORMATION_OCTET
*) &Elem
->Msg
[LENGTH_802_11
+2];
436 DBGPRINT(RT_DEBUG_TRACE
,("ACTION - HT Information Exchange action----> \n"));
437 if (pHT_info
->Request
)
439 respond_ht_information_exchange_action(pAd
, Elem
);
448 ==========================================================================
450 Retry sending ADDBA Reqest.
452 IRQL = DISPATCH_LEVEL
455 p8023Header: if this is already 802.3 format, p8023Header is NULL
457 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
458 FALSE , then continue indicaterx at this moment.
459 ==========================================================================
461 VOID
ORIBATimerTimeout(
462 IN PRTMP_ADAPTER pAd
)
464 MAC_TABLE_ENTRY
*pEntry
;
468 total
= pAd
->MacTab
.Size
* NUM_OF_TID
;
470 for (i
= 1; ((i
<MAX_LEN_OF_BA_ORI_TABLE
) && (total
> 0)) ; i
++)
472 if (pAd
->BATable
.BAOriEntry
[i
].ORI_BA_Status
== Originator_Done
)
474 pEntry
= &pAd
->MacTab
.Content
[pAd
->BATable
.BAOriEntry
[i
].Wcid
];
475 TID
= pAd
->BATable
.BAOriEntry
[i
].TID
;
477 ASSERT(pAd
->BATable
.BAOriEntry
[i
].Wcid
< MAX_LEN_OF_MAC_TABLE
);
485 IN PRTMP_ADAPTER pAd
,
486 IN MAC_TABLE_ENTRY
*pEntry
)
491 PUCHAR pOutBuffer
= NULL
;
495 BA_ORI_ENTRY
*pBAEntry
;
497 for (i
= 0; i
<NUM_OF_TID
; i
++)
499 idx
= pEntry
->BAOriWcidArray
[i
];
504 pBAEntry
= &pAd
->BATable
.BAOriEntry
[idx
];
506 if (pBAEntry
->ORI_BA_Status
== Originator_Done
)
510 ASSERT(pBAEntry
->Wcid
< MAX_LEN_OF_MAC_TABLE
);
512 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer
); //Get an unused nonpaged memory
513 if(NStatus
!= NDIS_STATUS_SUCCESS
)
515 DBGPRINT(RT_DEBUG_ERROR
,("BA - MlmeADDBAAction() allocate memory failed \n"));
519 Sequence
= pEntry
->TxSeq
[TID
];
521 BarHeaderInit(pAd
, &FrameBar
, pEntry
->Addr
, pAd
->CurrentAddress
);
523 FrameBar
.StartingSeq
.field
.FragNum
= 0; // make sure sequence not clear in DEL function.
524 FrameBar
.StartingSeq
.field
.StartSeq
= Sequence
; // make sure sequence not clear in DEL funciton.
525 FrameBar
.BarControl
.TID
= TID
; // make sure sequence not clear in DEL funciton.
527 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
528 sizeof(FRAME_BAR
), &FrameBar
,
531 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
533 MlmeFreeMemory(pAd
, pOutBuffer
);
539 IN PRTMP_ADAPTER pAd
,
540 IN OUT PHEADER_802_11 pHdr80211
,
545 NdisZeroMemory(pHdr80211
, sizeof(HEADER_802_11
));
546 pHdr80211
->FC
.Type
= BTYPE_MGMT
;
547 pHdr80211
->FC
.SubType
= SUBTYPE_ACTION
;
549 COPY_MAC_ADDR(pHdr80211
->Addr1
, Addr1
);
550 COPY_MAC_ADDR(pHdr80211
->Addr2
, Addr2
);
551 COPY_MAC_ADDR(pHdr80211
->Addr3
, Addr3
);
555 IN PRTMP_ADAPTER pAd
,
556 IN OUT PFRAME_BAR pCntlBar
,
560 NdisZeroMemory(pCntlBar
, sizeof(FRAME_BAR
));
561 pCntlBar
->FC
.Type
= BTYPE_CNTL
;
562 pCntlBar
->FC
.SubType
= SUBTYPE_BLOCK_ACK_REQ
;
563 pCntlBar
->BarControl
.MTID
= 0;
564 pCntlBar
->BarControl
.Compressed
= 1;
565 pCntlBar
->BarControl
.ACKPolicy
= 0;
568 pCntlBar
->Duration
= 16 + RTMPCalcDuration(pAd
, RATE_1
, sizeof(FRAME_BA
));
570 COPY_MAC_ADDR(pCntlBar
->Addr1
, pDA
);
571 COPY_MAC_ADDR(pCntlBar
->Addr2
, pSA
);
576 ==========================================================================
578 Insert Category and action code into the action frame.
581 1. frame buffer pointer.
583 3. category code of the frame.
584 4. action code of the frame.
587 ==========================================================================
590 IN PRTMP_ADAPTER pAd
,
591 OUT PUCHAR pFrameBuf
,
592 OUT PULONG pFrameLen
,
598 MakeOutgoingFrame( pFrameBuf
, &TempLen
,
603 *pFrameLen
= *pFrameLen
+ TempLen
;